< prev index next >

src/hotspot/share/classfile/javaClasses.cpp

Print this page
rev 54472 : 8221836: Avoid recalculating String.hash when zero
Reviewed-by: jrose, adinn
Contributed-by: peter.levart@gmail.com, claes.redestad@oracle.com

*** 158,167 **** --- 158,168 ---- compute_offset(dest_offset, ik, name, signature_symbol, is_static); } int java_lang_String::value_offset = 0; int java_lang_String::hash_offset = 0; + int java_lang_String::hashIsZero_offset = 0; int java_lang_String::coder_offset = 0; bool java_lang_String::initialized = false; bool java_lang_String::is_instance(oop obj) {
*** 177,187 **** compute_offset(offset, klass, name, vmSymbols::signature(), is_static) #define STRING_FIELDS_DO(macro) \ macro(value_offset, k, vmSymbols::value_name(), byte_array_signature, false); \ macro(hash_offset, k, "hash", int_signature, false); \ ! macro(coder_offset, k, "coder", byte_signature, false) void java_lang_String::compute_offsets() { if (initialized) { return; } --- 178,189 ---- compute_offset(offset, klass, name, vmSymbols::signature(), is_static) #define STRING_FIELDS_DO(macro) \ macro(value_offset, k, vmSymbols::value_name(), byte_array_signature, false); \ macro(hash_offset, k, "hash", int_signature, false); \ ! macro(hashIsZero_offset, k, "hashIsZero", bool_signature, false); \ ! macro(coder_offset, k, "coder", byte_signature, false); void java_lang_String::compute_offsets() { if (initialized) { return; }
*** 505,526 **** } return result; } unsigned int java_lang_String::hash_code(oop 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; - bool is_latin1 = java_lang_String::is_latin1(java_string); if (is_latin1) { ! return java_lang_String::hash_code(value->byte_at_addr(0), length); } else { ! return java_lang_String::hash_code(value->char_at_addr(0), length); } } 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, value); --- 507,548 ---- } return result; } unsigned int java_lang_String::hash_code(oop java_string) { + // The hash and hashIsZero fields are subject to a benign data race, + // making it crucial to ensure that any observable result of the + // calculation in this method stays correct under any possible read of + // these fields. Necessary restrictions to allow this to be correct + // without explicit memory fences or similar concurrency primitives is + // that we can ever only write to one of these two fields for a given + // String instance, and that the computation is idempotent and derived + // from immutable state + assert(initialized && (hash_offset > 0) && (hashIsZero_offset > 0), "Must be initialized"); + if (java_lang_String::hash_is_set(java_string)) { + return java_string->int_field(hash_offset); + } + typeArrayOop value = 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); + unsigned int hash = 0; + if (length > 0) { if (is_latin1) { ! hash = java_lang_String::hash_code(value->byte_at_addr(0), length); ! } else { ! hash = java_lang_String::hash_code(value->char_at_addr(0), length); ! } ! } ! ! if (hash != 0) { ! java_string->int_field_put(hash_offset, hash); } else { ! java_string->bool_field_put(hashIsZero_offset, true); } + return hash; } 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, value);
< prev index next >