1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 package jdk.internal.vm.compiler.libgraal; 26 27 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; 28 29 /** 30 * Scope for calling CEntryPoints in libgraal. {@linkplain #LibGraalScope(HotSpotJVMCIRuntime) 31 * Opening} a scope attaches the current thread to libgraal and {@linkplain #close() closing} it 32 * detaches the current thread. 33 */ 34 public final class LibGraalScope implements AutoCloseable { 35 36 static final ThreadLocal<LibGraalScope> currentScope = new ThreadLocal<>(); 37 38 private final LibGraalScope parent; 39 private final boolean topLevel; 40 private final HotSpotJVMCIRuntime runtime; 41 private final long isolateThread; 42 43 /** 44 * Gets the isolate thread associated with the current thread. The current thread must be in an 45 * {@linkplain #LibGraalScope(HotSpotJVMCIRuntime) opened} scope. 46 * 47 * @returns a value that can be used for the IsolateThreadContext argument of a {@code native} 48 * method {@link LibGraal#registerNativeMethods linked} to a CEntryPoint function in 49 * libgraal 50 * @throws IllegalStateException if not the current thread is not attached to libgraal 51 */ 52 public static long getIsolateThread() { 53 LibGraalScope scope = currentScope.get(); 54 if (scope == null) { 55 throw new IllegalStateException("Cannot get isolate thread outside of a " + LibGraalScope.class.getSimpleName()); 56 } 57 return scope.isolateThread; 58 } 59 60 /** 61 * Enters a scope for making calls into libgraal. If there is no existing libgraal scope for the 62 * current thread, the current thread is attached to libgraal. When the outer most scope is 63 * closed, the current thread is detached from libgraal. 64 * 65 * This must be used in a try-with-resources statement. 66 * 67 * This cannot be called from {@linkplain LibGraal#inLibGraal() within} libgraal. 68 * 69 * @throws IllegalStateException if libgraal is {@linkplain LibGraal#isAvailable() unavailable} 70 * or {@link LibGraal#inLibGraal()} returns true 71 */ 72 public LibGraalScope(HotSpotJVMCIRuntime runtime) { 73 if (LibGraal.inLibGraal() || !LibGraal.isAvailable()) { 74 throw new IllegalStateException(); 75 } 76 this.runtime = runtime; 77 parent = currentScope.get(); 78 boolean top = false; 79 if (parent == null) { 80 top = LibGraal.attachCurrentThread(runtime); 81 isolateThread = LibGraal.getCurrentIsolateThread(LibGraal.isolate); 82 } else { 83 isolateThread = parent.isolateThread; 84 } 85 topLevel = top; 86 currentScope.set(this); 87 } 88 89 @Override 90 public void close() { 91 if (topLevel) { 92 LibGraal.detachCurrentThread(runtime); 93 } 94 currentScope.set(parent); 95 } 96 }