-
Notifications
You must be signed in to change notification settings - Fork 729
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Re-enable toLowerCase/toUpperCase acceleration #2098
Conversation
@fjeremic Could you please review this |
return output; | ||
int sLength = lengthInternal(); | ||
|
||
if (enableCompression && (null == compressionFlag || coder == LATIN1)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to refactor this code and avoid the duplicate if. Can we merge with the path below?
@@ -2720,9 +2720,17 @@ public String toLowerCase(Locale locale) { | |||
} | |||
|
|||
if (StrHWAvailable() && language == "en") { //$NON-NLS-1$ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are in this area of code can we rename this method here to something more sane and place it in the JitHelpers class with proper documentation? Perhaps supportsIntrinsicCaseConversion
or if you can think of a better name I'm fine with that?
|
||
if (enableCompression && (null == compressionFlag || coder == LATIN1)) { | ||
byte[] output = new byte[sLength]; | ||
if (toLowerHWOptimizedLatin1(value, output, sLength)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we can match the new name of the check and rename these accordingly to toLowerIntrinsicLatin1
/ toLowerIntrinsicUTF16
(similarly for toUpper
).
if (toLowerHWOptimizedLatin1(value, output, sLength)) | ||
return new String(output, LATIN1); | ||
} else { | ||
byte[] output = new byte[sLength * 2]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be factored out as sLength << coder
} else { | ||
byte[] output = new byte[sLength * 2]; | ||
if (toLowerHWOptimizedUTF16(value, output, sLength * 2)) | ||
return new String(output, UTF16); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's stay consistent with the rest of the codebase and add curly brackets around if blocks.
// DO NOT CHANGE CONTENTS OF THESE METHODS | ||
private final boolean toUpperHWOptimized(String input) { | ||
// DO NOT CHANGE THE CONTENTS OF THESE METHODS | ||
private final static boolean toUpperHWOptimizedLatin1(byte[] value, byte[] output, int length) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's move this guy to JitHelpers as well and fully document it. Similarly with others.
@@ -4569,6 +4593,21 @@ public String(char[] data, int start, int length) { | |||
} | |||
} | |||
|
|||
String(char[] data, int length, boolean compressed) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there is a need for this constructor to exist. Can we not just reuse the one below with length == 0
? These things would typically get inlined and the constant will be propagated thus ending up with the same implementation as you have here.
Depends on eclipse/omr#2650 |
Addressed your changes requested from 3fe5f89 in 5d7021f. |
case TR::java_lang_String_toLowerHWOptimizedLatin1: | ||
return TR::TreeEvaluator::compressedStringToLowerCaseEvaluator(node, cg); | ||
case TR::com_ibm_jit_JITHelpers_toUpperIntrinsicUTF16: | ||
return TR::TreeEvaluator::UTF16StringToUpperCaseEvaluator(node, cg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably rename these to toUpperIntrinsicUTF16Evaluator
for easier search ability. And of course use the same names on Z if needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would the name inlineToUpper
in Z be appropriate or should I change it to something like toUpperIntrinsic
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's go with toUpperIntrinsic
. By grepping for the Java method we should be able to find all related methods/functions in the VM/JIT as well. This is the intention.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed functions in x and z codegen in 5fd75e8.
* Boolean representing the string's compression | ||
* | ||
* \return | ||
* 0 if the conversion is unsuccessful, a non zero value otherwise |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not true. The function returns a register which represents the return value of the Java call. We need to JavaDoc the JIT helpers you added to define what the input parameters represent and what the return value represents. This Doxygen comment needs to be modified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added JavaDoc comments to JIT helper methods and fixed doxygen comment in 91004aa
TR::Instruction* instruction; | ||
|
||
const int elementSizeMask = (isCompressedString) ? 0x0 : 0x1; // byte or halfword mask | ||
const int sizeOfVector = 16; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We cast this variable to an int8_t
a little below. Are we able to avoid the cast by redefining the type at source?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
9b53d1e
const bool is64 = TR::Compiler->target.is64Bit(); | ||
uintptrj_t headerSize = TR::Compiler->om.contiguousArrayHeaderSizeInBytes(); | ||
|
||
TR::RegisterDependencyConditions * regDeps = new (cg->trHeapMemory()) TR::RegisterDependencyConditions(0, 14, cg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only count 13 dependencies below. Can we save some space?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
5143440
regDeps->addPostCondition(invalidRangeVector, TR::RealRegister::AssignAny); | ||
regDeps->addPostCondition(invalidCondVector, TR::RealRegister::AssignAny); | ||
|
||
if (is64){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Formatting of braces should be consistent with the rest of the codebase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
56171e1
// Check for strings lengths that are too big in 32bit | ||
if (!is64) | ||
{ | ||
generateRIInstruction(cg, TR::InstOpCode::TMLH, node, lengthRegister, (uint16_t) 0x8000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need a cast here? Also doesn't this check if lengthRegister < 0
. I don't think this is possible. Can you explain what this code is supposed to handle?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here there was some justification for this check. It does seem that this is checking for negative lengths, which would never happen so I don't see the need for this. I think this is dead code and can be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
d0a4635
|
||
generateRRInstruction(cg, TR::InstOpCode::LR, node, loadLength, lengthRegister); | ||
|
||
// Check for strings lengths that are too big in 32bit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the bitness of the JVM matters here. Couldn't the same problem happen on 64-bit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the same reasons as stated in the comment at Line 407, it seems this whole code block is unnecessary and can be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
d0a4635
generateVRSbInstruction(cg, TR::InstOpCode::VLL, node, charBufferVector, loadLength, generateS390MemoryReference(sourceRegister, addressOffset, headerSize, cg)); | ||
|
||
// Check for invalid characters, go to fallback individual character conversion implementation | ||
if(!isCompressedString) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consistency in space between if and parenthesis. Similarly elsewhere in the function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
56171e1
generateVRRcInstruction(cg, isToUpper ? TR::InstOpCode::VS : TR::InstOpCode::VA, node, modifiedCaseVector, charBufferVector, charOffsetVector, 0x0, 0x0, elementSizeMask); | ||
generateVRReInstruction(cg, TR::InstOpCode::VSEL, node, modifiedCaseVector, modifiedCaseVector, charBufferVector, selectionVector); | ||
|
||
instruction = generateVRSbInstruction(cg, TR::InstOpCode::VSTL, node, modifiedCaseVector, loadLength, generateS390MemoryReference(destRegister, addressOffset, headerSize, cg), 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to set instruction =
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4289d81
|
||
generateVRRdInstruction(cg, TR::InstOpCode::VSTRC, node, selectionVector, charBufferVector, alphaRangeVector, alphaCondVector, 0x4, elementSizeMask); | ||
generateVRRcInstruction(cg, isToUpper ? TR::InstOpCode::VS : TR::InstOpCode::VA, node, modifiedCaseVector, charBufferVector, charOffsetVector, 0x0, 0x0, elementSizeMask); | ||
instruction = generateVRReInstruction(cg, TR::InstOpCode::VSEL, node, modifiedCaseVector, modifiedCaseVector, charBufferVector, selectionVector); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to set instruction =
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4289d81
|
||
instruction=generateS390LabelInstruction(cg, TR::InstOpCode::LABEL, node, doneLabel); | ||
instruction->setEndInternalControlFlow(); | ||
instruction->setDependencyConditions(regDeps); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this line can be folded into the generateS390LabelInstruction
. There should be an overload accepting register dependencies.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
b796109
cg->generateDebugCounter(isToUpper? "z13/simd/toUpper/null" : "z13/simd/toLower/null", 1, TR::DebugCounter::Cheap); | ||
generateRRInstruction(cg, TR::InstOpCode::getXORRegOpCode(), node, destRegister, destRegister); | ||
|
||
instruction=generateS390LabelInstruction(cg, TR::InstOpCode::LABEL, node, doneLabel); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Formatting around =
needs to be fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
56171e1
|
// The index will begin at 0 and increment in multiples of 16 | ||
cursor = generateRXInstruction (cg, TR::InstOpCode::getLoadAddressOpCode(), node, rSrcVal, generateS390MemoryReference(rSrcVal, rResidue, 0, cg)); iComment("source.val += residue"); | ||
cursor = generateRXInstruction (cg, TR::InstOpCode::getLoadAddressOpCode(), node, rTgtVal, generateS390MemoryReference(rTgtVal, rResidue, 0 ,cg)); iComment("tgt.val += residue"); | ||
generateRIEInstruction(cg, is64 ? TR::InstOpCode::CGIJ : TR::InstOpCode::CIJ, node, lengthRegister, sizeOfVector, doneLabel, TR::InstOpCode::COND_BL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use TR::InstOpCode::getCmpImmBranchRelOpCode()
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3bf85b1
/* ===================== Step 4.0: Setup for core-loop =====================*/ | ||
// Increment index by the remainder then add 1, since the loadLength contains the highest index, we must go one past that | ||
generateRXInstruction(cg, TR::InstOpCode::getLoadAddressOpCode(), node, addressOffset, generateS390MemoryReference(addressOffset, loadLength, 0, cg)); | ||
generateRILInstruction(cg, is64 ? TR::InstOpCode::ALGFI : TR::InstOpCode::ALFI, node, addressOffset, 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we introduce a missing TR::InstOpCode
helper for this instruction pair?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[ 0x3ff87253590] LA GPR_0213,#676 0(GPR_0214,GPR_0213)
[ 0x3ff87253680] ALGFI GPR_0213,1
These two instructions can be fused by folding the ALGFI
into the memory reference displacement.
[ 0x3ff872548d0] XGR &GPR_0152,&GPR_0152
This looks incorrect. Are we using the second child as the return value register? If so that is a bug. Any register you get from an evaluation of a node cannot be clobbered. It must represent the value of the node it was evaluated from at the exit point of any evaluator. You need to allocate a new register for the return value or reuse an existing one. Perhaps can you check if we can use lengthRegister
for the return value since we already call gprClobberEvaluate
on it?
|
I don't think we need to depend on this. The |
@@ -54,9 +54,6 @@ private JITHelpers() { | |||
|
|||
@CallerSensitive | |||
public static JITHelpers getHelpers() { | |||
if (Reflection.getCallerClass().getClassLoader() != null) { | |||
throw new SecurityException("JITHelpers"); //$NON-NLS-1$ | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@andrewcraik wanted to point this one out to you. Is this safe? We need a handle to the JITHelpers object in Test_JITHelpers.java so we can do unit testing on the newly added APIs and have full control over expected inputs and outputs to test all corner cases. Unfortunately we cannot get a handle to the object without removing this or going the reflection route which seems a bit dodgy. Are you aware of any reason why this protection was put in place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this is here for the same reason sun.misc.Unsafe has the same kind of check - to dissuade others from getting the instance easily. Using a trick similar to unsafe to get hold of the instance in the tests would seem better to me than exposing the API in general.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, that makes sense. @dhong44 can you use a similar trick we use in String.java to get a hold of the JITHelpers object and revert the above deleted lines?
|
||
if (enableCompression && (null == compressionFlag || coder == LATIN1)) { | ||
|
||
if (helpers.supportsIntrinsicCaseConversion() && language == "en") { //$NON-NLS-1$ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The interpreter will never execute this code which means it will appear as a cold path due to no interpreter profiling data. Does the intrinsic recognition overcome this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe so. The interpreter will enter the if block immediately above on line 2728 so we will have profiling data for that path. The JIT will fold away the call to helpers.supportsIntrinsicCaseConversion()
as a constant at compile time and the flow algorithm in the JIT should propagate the block frequencies to the if at line 2725 to be equal to that of the preceding if.
Just to be cautious though @dhong44 can we collect a log and verify the block frequencies we compute for the block in which we inline the intrinsic? Given your expertise @andrewcraik is my reasoning here valid?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The key question is when the supportsIntrinsicCaseConversion is folded. It looks to be in ilgen so the flow for IProfiling will have a chance to happen - other profilers do not do a flow. The key thing is to check the frequency on the blocks with the custom implementation after cold block marking. I think a log is the best way to verify this is working right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
n1398n BBStart <block_125> (freq 5002) [ 0x3ff4315a4b0] bci=[10,116,2664] rc=0 vc=257 vn=- li=- udi=- nc=0
n1432n treetop [ 0x3ff4315af50] bci=[10,122,2664] rc=0 vc=257 vn=- li=- udi=- nc=1
n1431n newarray jitNewArray[#176 helper Method] [flags 0x400 0x0 ] (skipZeroInit sharedMemory ) [ 0x3ff4315af00] bci=[10,122,2664] rc=2 vc=257 vn=- li=- udi=- nc=2 flg=0x8000
n1429n ishl [ 0x3ff4315ae60] bci=[10,121,2664] rc=1 vc=257 vn=- li=- udi=- nc=2
n1426n iload <auto slot 3>[#796 Auto] [flags 0x3 0x0 ] [ 0x3ff4315ad70] bci=[10,116,2664] rc=1 vc=257 vn=- li=- udi=- nc=0
n1428n iloadi java/lang/String.coder B[#802 final Shadow +8] [flags 0xa0601 0x0 ] [ 0x3ff4315ae10] bci=[10,118,2664] rc=1 vc=257 vn=- li=- udi=- nc=1
n1427n aload <temp slot 3>[#786 Auto] [flags 0x7 0x0 ] (X!=0 sharedMemory ) [ 0x3ff4315adc0] bci=[10,117,2664] rc=1 vc=257 vn=- li=- udi=- nc=0 flg=0x4
n1430n iconst 8 ; array type is byte [ 0x3ff4315aeb0] bci=[10,122,2664] rc=1 vc=257 vn=- li=- udi=- nc=0
n1433n astore <auto slot 4>[#810 Auto] [flags 0x7 0x0 ] [ 0x3ff4315afa0] bci=[10,124,2664] rc=0 vc=257 vn=- li=- udi=- nc=1
n1431n ==>newarray
n1438n compressedRefs [ 0x3ff4315b130] bci=[10,130,2666] rc=0 vc=257 vn=- li=- udi=- nc=2
n1436n aloadi java/lang/String.value [B[#804 final Shadow +4] [flags 0x400a0607 0x0 ] [ 0x3ff4315b090] bci=[10,130,2666] rc=2 vc=257 vn=- li=- udi=- nc=1
n1435n aload <temp slot 3>[#786 Auto] [flags 0x7 0x0 ] (X!=0 sharedMemory ) [ 0x3ff4315b040] bci=[10,129,2666] rc=1 vc=257 vn=- li=- udi=- nc=0 flg=0x4
n1437n lconst 0 [ 0x3ff4315b0e0] bci=[10,130,2666] rc=1 vc=257 vn=- li=- udi=- nc=0
n1444n NULLCHK on n1434n [#30] [ 0x3ff4315b310] bci=[10,138,2666] rc=0 vc=257 vn=- li=- udi=- nc=1
n1443n icall com/ibm/jit/JITHelpers.toLowerIntrinsicUTF16([B[BI)Z[#815 final virtual Method -136] [flags 0x20500 0x0 ] () [ 0x3ff4315b2c0] bci=[10,138,2666] rc=3 vc=257 vn=- li=- udi=- nc=4 flg=0x20
n1434n aload java/lang/String.helpers Lcom/ibm/jit/JITHelpers;[#799 final Static] [flags 0xa0307 0x0 ] [ 0x3ff4315aff0] bci=[10,126,2666] rc=1 vc=257 vn=- li=- udi=- nc=0
n1436n ==>aloadi
n1439n aload <auto slot 4>[#810 Auto] [flags 0x7 0x0 ] [ 0x3ff4315b180] bci=[10,133,2666] rc=1 vc=257 vn=- li=- udi=- nc=0
n1442n imul [ 0x3ff4315b270] bci=[10,137,2666] rc=1 vc=257 vn=- li=- udi=- nc=2
n1440n iload <auto slot 3>[#796 Auto] [flags 0x3 0x0 ] [ 0x3ff4315b1d0] bci=[10,135,2666] rc=1 vc=257 vn=- li=- udi=- nc=0
n1441n iconst 2 [ 0x3ff4315b220] bci=[10,136,2666] rc=1 vc=257 vn=- li=- udi=- nc=0
n1445n istore <pending push temp 0>[#793 Auto] [flags 0x3 0x800 ] [ 0x3ff4315b360] bci=[10,138,2666] rc=0 vc=257 vn=- li=- udi=- nc=1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to be working as intended. I validated the log with @dhong44. We seem to have good frequencies on the blocks containing the intrinsic calls.
@smlambert @llxia Can one of you review the tests? |
@@ -1042,7 +1042,7 @@ | |||
<test> | |||
<testCaseName>JCL_Test_JIT_Helper</testCaseName> | |||
<command>$(JAVA_COMMAND) $(JVM_OPTIONS) --add-exports=java.base/com.ibm.jit=ALL-UNNAMED \ | |||
-Xbootclasspath/a:$(Q)$(TEST_RESROOT)$(D)TestResources.jar$(Q) \ | |||
--add-opens=java.base/com.ibm.jit=ALL-UNNAMED -Xbootclasspath/a:$(Q)$(TEST_RESROOT)$(D)TestResources.jar$(Q) \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While we're in the area can you rename this test case name to "JCL_Test_JITHelpers" to make it searchable since the test file is Test_JITHelpers.java and the class name is JITHelpers. I would like to be able to find this line in the future by grepping for the class name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is only for SE90 and up, SE80 has it's own test above. I don't think the --add-opens
is necessary or is even recognized in Java 8.
367a19f
to
4553d5a
Compare
for (int j : edgecaseLengths){ | ||
buffer = new char[j]; | ||
if (helpers.toUpperIntrinsicUTF16(Arrays.copyOfRange(lowercaseUTF16Char, 0, j), buffer, j * 2)) { | ||
AssertJUnit.assertTrue("UTF16 JITHelper upper case conversion with char arrays of " + j + " letters failed", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of using org.testng.AssertJUnit
, we should directly use org.testng.Assert
http://static.javadoc.io/org.testng/testng/6.8.17/org/testng/Assert.html
org.testng.AssertJUnit
is used when we port/migrate code that uses JUnit's asserts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4a4b2df
@@ -1377,6 +1405,34 @@ public void test_toUpperCase() { | |||
|
|||
AssertJUnit.assertTrue("Wrong conversion", "\u00df".toUpperCase().equals("SS")); | |||
|
|||
// Long strings and strings of lengths near multiples of 16 bytes to test vector HW acceleration edge cases. | |||
AssertJUnit.assertTrue("toUpperCase case conversion failed on a long string", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. org.testng.Assert
should be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
09078d4
I ran a bumble bench that called |
cursor = generateRILInstruction (cg, TR::InstOpCode::getSubtractLogicalImmOpCode(), node, rResidue, 1); iComment("adjust residue for VLL/VSTL (length -> index)"); | ||
|
||
/* ===================== Step 3: Residue processing =====================*/ | ||
generateRRInstruction(cg, TR::InstOpCode::getLoadRegOpCode(), node, loadLength, lengthRegister); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems unnecessary given the load above. Can we remove this? Also shouldn't lengthRegister
always a 32-bit value? Shouldn't we always use an LR
here? Similarly to above, why can't loadLength
also be a 32-bit register?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cf269b9
cursor = generateRIInstruction (cg, TR::InstOpCode::TMLH, node, rLen, (uint16_t) 0x8000); | ||
cursor = generateS390BranchInstruction (cg, TR::InstOpCode::BRC , TR::InstOpCode::COND_MASK2, node, handleInvalidChars); | ||
cursor->setStartInternalControlFlow(); | ||
generateRRInstruction(cg, TR::InstOpCode::LLGFR, node, lengthRegister, lengthRegister); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why exactly is this needed? Looking at the instruction selection from #2098 (comment) I see that all uses of this register can be made in a 32-bit context. We seem to be forcing it to be 64-bit here however.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cf269b9
} | ||
buffer.getClass(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to test supportsIntrinsicCaseConversion
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so, since the result of that method when compiled is dependent on the machine. There's no way we could really test that it returns the correct result.
Jenkins test sanity |
Transferring this to @joransiu as I'll be away for the next two weeks. |
Modify API call so that caseConversionHelper recieves underlying arrays and length of string. Closes: eclipse-openj9#1934 Signed-off-by: Daniel Hong <[email protected]>
Remove unused String constructors accepting one integer and returning an empty String with an appropriate capacity. Closes: eclipse-openj9#777 Signed-off-by: Daniel Hong <[email protected]>
Modify API call so that caseConversionHelper receives
underlying arrays and length of string.
Closes: #1934
Signed-off-by: Daniel Hong [email protected]