use of jdk.vm.ci.meta.MetaAccessProvider in project graal by oracle.
the class CompileTheWorld method compile.
/**
* Compiles all methods in all classes in a given class path.
*
* @param classPath class path denoting classes to compile
* @throws IOException
*/
@SuppressWarnings("try")
private void compile(String classPath) throws IOException {
final String[] entries = classPath.split(File.pathSeparator);
long start = System.currentTimeMillis();
Map<Thread, StackTraceElement[]> initialThreads = Thread.getAllStackTraces();
try {
// compile dummy method to get compiler initialized outside of the
// config debug override.
HotSpotResolvedJavaMethod dummyMethod = (HotSpotResolvedJavaMethod) JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaMethod(CompileTheWorld.class.getDeclaredMethod("dummy"));
int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI;
boolean useProfilingInfo = false;
boolean installAsDefault = false;
CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), useProfilingInfo, installAsDefault, currentOptions);
task.runCompilation();
} catch (NoSuchMethodException | SecurityException e1) {
printStackTrace(e1);
}
/*
* Always use a thread pool, even for single threaded mode since it simplifies the use of
* DebugValueThreadFilter to filter on the thread names.
*/
int threadCount = 1;
if (Options.MultiThreaded.getValue(currentOptions)) {
threadCount = Options.Threads.getValue(currentOptions);
if (threadCount == 0) {
threadCount = Runtime.getRuntime().availableProcessors();
}
} else {
running = true;
}
OptionValues savedOptions = currentOptions;
currentOptions = new OptionValues(compilationOptions);
threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new CompilerThreadFactory("CompileTheWorld"));
try {
for (int i = 0; i < entries.length; i++) {
final String entry = entries[i];
ClassPathEntry cpe;
if (entry.endsWith(".zip") || entry.endsWith(".jar")) {
cpe = new JarClassPathEntry(entry);
} else if (entry.equals(JRT_CLASS_PATH_ENTRY)) {
cpe = new JRTClassPathEntry(entry, Options.LimitModules.getValue(currentOptions));
} else {
if (!new File(entry).isDirectory()) {
println("CompileTheWorld : Skipped classes in " + entry);
println();
continue;
}
cpe = new DirClassPathEntry(entry);
}
if (methodFilters == null || methodFilters.length == 0) {
println("CompileTheWorld : Compiling all classes in " + entry);
} else {
String include = Arrays.asList(methodFilters).stream().map(MethodFilter::toString).collect(Collectors.joining(", "));
println("CompileTheWorld : Compiling all methods in " + entry + " matching one of the following filters: " + include);
}
if (excludeMethodFilters != null && excludeMethodFilters.length > 0) {
String exclude = Arrays.asList(excludeMethodFilters).stream().map(MethodFilter::toString).collect(Collectors.joining(", "));
println("CompileTheWorld : Excluding all methods matching one of the following filters: " + exclude);
}
println();
ClassLoader loader = cpe.createClassLoader();
for (String className : cpe.getClassNames()) {
// Are we done?
if (classFileCounter >= stopAt) {
break;
}
classFileCounter++;
if (className.startsWith("jdk.management.") || className.startsWith("jdk.internal.cmm.*") || // These threads tend to cause deadlock at VM exit
className.startsWith("sun.tools.jconsole.")) {
continue;
}
if (!isClassIncluded(className)) {
continue;
}
try {
// Load and initialize class
Class<?> javaClass = Class.forName(className, true, loader);
// Pre-load all classes in the constant pool.
try {
HotSpotResolvedObjectType objectType = HotSpotResolvedObjectType.fromObjectClass(javaClass);
ConstantPool constantPool = objectType.getConstantPool();
for (int cpi = 1; cpi < constantPool.length(); cpi++) {
constantPool.loadReferencedType(cpi, Bytecodes.LDC);
}
} catch (Throwable t) {
// If something went wrong during pre-loading we just ignore it.
if (isClassIncluded(className)) {
println("Preloading failed for (%d) %s: %s", classFileCounter, className, t);
}
continue;
}
// Are we compiling this class?
MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
if (classFileCounter >= startAt) {
println("CompileTheWorld (%d) : %s", classFileCounter, className);
// Compile each constructor/method in the class.
for (Constructor<?> constructor : javaClass.getDeclaredConstructors()) {
HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(constructor);
if (canBeCompiled(javaMethod, constructor.getModifiers())) {
compileMethod(javaMethod);
}
}
for (Method method : javaClass.getDeclaredMethods()) {
HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaMethod(method);
if (canBeCompiled(javaMethod, method.getModifiers())) {
compileMethod(javaMethod);
}
}
// Also compile the class initializer if it exists
HotSpotResolvedJavaMethod clinit = (HotSpotResolvedJavaMethod) metaAccess.lookupJavaType(javaClass).getClassInitializer();
if (clinit != null && canBeCompiled(clinit, clinit.getModifiers())) {
compileMethod(clinit);
}
}
} catch (Throwable t) {
if (isClassIncluded(className)) {
println("CompileTheWorld (%d) : Skipping %s %s", classFileCounter, className, t.toString());
printStackTrace(t);
}
}
}
cpe.close();
}
} finally {
currentOptions = savedOptions;
}
if (!running) {
startThreads();
}
int wakeups = 0;
while (threadPool.getCompletedTaskCount() != threadPool.getTaskCount()) {
if (wakeups % 15 == 0) {
TTY.println("CompileTheWorld : Waiting for " + (threadPool.getTaskCount() - threadPool.getCompletedTaskCount()) + " compiles");
}
try {
threadPool.awaitTermination(1, TimeUnit.SECONDS);
wakeups++;
} catch (InterruptedException e) {
}
}
threadPool = null;
long elapsedTime = System.currentTimeMillis() - start;
println();
if (Options.MultiThreaded.getValue(currentOptions)) {
TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms elapsed, %d ms compile time, %d bytes of memory used)", classFileCounter, compiledMethodsCounter.get(), elapsedTime, compileTime.get(), memoryUsed.get());
} else {
TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms, %d bytes of memory used)", classFileCounter, compiledMethodsCounter.get(), compileTime.get(), memoryUsed.get());
}
// Apart from the main thread, there should be only be daemon threads
// alive now. If not, then a class initializer has probably started
// a thread that could cause a deadlock while trying to exit the VM.
// One known example of this is sun.tools.jconsole.OutputViewer which
// spawns threads to redirect sysout and syserr. To help debug such
// scenarios, the stacks of potentially problematic threads are dumped.
Map<Thread, StackTraceElement[]> suspiciousThreads = new HashMap<>();
for (Map.Entry<Thread, StackTraceElement[]> e : Thread.getAllStackTraces().entrySet()) {
Thread thread = e.getKey();
if (thread != Thread.currentThread() && !initialThreads.containsKey(thread) && !thread.isDaemon() && thread.isAlive()) {
suspiciousThreads.put(thread, e.getValue());
}
}
if (!suspiciousThreads.isEmpty()) {
TTY.println("--- Non-daemon threads started during CTW ---");
for (Map.Entry<Thread, StackTraceElement[]> e : suspiciousThreads.entrySet()) {
Thread thread = e.getKey();
if (thread.isAlive()) {
TTY.println(thread.toString() + " " + thread.getState());
for (StackTraceElement ste : e.getValue()) {
TTY.println("\tat " + ste);
}
}
}
TTY.println("---------------------------------------------");
}
}
use of jdk.vm.ci.meta.MetaAccessProvider in project graal by oracle.
the class JNIJavaCallWrapperMethod method loadAndUnboxArguments.
private List<Pair<ValueNode, ResolvedJavaType>> loadAndUnboxArguments(JNIGraphKit kit, HostedProviders providers, ResolvedJavaMethod invokeMethod, Signature invokeSignature) {
MetaAccessProvider metaAccess = providers.getMetaAccess();
List<Pair<ValueNode, ResolvedJavaType>> args = new ArrayList<>();
int javaIndex = 0;
javaIndex += metaAccess.lookupJavaType(JNIEnvironment.class).getJavaKind().getSlotCount();
if (!invokeMethod.isStatic()) {
JavaKind kind = metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind();
ValueNode handle = kit.loadLocal(javaIndex, kind);
ValueNode unboxed = kit.unboxHandle(handle);
ValueNode receiver;
ResolvedJavaType receiverClass = invokeMethod.getDeclaringClass();
if (invokeMethod.isConstructor()) {
/*
* Our target method is a constructor and we might be called via `NewObject`, in
* which case we need to allocate the object before calling the constructor. We can
* detect when this is the case because unlike with `Call<Type>Method`, we are
* passed the object hub of our target class in place of the receiver object.
*/
Constant hub = providers.getConstantReflection().asObjectHub(receiverClass);
ConstantNode hubNode = kit.createConstant(hub, JavaKind.Object);
kit.startIf(kit.unique(new ObjectEqualsNode(unboxed, hubNode)), BranchProbabilityNode.FAST_PATH_PROBABILITY);
kit.thenPart();
ValueNode created = kit.append(new NewInstanceNode(receiverClass, true));
AbstractMergeNode merge = kit.endIf();
receiver = kit.unique(new ValuePhiNode(StampFactory.object(), merge, new ValueNode[] { created, unboxed }));
} else {
receiver = unboxed;
}
args.add(Pair.create(receiver, receiverClass));
}
javaIndex += metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind().getSlotCount();
if (nonVirtual) {
javaIndex += metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind().getSlotCount();
}
javaIndex += metaAccess.lookupJavaType(JNIMethodId.class).getJavaKind().getSlotCount();
int count = invokeSignature.getParameterCount(false);
if (callVariant == CallVariant.VARARGS) {
for (int i = 0; i < count; i++) {
ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
JavaKind kind = type.getJavaKind();
JavaKind loadKind = kind;
if (loadKind == JavaKind.Float) {
// C varargs promote float to double
loadKind = JavaKind.Double;
}
ValueNode value = kit.loadLocal(javaIndex, loadKind);
if (kind == JavaKind.Float) {
value = kit.unique(new FloatConvertNode(FloatConvert.D2F, value));
} else if (kind.isObject()) {
value = kit.unboxHandle(value);
}
args.add(Pair.create(value, type));
javaIndex += loadKind.getSlotCount();
}
} else if (callVariant == CallVariant.ARRAY) {
ResolvedJavaType elementType = metaAccess.lookupJavaType(JNIValue.class);
int elementSize = SizeOf.get(JNIValue.class);
ValueNode array = kit.loadLocal(javaIndex, elementType.getJavaKind());
for (int i = 0; i < count; i++) {
ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
JavaKind readKind = type.getJavaKind();
StructFieldInfo fieldInfo = getJNIValueOffsetOf(elementType, readKind);
int offset = i * elementSize + fieldInfo.getOffsetInfo().getProperty();
ConstantNode offsetConstant = kit.createConstant(JavaConstant.forInt(offset), providers.getWordTypes().getWordKind());
OffsetAddressNode address = kit.unique(new OffsetAddressNode(array, offsetConstant));
LocationIdentity locationIdentity = fieldInfo.getLocationIdentity();
if (locationIdentity == null) {
locationIdentity = LocationIdentity.any();
}
Stamp readStamp = getNarrowStamp(providers, readKind);
ValueNode value = kit.append(new CInterfaceReadNode(address, locationIdentity, readStamp, BarrierType.NONE, "args[" + i + "]"));
JavaKind stackKind = readKind.getStackKind();
if (readKind != stackKind) {
assert stackKind.getBitCount() > readKind.getBitCount() : "read kind must be narrower than stack kind";
if (readKind.isUnsigned()) {
// needed or another op may illegally sign-extend
value = kit.unique(new ZeroExtendNode(value, stackKind.getBitCount()));
} else {
value = kit.unique(new SignExtendNode(value, stackKind.getBitCount()));
}
} else if (readKind.isObject()) {
value = kit.unboxHandle(value);
}
args.add(Pair.create(value, type));
}
} else if (callVariant == CallVariant.VA_LIST) {
ValueNode valist = kit.loadLocal(javaIndex, metaAccess.lookupJavaType(WordBase.class).getJavaKind());
for (int i = 0; i < count; i++) {
ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
JavaKind loadKind = type.getJavaKind();
if (loadKind.isObject()) {
loadKind = providers.getWordTypes().getWordKind();
}
ValueNode value = kit.append(new VaListNextArgNode(loadKind, valist));
if (type.getJavaKind().isObject()) {
value = kit.unboxHandle(value);
}
args.add(Pair.create(value, type));
}
} else {
throw VMError.unsupportedFeature("Call variant: " + callVariant);
}
return args;
}
use of jdk.vm.ci.meta.MetaAccessProvider in project graal by oracle.
the class JNIFunctionTablesFeature method beforeAnalysis.
@Override
public void beforeAnalysis(BeforeAnalysisAccess arg) {
BeforeAnalysisAccessImpl access = (BeforeAnalysisAccessImpl) arg;
AnalysisMetaAccess metaAccess = access.getMetaAccess();
JNIFunctionTables.create();
NativeLibraries nativeLibraries = access.getNativeLibraries();
AnalysisType invokeInterface = metaAccess.lookupJavaType(JNIInvokeInterface.class);
invokeInterfaceMetadata = (StructInfo) nativeLibraries.findElementInfo(invokeInterface);
AnalysisType functionTable = metaAccess.lookupJavaType(JNINativeInterface.class);
functionTableMetadata = (StructInfo) nativeLibraries.findElementInfo(functionTable);
// Manually add functions as entry points so this is only done when JNI features are enabled
AnalysisType invokes = metaAccess.lookupJavaType(JNIInvocationInterface.class);
AnalysisType exports = metaAccess.lookupJavaType(JNIInvocationInterface.Exports.class);
AnalysisType functions = metaAccess.lookupJavaType(JNIFunctions.class);
Stream<AnalysisMethod> analysisMethods = Stream.of(invokes, functions, exports).flatMap(t -> Stream.of(t.getDeclaredMethods()));
Stream<AnalysisMethod> unimplementedMethods = Stream.of((AnalysisMethod) getSingleMethod(metaAccess, UnimplementedWithJNIEnvArgument.class), (AnalysisMethod) getSingleMethod(metaAccess, UnimplementedWithJavaVMArgument.class));
Stream.concat(analysisMethods, unimplementedMethods).forEach(method -> {
CEntryPoint annotation = method.getAnnotation(CEntryPoint.class);
assert annotation != null : "only entry points allowed in class";
CEntryPointCallStubSupport.singleton().registerStubForMethod(method, () -> CEntryPointData.create(method));
});
ArrayList<ResolvedJavaMethod> generated = new ArrayList<>();
MetaAccessProvider wrappedMetaAccess = metaAccess.getWrapped();
ResolvedJavaType generatedMethodClass = wrappedMetaAccess.lookupJavaType(JNIFunctions.class);
ConstantPool constantPool = generatedMethodClass.getDeclaredMethods()[0].getConstantPool();
// Generate JNI field accessors
EnumSet<JavaKind> fldKinds = jniKinds.clone();
fldKinds.remove(JavaKind.Void);
for (JavaKind kind : fldKinds) {
boolean[] trueFalse = { true, false };
for (boolean isSetter : trueFalse) {
for (boolean isStatic : trueFalse) {
JNIFieldAccessorMethod method = new JNIFieldAccessorMethod(kind, isSetter, isStatic, generatedMethodClass, constantPool, wrappedMetaAccess);
AnalysisMethod analysisMethod = access.getUniverse().lookup(method);
access.getBigBang().addRootMethod(analysisMethod).registerAsEntryPoint(method.createEntryPointData());
generated.add(method);
}
}
}
// Generate JNI primitive array operations
EnumSet<JavaKind> primitiveArrayKinds = jniKinds.clone();
primitiveArrayKinds.remove(JavaKind.Void);
primitiveArrayKinds.remove(JavaKind.Object);
for (JavaKind kind : primitiveArrayKinds) {
for (Operation op : Operation.values()) {
JNIPrimitiveArrayOperationMethod method = new JNIPrimitiveArrayOperationMethod(kind, op, generatedMethodClass, constantPool, wrappedMetaAccess);
AnalysisMethod analysisMethod = access.getUniverse().lookup(method);
access.getBigBang().addRootMethod(analysisMethod).registerAsEntryPoint(method.createEntryPointData());
generated.add(method);
}
}
generatedMethods = generated.toArray(new ResolvedJavaMethod[0]);
}
use of jdk.vm.ci.meta.MetaAccessProvider in project graal by oracle.
the class JNIAccessFeature method addMethod.
private void addMethod(Executable method, DuringAnalysisAccessImpl access) {
JNIAccessibleClass jniClass = addClass(method.getDeclaringClass(), access);
JNIAccessibleMethodDescriptor descriptor = JNIAccessibleMethodDescriptor.of(method);
jniClass.addMethodIfAbsent(descriptor, d -> {
MetaAccessProvider wrappedMetaAccess = access.getMetaAccess().getWrapped();
JNIJavaCallWrapperMethod varargsCallWrapper = new JNIJavaCallWrapperMethod(method, CallVariant.VARARGS, false, wrappedMetaAccess, nativeLibraries);
JNIJavaCallWrapperMethod arrayCallWrapper = new JNIJavaCallWrapperMethod(method, CallVariant.ARRAY, false, wrappedMetaAccess, nativeLibraries);
JNIJavaCallWrapperMethod valistCallWrapper = new JNIJavaCallWrapperMethod(method, CallVariant.VA_LIST, false, wrappedMetaAccess, nativeLibraries);
Stream<JNIJavaCallWrapperMethod> wrappers = Stream.of(varargsCallWrapper, arrayCallWrapper, valistCallWrapper);
JNIJavaCallWrapperMethod varargsNonvirtualCallWrapper = null;
JNIJavaCallWrapperMethod arrayNonvirtualCallWrapper = null;
JNIJavaCallWrapperMethod valistNonvirtualCallWrapper = null;
if (!Modifier.isStatic(method.getModifiers())) {
varargsNonvirtualCallWrapper = new JNIJavaCallWrapperMethod(method, CallVariant.VARARGS, true, wrappedMetaAccess, nativeLibraries);
arrayNonvirtualCallWrapper = new JNIJavaCallWrapperMethod(method, CallVariant.ARRAY, true, wrappedMetaAccess, nativeLibraries);
valistNonvirtualCallWrapper = new JNIJavaCallWrapperMethod(method, CallVariant.VA_LIST, true, wrappedMetaAccess, nativeLibraries);
wrappers = Stream.concat(wrappers, Stream.of(varargsNonvirtualCallWrapper, arrayNonvirtualCallWrapper, valistNonvirtualCallWrapper));
}
JNIAccessibleMethod jniMethod = new JNIAccessibleMethod(method.getModifiers(), jniClass, varargsCallWrapper, arrayCallWrapper, valistCallWrapper, varargsNonvirtualCallWrapper, arrayNonvirtualCallWrapper, valistNonvirtualCallWrapper);
wrappers.forEach(wrapper -> {
AnalysisMethod analysisWrapper = access.getUniverse().lookup(wrapper);
access.getBigBang().addRootMethod(analysisWrapper);
// ensures C calling convention
analysisWrapper.registerAsEntryPoint(jniMethod);
});
return jniMethod;
});
}
use of jdk.vm.ci.meta.MetaAccessProvider in project graal by oracle.
the class JNIAccessFeature method createJavaCallTrampoline.
private static JNICallTrampolineMethod createJavaCallTrampoline(BeforeAnalysisAccessImpl access, CallVariant variant, boolean nonVirtual) {
MetaAccessProvider wrappedMetaAccess = access.getMetaAccess().getWrapped();
ResolvedJavaField field = JNIAccessibleMethod.getCallWrapperField(wrappedMetaAccess, variant, nonVirtual);
access.registerAsAccessed(access.getUniverse().lookup(field));
ResolvedJavaMethod method = JNIJavaCallWrappers.lookupJavaCallTrampoline(wrappedMetaAccess, variant, nonVirtual);
JNICallTrampolineMethod trampoline = new JNICallTrampolineMethod(method, field, nonVirtual);
access.registerAsCompiled(access.getUniverse().lookup(trampoline));
return trampoline;
}
Aggregations