Skip to content

Commit 08f0243

Browse files
committed
hotspot: Enable j.l.String related intrinsics
equals: ([C[C)Z compareTo: ([B[B)I getChars: ([CII[CI)V indexOf: ([C[C)I indexOf: ([CI[CII)I indexOfChar: ([CIII)I
1 parent d3869ce commit 08f0243

File tree

5 files changed

+107
-0
lines changed

5 files changed

+107
-0
lines changed

src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3799,10 +3799,13 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2,
37993799
subl(result, cnt1);
38003800
jcc(Assembler::notZero, POP_LABEL);
38013801

3802+
#if HOTSPOT_TARGET_CLASSLIB != 8
38023803
if (ae == StrIntrinsicNode::UU) {
3804+
// LibraryCallKit::inline_string_compareTo() already generated char[] length
38033805
// Divide length by 2 to get number of chars
38043806
shrl(cnt2, 1);
38053807
}
3808+
#endif
38063809
cmpl(cnt2, 1);
38073810
jcc(Assembler::equal, LENGTH_DIFF_LABEL);
38083811

@@ -4084,10 +4087,13 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2,
40844087
// Strings are equal up to min length. Return the length difference.
40854088
bind(LENGTH_DIFF_LABEL);
40864089
pop(result);
4090+
#if HOTSPOT_TARGET_CLASSLIB != 8
40874091
if (ae == StrIntrinsicNode::UU) {
4092+
// LibraryCallKit::inline_string_compareTo() already generated char[] length
40884093
// Divide diff by 2 to get number of chars
40894094
sarl(result, 1);
40904095
}
4096+
#endif
40914097
jmpb(DONE_LABEL);
40924098

40934099
if (VM_Version::supports_avx512vlbw()) {

src/hotspot/share/classfile/vmIntrinsics.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,17 @@ class methodHandle;
131131
do_intrinsic(_putOrderedObject, sun_misc_Unsafe, putOrderedObject_name, putReference_signature, F_RN) \
132132
do_intrinsic(_putOrderedInt, sun_misc_Unsafe, putOrderedInt_name, putInt_signature, F_RN) \
133133
do_intrinsic(_putOrderedLong, sun_misc_Unsafe, putOrderedLong_name, putLong_signature, F_RN) \
134+
\
135+
do_intrinsic(_sgetChars, java_lang_String, getCharsU_name, sgetChars_signature, F_S) \
136+
do_signature(sgetChars_signature, "([CII[CI)V") \
137+
do_intrinsic(_sequals, java_lang_String, equals_name, equalsC_signature, F_S) \
138+
do_intrinsic(_scompareTo, java_lang_String, compareTo_name, scompareTo_indexOf_signature, F_S) \
139+
do_intrinsic(_sindexOf, java_lang_String, indexOf_name, scompareTo_indexOf_signature, F_S) \
140+
do_intrinsic(_sindexOfI, java_lang_String, indexOf_name, sindexOfI_signature, F_S) \
141+
do_intrinsic(_sindexOfChar, java_lang_String, indexOfChar_name, sindexOfChar_signature, F_S) \
142+
do_signature(scompareTo_indexOf_signature, "([C[C)I") \
143+
do_signature(sindexOfI_signature, "([CI[CII)I") \
144+
do_signature(sindexOfChar_signature, "([CIII)I") \
134145

135146
#else
136147
#define COMPAREANDSETINT compareAndSetInt_name

src/hotspot/share/opto/c2compiler.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,14 @@ bool C2Compiler::is_intrinsic_supported(vmIntrinsics::ID id) {
639639
case vmIntrinsics::_arraycopy:
640640
case vmIntrinsics::_arraySort:
641641
case vmIntrinsics::_arrayPartition:
642+
#if HOTSPOT_TARGET_CLASSLIB == 8
643+
case vmIntrinsics::_sgetChars:
644+
case vmIntrinsics::_sequals:
645+
case vmIntrinsics::_scompareTo:
646+
case vmIntrinsics::_sindexOf:
647+
case vmIntrinsics::_sindexOfI:
648+
case vmIntrinsics::_sindexOfChar:
649+
#else
642650
case vmIntrinsics::_indexOfL:
643651
case vmIntrinsics::_indexOfU:
644652
case vmIntrinsics::_indexOfUL:
@@ -647,6 +655,7 @@ bool C2Compiler::is_intrinsic_supported(vmIntrinsics::ID id) {
647655
case vmIntrinsics::_indexOfIUL:
648656
case vmIntrinsics::_indexOfU_char:
649657
case vmIntrinsics::_indexOfL_char:
658+
#endif
650659
case vmIntrinsics::_toBytesStringU:
651660
case vmIntrinsics::_getCharsStringU:
652661
case vmIntrinsics::_getCharStringU:

src/hotspot/share/opto/intrinsicnode.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,11 @@ class StrIntrinsicNode: public Node {
7575
}
7676

7777
virtual bool depends_only_on_test() const { return false; }
78+
#if HOTSPOT_TARGET_CLASSLIB == 8
79+
virtual const TypePtr* adr_type() const { return TypeAryPtr::CHARS; }
80+
#else
7881
virtual const TypePtr* adr_type() const { return TypeAryPtr::BYTES; }
82+
#endif
7983
virtual uint match_edge(uint idx) const;
8084
virtual uint ideal_reg() const { return Op_RegI; }
8185
virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);

src/hotspot/share/opto/library_call.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,15 @@ bool LibraryCallKit::try_to_inline(int predicate) {
293293
case vmIntrinsics::_compareToLU: return inline_string_compareTo(StrIntrinsicNode::LU);
294294
case vmIntrinsics::_compareToUL: return inline_string_compareTo(StrIntrinsicNode::UL);
295295

296+
#if HOTSPOT_TARGET_CLASSLIB == 8
297+
case vmIntrinsics::_sgetChars: return inline_string_getCharsU();
298+
// String.equals(), Arrays.equals() both are comparing char[], and have identical signature
299+
case vmIntrinsics::_sequals: return inline_array_equals(StrIntrinsicNode::UU);
300+
case vmIntrinsics::_scompareTo: return inline_string_compareTo(StrIntrinsicNode::UU);
301+
case vmIntrinsics::_sindexOf: return inline_string_indexOf(StrIntrinsicNode::UU);
302+
case vmIntrinsics::_sindexOfI: return inline_string_indexOfI(StrIntrinsicNode::UU);
303+
case vmIntrinsics::_sindexOfChar: return inline_string_indexOfChar(StrIntrinsicNode::U);
304+
#else
296305
case vmIntrinsics::_indexOfL: return inline_string_indexOf(StrIntrinsicNode::LL);
297306
case vmIntrinsics::_indexOfU: return inline_string_indexOf(StrIntrinsicNode::UU);
298307
case vmIntrinsics::_indexOfUL: return inline_string_indexOf(StrIntrinsicNode::UL);
@@ -301,6 +310,7 @@ bool LibraryCallKit::try_to_inline(int predicate) {
301310
case vmIntrinsics::_indexOfIUL: return inline_string_indexOfI(StrIntrinsicNode::UL);
302311
case vmIntrinsics::_indexOfU_char: return inline_string_indexOfChar(StrIntrinsicNode::U);
303312
case vmIntrinsics::_indexOfL_char: return inline_string_indexOfChar(StrIntrinsicNode::L);
313+
#endif
304314

305315
case vmIntrinsics::_equalsL: return inline_string_equals(StrIntrinsicNode::LL);
306316

@@ -949,10 +959,12 @@ void LibraryCallKit::generate_string_range_check(Node* array, Node* offset, Node
949959
}
950960
RegionNode* bailout = new RegionNode(1);
951961
record_for_igvn(bailout);
962+
#if HOTSPOT_TARGET_CLASSLIB != 8
952963
if (char_count) {
953964
// Convert char count to byte count
954965
count = _gvn.transform(new LShiftINode(count, intcon(1)));
955966
}
967+
#endif
956968

957969
// Offset and count must not be negative
958970
generate_negative_guard(offset, bailout);
@@ -1010,16 +1022,31 @@ Node* LibraryCallKit::generate_virtual_thread(Node* tls_output) {
10101022
// characters (depending on 'is_byte'). cnt1 and cnt2 are pointing to Int nodes
10111023
// containing the lengths of str1 and str2.
10121024
Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2, StrIntrinsicNode::ArgEnc ae) {
1025+
#if HOTSPOT_TARGET_CLASSLIB == 8
1026+
assert(!CompactStrings && ae == StrIntrinsicNode::UU, "classlib8 requires CHARS");
1027+
#endif
10131028
Node* result = nullptr;
10141029
switch (opcode) {
10151030
case Op_StrIndexOf:
1031+
#if HOTSPOT_TARGET_CLASSLIB == 8
1032+
result = new StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
1033+
str1_start, cnt1, str2_start, cnt2, ae);
1034+
#else
10161035
result = new StrIndexOfNode(control(), memory(TypeAryPtr::BYTES),
10171036
str1_start, cnt1, str2_start, cnt2, ae);
1037+
#endif
10181038
break;
10191039
case Op_StrComp:
1040+
#if HOTSPOT_TARGET_CLASSLIB == 8
1041+
result = new StrCompNode(control(), memory(TypeAryPtr::CHARS),
1042+
str1_start, cnt1, str2_start, cnt2, ae);
1043+
#else
10201044
result = new StrCompNode(control(), memory(TypeAryPtr::BYTES),
10211045
str1_start, cnt1, str2_start, cnt2, ae);
1046+
#endif
10221047
break;
1048+
// This call is made from StringLatin1.java/StringUTF16.java, which does not exist in cvm8,
1049+
// so no change is needed in this branch
10231050
case Op_StrEquals:
10241051
// We already know that cnt1 == cnt2 here (checked in 'inline_string_equals').
10251052
// Use the constant length if there is one because optimized match rule may exist.
@@ -1046,13 +1073,23 @@ bool LibraryCallKit::inline_string_compareTo(StrIntrinsicNode::ArgEnc ae) {
10461073
arg1 = must_be_not_null(arg1, true);
10471074
arg2 = must_be_not_null(arg2, true);
10481075

1076+
#if HOTSPOT_TARGET_CLASSLIB == 8
1077+
// Get start addr and length of first argument
1078+
Node* arg1_start = array_element_address(arg1, intcon(0), T_CHAR);
1079+
Node* arg1_cnt = load_array_length(arg1);
1080+
1081+
// Get start addr and length of second argument
1082+
Node* arg2_start = array_element_address(arg2, intcon(0), T_CHAR);
1083+
Node* arg2_cnt = load_array_length(arg2);
1084+
#else
10491085
// Get start addr and length of first argument
10501086
Node* arg1_start = array_element_address(arg1, intcon(0), T_BYTE);
10511087
Node* arg1_cnt = load_array_length(arg1);
10521088

10531089
// Get start addr and length of second argument
10541090
Node* arg2_start = array_element_address(arg2, intcon(0), T_BYTE);
10551091
Node* arg2_cnt = load_array_length(arg2);
1092+
#endif
10561093

10571094
Node* result = make_string_method_node(Op_StrComp, arg1_start, arg1_cnt, arg2_start, arg2_cnt, ae);
10581095
set_result(result);
@@ -1225,17 +1262,28 @@ bool LibraryCallKit::inline_string_indexOf(StrIntrinsicNode::ArgEnc ae) {
12251262
src = must_be_not_null(src, true);
12261263
tgt = must_be_not_null(tgt, true);
12271264

1265+
#if HOTSPOT_TARGET_CLASSLIB == 8
1266+
// Get start addr and length of source string
1267+
Node* src_start = array_element_address(src, intcon(0), T_CHAR);
1268+
Node* src_count = load_array_length(src);
1269+
1270+
// Get start addr and length of substring
1271+
Node* tgt_start = array_element_address(tgt, intcon(0), T_CHAR);
1272+
Node* tgt_count = load_array_length(tgt);
1273+
#else
12281274
// Get start addr and length of source string
12291275
Node* src_start = array_element_address(src, intcon(0), T_BYTE);
12301276
Node* src_count = load_array_length(src);
12311277

12321278
// Get start addr and length of substring
12331279
Node* tgt_start = array_element_address(tgt, intcon(0), T_BYTE);
12341280
Node* tgt_count = load_array_length(tgt);
1281+
#endif
12351282

12361283
Node* result = nullptr;
12371284
bool call_opt_stub = (StubRoutines::_string_indexof_array[ae] != nullptr);
12381285

1286+
#if HOTSPOT_TARGET_CLASSLIB != 8
12391287
if (ae == StrIntrinsicNode::UU || ae == StrIntrinsicNode::UL) {
12401288
// Divide src size by 2 if String is UTF16 encoded
12411289
src_count = _gvn.transform(new RShiftINode(src_count, intcon(1)));
@@ -1244,6 +1292,7 @@ bool LibraryCallKit::inline_string_indexOf(StrIntrinsicNode::ArgEnc ae) {
12441292
// Divide substring size by 2 if String is UTF16 encoded
12451293
tgt_count = _gvn.transform(new RShiftINode(tgt_count, intcon(1)));
12461294
}
1295+
#endif
12471296

12481297
if (call_opt_stub) {
12491298
Node* call = make_runtime_call(RC_LEAF, OptoRuntime::string_IndexOf_Type(),
@@ -1286,10 +1335,18 @@ bool LibraryCallKit::inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae) {
12861335
tgt = must_be_not_null(tgt, true);
12871336

12881337
// Multiply byte array index by 2 if String is UTF16 encoded
1338+
#if HOTSPOT_TARGET_CLASSLIB == 8
1339+
assert(!CompactStrings && ae == StrIntrinsicNode::UU, "classlib-8 requires T_CHAR");
1340+
Node* src_offset = from_index;
1341+
src_count = _gvn.transform(new SubINode(src_count, from_index));
1342+
Node* src_start = array_element_address(src, src_offset, T_CHAR);
1343+
Node* tgt_start = array_element_address(tgt, intcon(0), T_CHAR);
1344+
#else
12891345
Node* src_offset = (ae == StrIntrinsicNode::LL) ? from_index : _gvn.transform(new LShiftINode(from_index, intcon(1)));
12901346
src_count = _gvn.transform(new SubINode(src_count, from_index));
12911347
Node* src_start = array_element_address(src, src_offset, T_BYTE);
12921348
Node* tgt_start = array_element_address(tgt, intcon(0), T_BYTE);
1349+
#endif
12931350

12941351
// Range checks
12951352
generate_string_range_check(src, src_offset, src_count, ae != StrIntrinsicNode::LL);
@@ -1384,8 +1441,14 @@ bool LibraryCallKit::inline_string_indexOfChar(StrIntrinsicNode::ArgEnc ae) {
13841441

13851442
src = must_be_not_null(src, true);
13861443

1444+
#if HOTSPOT_TARGET_CLASSLIB == 8
1445+
assert(!CompactStrings && ae == StrIntrinsicNode::U, "classlib8 requires CHARS");
1446+
Node* src_offset = from_index;
1447+
Node* src_start = array_element_address(src, src_offset, T_CHAR);
1448+
#else
13871449
Node* src_offset = ae == StrIntrinsicNode::L ? from_index : _gvn.transform(new LShiftINode(from_index, intcon(1)));
13881450
Node* src_start = array_element_address(src, src_offset, T_BYTE);
1451+
#endif
13891452
Node* src_count = _gvn.transform(new SubINode(max, from_index));
13901453

13911454
// Range checks
@@ -1406,7 +1469,11 @@ bool LibraryCallKit::inline_string_indexOfChar(StrIntrinsicNode::ArgEnc ae) {
14061469
RegionNode* region = new RegionNode(3);
14071470
Node* phi = new PhiNode(region, TypeInt::INT);
14081471

1472+
#if HOTSPOT_TARGET_CLASSLIB == 8
1473+
Node* result = new StrIndexOfCharNode(control(), memory(TypeAryPtr::CHARS), src_start, src_count, int_ch, ae);
1474+
#else
14091475
Node* result = new StrIndexOfCharNode(control(), memory(TypeAryPtr::BYTES), src_start, src_count, int_ch, ae);
1476+
#endif
14101477
C->set_has_split_ifs(true); // Has chance for split-if optimization
14111478
_gvn.transform(result);
14121479

@@ -1651,7 +1718,9 @@ bool LibraryCallKit::inline_string_getCharsU() {
16511718

16521719
// Get length and convert char[] offset to byte[] offset
16531720
Node* length = _gvn.transform(new SubINode(src_end, src_begin));
1721+
#if HOTSPOT_TARGET_CLASSLIB != 8
16541722
src_begin = _gvn.transform(new LShiftINode(src_begin, intcon(1)));
1723+
#endif
16551724

16561725
// Range checks
16571726
generate_string_range_check(src, src_begin, length, true);
@@ -1662,13 +1731,21 @@ bool LibraryCallKit::inline_string_getCharsU() {
16621731

16631732
if (!stopped()) {
16641733
// Calculate starting addresses.
1734+
#if HOTSPOT_TARGET_CLASSLIB == 8
1735+
Node* src_start = array_element_address(src, src_begin, T_CHAR);
1736+
#else
16651737
Node* src_start = array_element_address(src, src_begin, T_BYTE);
1738+
#endif
16661739
Node* dst_start = array_element_address(dst, dst_begin, T_CHAR);
16671740

16681741
// Check if array addresses are aligned to HeapWordSize
16691742
const TypeInt* tsrc = gvn().type(src_begin)->is_int();
16701743
const TypeInt* tdst = gvn().type(dst_begin)->is_int();
1744+
#if HOTSPOT_TARGET_CLASSLIB == 8
1745+
bool aligned = tsrc->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_CHAR) + tsrc->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0) &&
1746+
#else
16711747
bool aligned = tsrc->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_BYTE) + tsrc->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0) &&
1748+
#endif
16721749
tdst->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_CHAR) + tdst->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0);
16731750

16741751
// Figure out which arraycopy runtime method to call (disjoint, uninitialized).

0 commit comments

Comments
 (0)