--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Tue May 03 19:45:44 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Tue May 03 21:28:46 2016 +0000
@@ -882,4 +882,9 @@
public boolean isTrustedInterfaceType() {
return TrustedInterface.class.isAssignableFrom(mirror());
}
+
+ @Override
+ public boolean isCloneableWithAllocation() {
+ return (getAccessFlags() & config().jvmAccIsCloneableFast) != 0;
+ }
}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java Tue May 03 19:45:44 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java Tue May 03 21:28:46 2016 +0000
@@ -267,4 +267,9 @@
public boolean isTrustedInterfaceType() {
return false;
}
+
+ @Override
+ public boolean isCloneableWithAllocation() {
+ return false;
+ }
}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Tue May 03 19:45:44 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Tue May 03 21:28:46 2016 +0000
@@ -1077,6 +1077,7 @@
@HotSpotVMConstant(name = "JVM_ACC_FIELD_STABLE") @Stable public int jvmAccFieldStable;
@HotSpotVMConstant(name = "JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE") @Stable public int jvmAccFieldHasGenericSignature;
@HotSpotVMConstant(name = "JVM_ACC_WRITTEN_FLAGS") @Stable public int jvmAccWrittenFlags;
+ @HotSpotVMConstant(name = "JVM_ACC_IS_CLONEABLE_FAST") @Stable public int jvmAccIsCloneableFast;
// Modifier.SYNTHETIC is not public so we get it via vmStructs.
@HotSpotVMConstant(name = "JVM_ACC_SYNTHETIC") @Stable public int jvmAccSynthetic;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java Tue May 03 19:45:44 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java Tue May 03 21:28:46 2016 +0000
@@ -359,4 +359,12 @@
}
return null;
}
+
+ /**
+ * Returns true if this type is {@link Cloneable} and can be safely cloned by creating a normal
+ * Java allocation and populating it from the fields returned by
+ * {@link #getInstanceFields(boolean)}. Some types may require special handling by the platform
+ * so they would to go through the normal {@link Object#clone} path.
+ */
+ boolean isCloneableWithAllocation();
}
--- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Tue May 03 19:45:44 2016 +0000
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Tue May 03 21:28:46 2016 +0000
@@ -309,6 +309,7 @@
declare_constant(JVM_ACC_MONITOR_MATCH) \
declare_constant(JVM_ACC_HAS_MONITOR_BYTECODES) \
declare_constant(JVM_ACC_HAS_FINALIZER) \
+ declare_constant(JVM_ACC_IS_CLONEABLE_FAST) \
declare_constant(JVM_ACC_FIELD_INTERNAL) \
declare_constant(JVM_ACC_FIELD_STABLE) \
declare_constant(JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE) \
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java Tue May 03 19:45:44 2016 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java Tue May 03 21:28:46 2016 +0000
@@ -866,6 +866,31 @@
}
}
+ static class TrivialCloneable implements Cloneable {
+ @Override
+ protected Object clone() {
+ return new TrivialCloneable();
+ }
+ }
+
+ @Test
+ public void isCloneableWithAllocationTest() {
+ ResolvedJavaType cloneable = metaAccess.lookupJavaType(Cloneable.class);
+ for (Class<?> c : classes) {
+ ResolvedJavaType type = metaAccess.lookupJavaType(c);
+ if (type.isCloneableWithAllocation()) {
+ // Only Cloneable types should be allocation cloneable
+ assertTrue(c.toString(), cloneable.isAssignableFrom(type));
+ }
+ }
+ /*
+ * We can't know for sure which types should be allocation cloneable on a particular
+ * platform but assume that at least totally trivial objects should be.
+ */
+ ResolvedJavaType trivialCloneable = metaAccess.lookupJavaType(TrivialCloneable.class);
+ assertTrue(trivialCloneable.toString(), trivialCloneable.isCloneableWithAllocation());
+ }
+
@Test
public void findMethodTest() {
try {