# HG changeset patch # User Doug Simon # Date 1390314398 -3600 # Node ID 2f944a810dd407a5caece1800625d7b0167689e5 # Parent 4281521dc39aad770533ee2b3ce08d8bd4ccf867 added list to PTXHotSpotBackend for keeping a valid installed kernel (and its associated nmethods) alive diff -r 4281521dc39a -r 2f944a810dd4 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXMethodInvalidation2Test.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXMethodInvalidation2Test.java Tue Jan 21 12:14:38 2014 +0100 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXMethodInvalidation2Test.java Tue Jan 21 15:26:38 2014 +0100 @@ -42,7 +42,6 @@ public class PTXMethodInvalidation2Test extends PTXTest { @Test - @Ignore("still need to make a strong reference from a PTX wrapper to a PTX kernel") public void test() { test("testSnippet", 100); } @@ -57,7 +56,7 @@ while (ref.get() != null) { System.gc(); // Give up after 1000 attempts - Assume.assumeTrue(attempts++ < 1000); + Assume.assumeTrue(++attempts < 1000); } Assert.assertFalse(code.getStart() == 0L); diff -r 4281521dc39a -r 2f944a810dd4 graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Tue Jan 21 12:14:38 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Tue Jan 21 15:26:38 2014 +0100 @@ -181,9 +181,27 @@ } - public HotSpotNmethod installKernel(ResolvedJavaMethod method, ExternalCompilationResult ptxCode) { - assert ptxCode.getEntryPoint() != 0L; - return getProviders().getCodeCache().addExternalMethod(method, ptxCode); + /** + * A list of the {@linkplain #installKernel(ResolvedJavaMethod, ExternalCompilationResult) + * installed} kernels. This is required so that there is a strong reference to each installed + * kernel as long as it is {@linkplain HotSpotNmethod#isValid() valid}. The list is pruned of + * invalid kernels every time a new kernel is installed. + */ + private List installedKernels = new LinkedList<>(); + + public final HotSpotNmethod installKernel(ResolvedJavaMethod method, ExternalCompilationResult ptxCode) { + assert OmitDeviceInit || ptxCode.getEntryPoint() != 0L; + HotSpotNmethod kernel = getProviders().getCodeCache().addExternalMethod(method, ptxCode); + synchronized (installedKernels) { + for (Iterator i = installedKernels.iterator(); i.hasNext();) { + HotSpotNmethod entry = i.next(); + if (!entry.isValid()) { + i.remove(); + } + } + installedKernels.add(kernel); + } + return kernel; } static final class RegisterAnalysis extends ValueProcedure { diff -r 4281521dc39a -r 2f944a810dd4 graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Tue Jan 21 12:14:38 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Tue Jan 21 15:26:38 2014 +0100 @@ -54,9 +54,9 @@ import com.oracle.graal.word.*; /** - * Utility for building a graph that "wraps" the PTX binary compiled for a method. Such a wrapper - * handles the transition from the host CPU to the GPU and back. The graph created is something like - * the following pseudo code with UPPER CASE denoting compile-time constants: + * Utility for building a graph that "wraps" a compiled PTX kernel. Such a wrapper handles the + * transition from the host CPU to the GPU and back. The graph created is something like the + * following pseudo code with UPPER CASE denoting compile-time constants: * *
  *     T kernel(p0, p1, ..., pN) {
@@ -66,6 +66,10 @@
  *         return convert(result);
  *     }
  * 
+ *

+ * The generated graph includes a reference to the {@link HotSpotNmethod} for the kernel. There must + * be another reference to the same {@link HotSpotNmethod} object to ensure that the nmethod is not + * unloaded by the next full GC. */ public class PTXWrapperBuilder extends GraphKit { @@ -98,9 +102,10 @@ * Creates the graph implementing the CPU to GPU transition. * * @param method a method that has been compiled to GPU binary code - * @param ptxInstalledCode the installed GPU binary for {@code method} + * @param kernel the installed GPU binary for {@code method} + * @see PTXWrapperBuilder */ - public PTXWrapperBuilder(ResolvedJavaMethod method, HotSpotNmethod ptxInstalledCode, HotSpotProviders providers) { + public PTXWrapperBuilder(ResolvedJavaMethod method, HotSpotNmethod kernel, HotSpotProviders providers) { super(new StructuredGraph(method), providers); int wordSize = providers.getCodeCache().getTarget().wordSize; Kind wordKind = providers.getCodeCache().getTarget().wordKind; @@ -133,13 +138,13 @@ } } - InvokeNode kernel = createInvoke(getClass(), "getKernelStart", ConstantNode.forObject(ptxInstalledCode, providers.getMetaAccess(), getGraph())); + InvokeNode kernelStart = createInvoke(getClass(), "getKernelStart", ConstantNode.forObject(kernel, providers.getMetaAccess(), getGraph())); AllocaNode buf = append(new AllocaNode(bufSize / wordSize, objects)); Map args = new EnumMap<>(LaunchArg.class); args.put(Thread, append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), true, false))); - args.put(Kernel, kernel); + args.put(Kernel, kernelStart); args.put(DimX, forInt(1, getGraph())); args.put(DimY, forInt(1, getGraph())); args.put(DimZ, forInt(1, getGraph()));