mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-19 18:44:38 +02:00
8141132: JEP 254: Compact Strings
Adopt a more space-efficient internal representation for strings. Co-authored-by: Brent Christian <brent.christian@oracle.com> Co-authored-by: Vivek Deshpande <vivek.r.deshpande@intel.com> Co-authored-by: Charlie Hunt <charlie.hunt@oracle.com> Co-authored-by: Vladimir Kozlov <vladimir.kozlov@oracle.com> Co-authored-by: Roger Riggs <roger.riggs@oracle.com> Co-authored-by: Xueming Shen <xueming.shen@oracle.com> Co-authored-by: Aleksey Shipilev <aleksey.shipilev@oracle.com> Co-authored-by: Sandhya Viswanathan <sandhya.viswanathan@intel.com> Reviewed-by: alanb, bdelsart, coleenp, iklam, jiangli, jrose, kevinw, naoto, pliden, roland, smarks, twisti
This commit is contained in:
parent
4e24e2cc6c
commit
7af927f9c1
74 changed files with 4838 additions and 1683 deletions
|
@ -232,118 +232,6 @@ void LIR_Assembler::osr_entry() {
|
|||
}
|
||||
|
||||
|
||||
// Optimized Library calls
|
||||
// This is the fast version of java.lang.String.compare; it has not
|
||||
// OSR-entry and therefore, we generate a slow version for OSR's
|
||||
void LIR_Assembler::emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst, CodeEmitInfo* info) {
|
||||
Register str0 = left->as_register();
|
||||
Register str1 = right->as_register();
|
||||
|
||||
Label Ldone;
|
||||
|
||||
Register result = dst->as_register();
|
||||
{
|
||||
// Get a pointer to the first character of string0 in tmp0
|
||||
// and get string0.length() in str0
|
||||
// Get a pointer to the first character of string1 in tmp1
|
||||
// and get string1.length() in str1
|
||||
// Also, get string0.length()-string1.length() in
|
||||
// o7 and get the condition code set
|
||||
// Note: some instructions have been hoisted for better instruction scheduling
|
||||
|
||||
Register tmp0 = L0;
|
||||
Register tmp1 = L1;
|
||||
Register tmp2 = L2;
|
||||
|
||||
int value_offset = java_lang_String:: value_offset_in_bytes(); // char array
|
||||
if (java_lang_String::has_offset_field()) {
|
||||
int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
|
||||
int count_offset = java_lang_String:: count_offset_in_bytes();
|
||||
__ load_heap_oop(str0, value_offset, tmp0);
|
||||
__ ld(str0, offset_offset, tmp2);
|
||||
__ add(tmp0, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
|
||||
__ ld(str0, count_offset, str0);
|
||||
__ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
|
||||
} else {
|
||||
__ load_heap_oop(str0, value_offset, tmp1);
|
||||
__ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
|
||||
__ ld(tmp1, arrayOopDesc::length_offset_in_bytes(), str0);
|
||||
}
|
||||
|
||||
// str1 may be null
|
||||
add_debug_info_for_null_check_here(info);
|
||||
|
||||
if (java_lang_String::has_offset_field()) {
|
||||
int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
|
||||
int count_offset = java_lang_String:: count_offset_in_bytes();
|
||||
__ load_heap_oop(str1, value_offset, tmp1);
|
||||
__ add(tmp0, tmp2, tmp0);
|
||||
|
||||
__ ld(str1, offset_offset, tmp2);
|
||||
__ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
|
||||
__ ld(str1, count_offset, str1);
|
||||
__ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
|
||||
__ add(tmp1, tmp2, tmp1);
|
||||
} else {
|
||||
__ load_heap_oop(str1, value_offset, tmp2);
|
||||
__ add(tmp2, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
|
||||
__ ld(tmp2, arrayOopDesc::length_offset_in_bytes(), str1);
|
||||
}
|
||||
__ subcc(str0, str1, O7);
|
||||
}
|
||||
|
||||
{
|
||||
// Compute the minimum of the string lengths, scale it and store it in limit
|
||||
Register count0 = I0;
|
||||
Register count1 = I1;
|
||||
Register limit = L3;
|
||||
|
||||
Label Lskip;
|
||||
__ sll(count0, exact_log2(sizeof(jchar)), limit); // string0 is shorter
|
||||
__ br(Assembler::greater, true, Assembler::pt, Lskip);
|
||||
__ delayed()->sll(count1, exact_log2(sizeof(jchar)), limit); // string1 is shorter
|
||||
__ bind(Lskip);
|
||||
|
||||
// If either string is empty (or both of them) the result is the difference in lengths
|
||||
__ cmp(limit, 0);
|
||||
__ br(Assembler::equal, true, Assembler::pn, Ldone);
|
||||
__ delayed()->mov(O7, result); // result is difference in lengths
|
||||
}
|
||||
|
||||
{
|
||||
// Neither string is empty
|
||||
Label Lloop;
|
||||
|
||||
Register base0 = L0;
|
||||
Register base1 = L1;
|
||||
Register chr0 = I0;
|
||||
Register chr1 = I1;
|
||||
Register limit = L3;
|
||||
|
||||
// Shift base0 and base1 to the end of the arrays, negate limit
|
||||
__ add(base0, limit, base0);
|
||||
__ add(base1, limit, base1);
|
||||
__ neg(limit); // limit = -min{string0.length(), string1.length()}
|
||||
|
||||
__ lduh(base0, limit, chr0);
|
||||
__ bind(Lloop);
|
||||
__ lduh(base1, limit, chr1);
|
||||
__ subcc(chr0, chr1, chr0);
|
||||
__ br(Assembler::notZero, false, Assembler::pn, Ldone);
|
||||
assert(chr0 == result, "result must be pre-placed");
|
||||
__ delayed()->inccc(limit, sizeof(jchar));
|
||||
__ br(Assembler::notZero, true, Assembler::pt, Lloop);
|
||||
__ delayed()->lduh(base0, limit, chr0);
|
||||
}
|
||||
|
||||
// If strings are equal up to min length, return the length difference.
|
||||
__ mov(O7, result);
|
||||
|
||||
// Otherwise, return the difference between the first mismatched chars.
|
||||
__ bind(Ldone);
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
void LIR_Assembler::monitorexit(LIR_Opr obj_opr, LIR_Opr lock_opr, Register hdr, int monitor_no) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue