Details
Backports
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8246822 | 13.0.4 | Thomas Stuefe | P3 | Resolved | Fixed | b05 |
JDK-8239239 | 11.0.8-oracle | Thomas Stuefe | P3 | Resolved | Fixed | b01 |
JDK-8238746 | 11.0.7 | Thomas Stuefe | P3 | Resolved | Fixed | b03 |
Description
A Klass* allocated at a 32bit aligned address (all lower 32 bits set to zero) may cause jlClass::isPrimitive() to return the wrong value.
The reason is that the C1 intrinsic for jlClass::isPrimitive(), which compares the Klass* address with NULL, does so using a 32bit compare:
-------------
6512 Compiled method (c1) 822 31 1 java.lang.invoke.MethodTypeForm::canonicalize (233 bytes)
..<snip>..
6544 ;; block B2 [9, 13]
6545 0x00007f2ca8e76f3f: mov 0x50(%rsi),%rdi ; implicit exception: dispatches to 0x00007f2ca8e771ec
6546 0x00007f2ca8e76f43: cmp $0x0,%edi <<<< 32bit?
6547 0x00007f2ca8e76f46: mov $0x0,%edi
6548 0x00007f2ca8e76f4b: jne 0x00007f2ca8e76f56
6549 0x00007f2ca8e76f51: mov $0x1,%edi ;*invokevirtual isPrimitive {reexecute=0 rethrow=0 return_oop=0}
6550 ; - java.lang.invoke.MethodTypeForm::canonicalize@10 (line 263)
-------------
Reproduce:
This is not possible to reproduce in the stock VM (though it could happen, albeit with very low probability).
However, in the new metaspace allocator under development forJDK-8221173 chunk headers are removed from metaspace and therefore the very first Klass* ever to be allocated is located directly at class space start, which may be aligned to 32bit.
This very first Klass* usually belongs to boolean[].class.
CDS needs to be off for this to happen.
To reproduce, sync jdk-sandbox, branch "stuefe-new-metaspace-branch".
Then apply the following patch to force class space to a rounded address:
--- a/src/hotspot/share/memory/metaspace.cpp Sat Oct 19 09:26:24 2019 +0200
+++ b/src/hotspot/share/memory/metaspace.cpp Fri Oct 25 15:40:32 2019 +0200
@@ -828,6 +828,8 @@
#ifdef _LP64
if (using_class_space()) {
char* base = (char*)align_up(CompressedOops::end(), _reserve_alignment);
+ base= (char*)0xb00000000ULL;
allocate_metaspace_compressed_klass_ptrs(base, 0);
}
#endif // _LP64
(any address with 32bits set to zero will do).
and build.
Then run the jtreg test "java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java", with CDS disabled. It will show an internal error related to isPrimitive() for boolean[].class being wrong.
The reason is that the C1 intrinsic for jlClass::isPrimitive(), which compares the Klass* address with NULL, does so using a 32bit compare:
-------------
6512 Compiled method (c1) 822 31 1 java.lang.invoke.MethodTypeForm::canonicalize (233 bytes)
..<snip>..
6544 ;; block B2 [9, 13]
6545 0x00007f2ca8e76f3f: mov 0x50(%rsi),%rdi ; implicit exception: dispatches to 0x00007f2ca8e771ec
6546 0x00007f2ca8e76f43: cmp $0x0,%edi <<<< 32bit?
6547 0x00007f2ca8e76f46: mov $0x0,%edi
6548 0x00007f2ca8e76f4b: jne 0x00007f2ca8e76f56
6549 0x00007f2ca8e76f51: mov $0x1,%edi ;*invokevirtual isPrimitive {reexecute=0 rethrow=0 return_oop=0}
6550 ; - java.lang.invoke.MethodTypeForm::canonicalize@10 (line 263)
-------------
Reproduce:
This is not possible to reproduce in the stock VM (though it could happen, albeit with very low probability).
However, in the new metaspace allocator under development for
This very first Klass* usually belongs to boolean[].class.
CDS needs to be off for this to happen.
To reproduce, sync jdk-sandbox, branch "stuefe-new-metaspace-branch".
Then apply the following patch to force class space to a rounded address:
--- a/src/hotspot/share/memory/metaspace.cpp Sat Oct 19 09:26:24 2019 +0200
+++ b/src/hotspot/share/memory/metaspace.cpp Fri Oct 25 15:40:32 2019 +0200
@@ -828,6 +828,8 @@
#ifdef _LP64
if (using_class_space()) {
char* base = (char*)align_up(CompressedOops::end(), _reserve_alignment);
+ base= (char*)0xb00000000ULL;
allocate_metaspace_compressed_klass_ptrs(base, 0);
}
#endif // _LP64
(any address with 32bits set to zero will do).
and build.
Then run the jtreg test "java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java", with CDS disabled. It will show an internal error related to isPrimitive() for boolean[].class being wrong.
Attachments
Issue Links
- backported by
-
JDK-8238746 java.lang.Class.isPrimitive() (C1) returns wrong result if Klass* is aligned to 32bit
-
- Resolved
-
-
JDK-8239239 java.lang.Class.isPrimitive() (C1) returns wrong result if Klass* is aligned to 32bit
-
- Resolved
-
-
JDK-8246822 java.lang.Class.isPrimitive() (C1) returns wrong result if Klass* is aligned to 32bit
-
- Resolved
-
- relates to
-
JDK-8221083 [ppc64] Wrong oop compare in C1-generated code
-
- Resolved
-
-
JDK-8150669 C1 intrinsic for Class.isPrimitive
-
- Resolved
-
- links to
-
Review openjdk/jdk8u-dev/43
(1 links to)