8336489: Track scoped accesses in JVMCI compiled code

Reviewed-by: dnsimon, never
This commit is contained in:
Carlo Refice 2024-08-05 14:09:54 +00:00
parent 7e925d727f
commit c095c0e6a5
11 changed files with 72 additions and 6 deletions

View File

@ -722,6 +722,7 @@ JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler,
jint entry_bci = -1; jint entry_bci = -1;
JVMCICompileState* compile_state = nullptr; JVMCICompileState* compile_state = nullptr;
bool has_unsafe_access = false; bool has_unsafe_access = false;
bool has_scoped_access = false;
jint id = -1; jint id = -1;
if (is_nmethod) { if (is_nmethod) {
@ -729,6 +730,7 @@ JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler,
entry_bci = is_nmethod ? stream->read_s4("entryBCI") : -1; entry_bci = is_nmethod ? stream->read_s4("entryBCI") : -1;
compile_state = (JVMCICompileState*) stream->read_u8("compileState"); compile_state = (JVMCICompileState*) stream->read_u8("compileState");
has_unsafe_access = stream->read_bool("hasUnsafeAccess"); has_unsafe_access = stream->read_bool("hasUnsafeAccess");
has_scoped_access = stream->read_bool("hasScopedAccess");
id = stream->read_s4("id"); id = stream->read_s4("id");
} }
stream->set_code_desc(name, method); stream->set_code_desc(name, method);
@ -795,6 +797,7 @@ JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler,
id, id,
_has_monitors, _has_monitors,
has_unsafe_access, has_unsafe_access,
has_scoped_access,
_has_wide_vector, _has_wide_vector,
compiled_code, compiled_code,
mirror, mirror,

View File

