-
Notifications
You must be signed in to change notification settings - Fork 1.8k
String.compareTo intrinsic for amd64 #299
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
Conversation
| * Initialize variables | ||
| */ | ||
| public StringCompareToTest() { | ||
| if (Java8OrEarlier) { |
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 this, use Assume.assumeFalse(Java8OrEarlier); (e.g.,
Line 229 in bfe765f
| public void testInvariantChecking() throws InterruptedException { |
|
|
||
| private static class EvexTupleType { | ||
| public static final int EVEX_FV = 0; | ||
| // public static final int EVEX_HV = 4; |
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.
These bits of commented code need to be removed or uncommented when this PR is ready to merge.
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.
Style check don't allow unused constants, but it's better to keep whole constant set for readability/future development.
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.
You can solve this by making EvexTupleType non-private (package-protected should be sufficient to convince Checkstyle that it might be used).
|
|
||
| /** | ||
| * @param value is byte[] | ||
| * @param other is char[] |
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.
Shouldn't this be byte?
|
This looks ok to me. Can we use this implementation for JDK8? It seems like a pretty simple substitution for String.compareTo could use the same logic as the char/char variant but with length * 2 to compensate for the byte[] vs char[] difference. It would also give us more test exposure with the implementation since we don't really use JDK9. I'll run it through our internal gate and see if anything shows up. |
| }; | ||
|
|
||
| public StringCompareToTest() { | ||
| Assume.assumeFalse(Java8OrEarlier); |
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.
Can you add an assumeTrue that the target arch is AMD64 as well?
|
I've gone ahead and fixed the issues I've mentioned as well as added a simple substitution for use in JDK8 along with a simple benchmark in StringBenchmark. If that's ok with you I'll push that through our gate. |
Tom, thank you for your support. Please, push the changes. |
|
There was one actual bug in the code that I found in the gate. It had emission logic checking for SSE4.1 when it should have been checking for SSE4.2. It was found by assertion checking. |
|
Thank you! |
|
Thanks for getting that in! |
| masm.leaq(str1, new AMD64Address(str1, cnt2, scale1)); | ||
| masm.leaq(str2, new AMD64Address(str2, cnt2, scale2)); | ||
| } | ||
| masm.decrementl(cnt2); // first character was compared already |
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 intrinsic causes segment fault transiently on Java 8. The problem occurs when cnt2 is 0 before this line. Then it decrements to 0xFFFFFFFF, and the next statement negates it to 0xFFFFFFFF00000001. This means on the entrance to this intrinsic min(cnt1, cnt2) is 1, and then gets right shifted to 0 at line 194. Given that we always double the length on Java 8, these two counters cannot be 1.
The crash log shows a corner case when we have String.compareTo in a loop, e.g., at TreeMap.getEntry. I suspect cnt1 is not reset within the loop but reuses the value from masm.pop(cnt1);. I am still working on reproducing it with a simple test case.
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 finally managed to reproduce it on my local machine and have created a pull request.
|
@dsamersoff there is a JDK bug (https://bugs.openjdk.java.net/browse/JDK-8228903) that seems to indicate a problem with |
I'll try to reproduce it in my setup and let you know if it succeeded. I also added myself to watchers of ojdk CR. |
|
@dsamersoff do you have access to a machine with capabilities that seem to be required for triggering this bug? |
|
No, I can't reproduce the issue on couple of machines I have access to |
|
@dougxc Could you try to disable the branch supportsAVX512VLBW inside AMD64ArrayCompareToOp:emitCode() and check whether it solves the problem or not? |
|
My Mac does not support AVX512VLBW. I'll find one of our test machines that does. In terms of a Graal unit test, does |
|
On brief check, StringCompareToTest from graal provides better coverage for compareTo, because it contains special sized strings to trigger tail comparison code. |
|
Interesting. We managed to reproduce the and: We added these to StringSubstitutionTestBase.testData but still |
|
@mur47x111 is looking into this. |
| // if (ae != StrIntrinsicNode::LL) { | ||
| if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) { | ||
| stride2x2 = 0x20; | ||
| } |
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.
stride2x2 should be 0x40 in the case of comparing latin string with latin string. Indeed, ae != StrIntrinsicNode::LL should be !(kind1 == JavaKind.Byte && kind2 == JavaKind.Byte), right?
Port of Chris Thalinger patch