Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / libjava / java / lang / VMCompiler.java
blob47920119f67740ee8b11b1ca91d8f31114b931c0
1 /* VMClassLoader.java -- Reference implementation of compiler interface
2 Copyright (C) 2004, 2005 Free Software Foundation
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package java.lang;
40 import java.io.File;
41 import java.io.FileOutputStream;
42 import java.io.InputStreamReader;
43 import java.security.MessageDigest;
44 import java.security.ProtectionDomain;
45 import java.security.NoSuchAlgorithmException;
46 import java.util.WeakHashMap;
47 import java.util.HashSet;
48 import java.util.Enumeration;
49 import java.util.StringTokenizer;
50 import java.util.Vector;
51 import gnu.gcj.runtime.SharedLibHelper;
52 import gnu.gcj.runtime.PersistentByteMap;
54 /**
55 * This class is just a per-VM reflection of java.lang.Compiler.
56 * All methods are defined identically.
58 final class VMCompiler
60 // True if we want to use gcj-jit.
61 public static boolean useCompiler = true;
63 // True if we're able to use gcj-jit.
64 public static final boolean canUseCompiler;
66 // Compiler to use.
67 public static String gcjJitCompiler;
69 // Compiler options.
70 public static String gcjJitCompilerOptions;
72 // Temporary directory to use.
73 public static String gcjJitTmpdir;
75 // This maps a ClassLoader to a set of SharedLibHelper objects that
76 // it has used. We do things this way to ensure that a
77 // SharedLibHelper is collected if and only if the ClassLoader is.
78 private static WeakHashMap sharedHelperMap = new WeakHashMap();
80 private static Vector precompiledMapFiles;
82 // We create a single MD5 engine and then clone it whenever we want
83 // a new one.
85 // We don't use
87 // md5Digest = MessageDigest.getInstance("MD5");
89 // here because that loads a great deal of security provider code as
90 // interpreted bytecode -- before we're able to use this class to
91 // load precompiled classes.
93 private static final MessageDigest md5Digest
94 = new gnu.java.security.provider.MD5();
96 static
98 gcjJitCompiler = System.getProperty("gnu.gcj.jit.compiler");
99 if (gcjJitCompiler == null)
100 canUseCompiler = false;
101 else
103 gcjJitCompilerOptions = System.getProperty("gnu.gcj.jit.options",
104 "-g");
105 gcjJitTmpdir = System.getProperty("gnu.gcj.jit.cachedir");
106 // Note that we *don't* choose java.io.tmpdir as a default --
107 // that would allow easy attacks against the VM.
108 if (gcjJitTmpdir == null)
109 canUseCompiler = false;
110 else
111 canUseCompiler = true;
114 String prop = System.getProperty ("gnu.gcj.precompiled.db.path");
115 if (prop != null)
117 precompiledMapFiles = new Vector();
118 // Add the
119 StringTokenizer st
120 = new StringTokenizer (prop,
121 System.getProperty ("path.separator", ":"));
123 while (st.hasMoreElements ())
125 String e = st.nextToken ();
128 PersistentByteMap map
129 = new PersistentByteMap
130 (e, PersistentByteMap.AccessMode.READ_ONLY);
131 precompiledMapFiles.add(map);
133 catch (IllegalArgumentException _)
135 // Not a map file
137 catch (java.io.IOException _)
140 catch (java.nio.BufferUnderflowException _)
142 // Invalid map file.
150 * Don't allow new `Compiler's to be made.
152 private VMCompiler()
156 private static Class loadSharedLibrary(ClassLoader loader,
157 String fileName,
158 ProtectionDomain domain,
159 String className)
161 Class c = null;
162 SharedLibHelper helper
163 = SharedLibHelper.findHelper (loader, fileName, domain.getCodeSource(),
164 domain, false);
165 c = helper.findClass (className);
166 if (c != null)
168 HashSet hs = (HashSet) sharedHelperMap.get(loader);
169 if (hs == null)
171 hs = new HashSet();
172 sharedHelperMap.put(loader, hs);
174 hs.add(helper);
176 return c;
180 * Compile a class given the bytes for it. Returns the Class, or
181 * null if compilation failed or otherwise could not be done.
183 public static Class compileClass(ClassLoader loader,
184 String name, byte[] data,
185 int offset, int len,
186 ProtectionDomain domain)
188 if (precompiledMapFiles == null
189 && (! useCompiler || ! canUseCompiler))
190 return null;
192 byte digest[];
196 MessageDigest md = (MessageDigest) md5Digest.clone();
197 digest = md.digest(data);
199 catch (CloneNotSupportedException _)
201 // Can't happen.
202 return null;
204 catch (NullPointerException _)
206 // If md5Digest==null -- but really this should never happen
207 // either, since the MD5 digest is in libgcj.
208 return null;
211 // We use lookaside cache files to determine whether these bytes
212 // correspond to a class file that is part of a precompiled DSO.
213 if (precompiledMapFiles != null)
217 Enumeration elements = precompiledMapFiles.elements();
218 while (elements.hasMoreElements())
220 PersistentByteMap map = (PersistentByteMap)elements.nextElement();
221 byte[] soName = map.get(digest);
222 if (soName != null)
223 return loadSharedLibrary(loader,
224 new String(soName),
225 domain, name);
228 catch (Exception _)
231 catch (UnknownError _)
233 // SharedLibHelper will throw UnknownError if the dlopen
234 // fails for some reason. We ignore it and continue on.
238 if (! useCompiler || ! canUseCompiler)
239 return null;
243 // FIXME: Make sure that the class represented by the
244 // bytes in DATA really is the class named in NAME. Make
245 // sure it's not "java.*".
246 StringBuffer hexBytes = new StringBuffer(gcjJitTmpdir);
247 hexBytes.append(File.separatorChar);
248 int digestLength = digest.length;
249 for (int i = 0; i < digestLength; ++i)
250 hexBytes.append(Integer.toHexString(digest[i] & 0xff));
252 // FIXME: use System.mapLibraryName?
253 // I'm thinking we should use that, plus a class specified
254 // via a property that determines lookup policy.
255 File soFile = new File(hexBytes + ".so");
256 if (soFile.isFile())
257 return loadSharedLibrary (loader, soFile.toString(), domain,
258 name);
260 File classFile = new File(hexBytes + ".class");
261 classFile.delete();
262 if (classFile.createNewFile() != true)
263 return null;
265 FileOutputStream f = new FileOutputStream (classFile);
266 // FIXME: race condition if bytes change... ?
267 f.write(data, offset, len);
269 // Invoke the compiler.
270 StringBuffer command = new StringBuffer(gcjJitCompiler);
271 command.append(" ");
272 command.append(classFile);
273 command.append(" ");
274 command.append(gcjJitCompilerOptions);
275 // These options are required.
276 command.append(" -findirect-dispatch -fjni -shared -fPIC -o ");
277 command.append(soFile);
278 Process p = Runtime.getRuntime().exec(command.toString());
280 // Read the process' stderr into a string.
281 StringBuffer err = new StringBuffer();
282 InputStreamReader stderr = new InputStreamReader (p.getErrorStream());
283 char[] inBuf = new char[500];
284 int bytesRead;
285 while ((bytesRead = stderr.read (inBuf)) != -1)
286 err.append(inBuf, 0, bytesRead);
288 if (p.waitFor() != 0)
290 // FIXME: we could log err.toString() somewhere...
291 return null;
294 return loadSharedLibrary(loader, soFile.toString(), domain, name);
296 catch (Exception _)
298 return null;
303 * Compile the class named by <code>oneClass</code>.
305 * @param oneClass the class to compile
306 * @return <code>false</code> if no compiler is available or
307 * compilation failed, <code>true</code> if compilation succeeded
308 * @throws NullPointerException if oneClass is null
310 public static boolean compileClass(Class oneClass)
312 // Never succeed.
313 return false;
317 * Compile the classes whose name matches <code>classNames</code>.
319 * @param classNames the name of classes to compile
320 * @return <code>false</code> if no compiler is available or
321 * compilation failed, <code>true</code> if compilation succeeded
322 * @throws NullPointerException if classNames is null
324 public static boolean compileClasses(String classNames)
326 // Note the incredibly lame interface. Always fail.
327 return false;
331 * This method examines the argument and performs an operation
332 * according to the compilers documentation. No specific operation
333 * is required.
335 * @param arg a compiler-specific argument
336 * @return a compiler-specific value, including null
337 * @throws NullPointerException if the compiler doesn't like a null arg
339 public static Object command(Object arg)
341 // Our implementation defines this to a no-op.
342 return null;
346 * Calling <code>Compiler.enable()</code> will cause the compiler
347 * to resume operation if it was previously disabled; provided that a
348 * compiler even exists.
350 public static void enable()
352 useCompiler = true;
356 * Calling <code>Compiler.disable()</code> will cause the compiler
357 * to be suspended; provided that a compiler even exists.
359 public static void disable()
361 useCompiler = false;