@ -2078,6 +2078,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV,
int compile_id, int compile_id,
bool has_monitors, bool has_monitors,
bool has_unsafe_access, bool has_unsafe_access,
bool has_scoped_access,
bool has_wide_vector, bool has_wide_vector,
JVMCIObject compiled_code, JVMCIObject compiled_code,
JVMCIObject nmethod_mirror, JVMCIObject nmethod_mirror,
@ -2183,7 +2184,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV,
nm->set_has_unsafe_access(has_unsafe_access); nm->set_has_unsafe_access(has_unsafe_access);
nm->set_has_wide_vectors(has_wide_vector); nm->set_has_wide_vectors(has_wide_vector);
nm->set_has_monitors(has_monitors); nm->set_has_monitors(has_monitors);
nm->set_has_scoped_access(true); // conservative nm->set_has_scoped_access(has_scoped_access);
JVMCINMethodData* data = nm->jvmci_nmethod_data(); JVMCINMethodData* data = nm->jvmci_nmethod_data();
assert(data != nullptr, "must be"); assert(data != nullptr, "must be");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -452,6 +452,7 @@ class JVMCIRuntime: public CHeapObj<mtJVMCI> {
int compile_id, int compile_id,
bool has_monitors, bool has_monitors,
bool has_unsafe_access, bool has_unsafe_access,
bool has_scoped_access,
bool has_wide_vector, bool has_wide_vector,
JVMCIObject compiled_code, JVMCIObject compiled_code,
JVMCIObject nmethod_mirror, JVMCIObject nmethod_mirror,

View File

@ -655,6 +655,7 @@
declare_constant(ConstMethodFlags::_misc_intrinsic_candidate) \ declare_constant(ConstMethodFlags::_misc_intrinsic_candidate) \
declare_constant(ConstMethodFlags::_misc_reserved_stack_access) \ declare_constant(ConstMethodFlags::_misc_reserved_stack_access) \
declare_constant(ConstMethodFlags::_misc_changes_current_thread) \ declare_constant(ConstMethodFlags::_misc_changes_current_thread) \
declare_constant(ConstMethodFlags::_misc_is_scoped) \
\ \
declare_constant(CounterData::count_off) \ declare_constant(CounterData::count_off) \
\ \

View File

@ -563,6 +563,7 @@ final class HotSpotCompiledCodeStream implements AutoCloseable {
writeInt("entryBCI", nmethod.entryBCI); writeInt("entryBCI", nmethod.entryBCI);
writeLong("compileState", nmethod.compileState); writeLong("compileState", nmethod.compileState);
writeBoolean("hasUnsafeAccess", nmethod.hasUnsafeAccess); writeBoolean("hasUnsafeAccess", nmethod.hasUnsafeAccess);
writeBoolean("hasScopedAccess", nmethod.hasScopedAccess());
writeInt("id", nmethod.id); writeInt("id", nmethod.id);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -100,4 +100,22 @@ public final class HotSpotCompiledNmethod extends HotSpotCompiledCode {
public String getInstallationFailureMessage() { public String getInstallationFailureMessage() {
return installationFailureMessage; return installationFailureMessage;
} }
/**
* Determines if {@code methods} contains at least one entry for which {@code HotSpotResolvedJavaMethod.isScoped()} returns true.
*/
public boolean hasScopedAccess() {
if (methods == null) {
return false;
}
for (ResolvedJavaMethod method : methods) {
if (method instanceof HotSpotResolvedJavaMethod hotSpotMethod) {
if (hotSpotMethod.isScoped()) {
return true;
}
}
}
return false;
}
} }

View File

@ -170,7 +170,7 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
* @return flags of this method * @return flags of this method
*/ */
private int getFlags() { private int getFlags() {
return UNSAFE.getShort(getMethodPointer() + config().methodFlagsOffset); return UNSAFE.getInt(getMethodPointer() + config().methodFlagsOffset);
} }
/** /**
@ -179,7 +179,7 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
* @return flags of this method's ConstMethod * @return flags of this method's ConstMethod
*/ */
private int getConstMethodFlags() { private int getConstMethodFlags() {
return UNSAFE.getChar(getConstMethod() + config().constMethodFlagsOffset); return UNSAFE.getInt(getConstMethod() + config().constMethodFlagsOffset);
} }
@Override @Override
@ -324,6 +324,17 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
return (getConstMethodFlags() & config().constMethodFlagsReservedStackAccess) != 0; return (getConstMethodFlags() & config().constMethodFlagsReservedStackAccess) != 0;
} }
/**
* Returns true if this method has a
* {@code jdk.internal.misc.ScopedMemoryAccess.Scoped} annotation.
*
* @return true if Scoped annotation present, false otherwise
*/
@Override
public boolean isScoped() {
return (getConstMethodFlags() & config().constMethodFlagsIsScoped) != 0;
}
/** /**
* Sets flags on {@code method} indicating that it should never be inlined or compiled by the * Sets flags on {@code method} indicating that it should never be inlined or compiled by the
* VM. * VM.

View File

@ -194,6 +194,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
final int constMethodFlagsReservedStackAccess = getConstant("ConstMethodFlags::_misc_reserved_stack_access", Integer.class); final int constMethodFlagsReservedStackAccess = getConstant("ConstMethodFlags::_misc_reserved_stack_access", Integer.class);
final int constMethodFlagsCallerSensitive = getConstant("ConstMethodFlags::_misc_caller_sensitive", Integer.class); final int constMethodFlagsCallerSensitive = getConstant("ConstMethodFlags::_misc_caller_sensitive", Integer.class);
final int constMethodFlagsIntrinsicCandidate = getConstant("ConstMethodFlags::_misc_intrinsic_candidate", Integer.class); final int constMethodFlagsIntrinsicCandidate = getConstant("ConstMethodFlags::_misc_intrinsic_candidate", Integer.class);
final int constMethodFlagsIsScoped = getConstant("ConstMethodFlags::_misc_is_scoped", Integer.class);
final int constMethodHasLineNumberTable = getConstant("ConstMethodFlags::_misc_has_linenumber_table", Integer.class); final int constMethodHasLineNumberTable = getConstant("ConstMethodFlags::_misc_has_linenumber_table", Integer.class);
final int constMethodHasLocalVariableTable = getConstant("ConstMethodFlags::_misc_has_localvariable_table", Integer.class); final int constMethodHasLocalVariableTable = getConstant("ConstMethodFlags::_misc_has_localvariable_table", Integer.class);
final int constMethodHasMethodAnnotations = getConstant("ConstMethodFlags::_misc_has_method_annotations", Integer.class); final int constMethodHasMethodAnnotations = getConstant("ConstMethodFlags::_misc_has_method_annotations", Integer.class);

View File

@ -463,6 +463,16 @@ public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersP
return getDeclaringClass().isJavaLangObject() && getName().equals("<init>"); return getDeclaringClass().isJavaLangObject() && getName().equals("<init>");
} }
/**
* Returns true if this method has a
* {@code jdk.internal.misc.ScopedMemoryAccess.Scoped} annotation.
*
* @return true if Scoped annotation present, false otherwise.
*/
default boolean isScoped() {
throw new UnsupportedOperationException();
}
/** /**
* Gets a speculation log that can be used when compiling this method to make new speculations * Gets a speculation log that can be used when compiling this method to make new speculations
* and query previously failed speculations. The implementation may return a new * and query previously failed speculations. The implementation may return a new

View File

@ -475,6 +475,24 @@ public class TestResolvedJavaMethod extends MethodUniverse {
} }
} }
@Test
public void isScopedTest() throws NoSuchMethodException, ClassNotFoundException {
// Must use reflection as ScopedMemoryAccess$Scoped is package-private
Class<? extends Annotation> scopedAnnotationClass = Class.forName("jdk.internal.misc.ScopedMemoryAccess$Scoped").asSubclass(Annotation.class);
boolean scopedMethodFound = false;
for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
ResolvedJavaMethod m = e.getValue();
Method key = e.getKey();
boolean expect = key.isAnnotationPresent(scopedAnnotationClass);
boolean actual = m.isScoped();
assertEquals(m.toString(), expect, actual);
if (expect) {
scopedMethodFound = true;
}
}
assertTrue("At least one scoped method must be present", scopedMethodFound);
}
abstract static class UnlinkedType { abstract static class UnlinkedType {
abstract void abstractMethod(); abstract void abstractMethod();

View File

@ -51,6 +51,7 @@ import java.util.stream.Collectors;
import org.junit.Test; import org.junit.Test;
import jdk.internal.misc.Unsafe; import jdk.internal.misc.Unsafe;
import jdk.internal.misc.ScopedMemoryAccess;
import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.MetaAccessProvider;
@ -115,7 +116,7 @@ public class TypeUniverse {
byte[][].class, short[][].class, char[][].class, int[][].class, float[][].class, long[][].class, double[][].class, Object[][].class, Class[][].class, List[][].class, byte[][].class, short[][].class, char[][].class, int[][].class, float[][].class, long[][].class, double[][].class, Object[][].class, Class[][].class, List[][].class,
ClassLoader.class, String.class, Serializable.class, Cloneable.class, Test.class, TestMetaAccessProvider.class, List.class, Collection.class, Map.class, Queue.class, ClassLoader.class, String.class, Serializable.class, Cloneable.class, Test.class, TestMetaAccessProvider.class, List.class, Collection.class, Map.class, Queue.class,
HashMap.class, LinkedHashMap.class, IdentityHashMap.class, AbstractCollection.class, AbstractList.class, ArrayList.class, InnerClass.class, InnerStaticClass.class, HashMap.class, LinkedHashMap.class, IdentityHashMap.class, AbstractCollection.class, AbstractList.class, ArrayList.class, InnerClass.class, InnerStaticClass.class,
InnerStaticFinalClass.class, PrivateInnerClass.class, ProtectedInnerClass.class}; InnerStaticFinalClass.class, PrivateInnerClass.class, ProtectedInnerClass.class, ScopedMemoryAccess.class};
for (Class<?> c : initialClasses) { for (Class<?> c : initialClasses) {
addClass(c); addClass(c);
} }