OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [java/] [lang/] [VMCompiler.java] - Blame information for rev 758

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 758 jeremybenn
/* VMClassLoader.java -- Reference implementation of compiler interface
2
   Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation
3
 
4
This file is part of GNU Classpath.
5
 
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.
10
 
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.
15
 
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.
20
 
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.
25
 
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. */
37
 
38
package java.lang;
39
 
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;
53
import gnu.java.security.hash.MD5;
54
 
55
/**
56
 * This class is just a per-VM reflection of java.lang.Compiler.
57
 * All methods are defined identically.
58
 */
59
final class VMCompiler
60
{
61
  // True if we want to use gcj-jit.
62
  public static boolean useCompiler = true;
63
 
64
  // True if we're able to use gcj-jit.
65
  public static final boolean canUseCompiler;
66
 
67
  // Compiler to use.
68
  public static String gcjJitCompiler;
69
 
70
  // Compiler options.
71
  public static String gcjJitCompilerOptions;
72
 
73
  // Temporary directory to use.
74
  public static String gcjJitTmpdir;
75
 
76
  public static boolean precompiles()
77
  {
78
    return (canUseCompiler & useCompiler);
79
  }
80
 
81
  // This maps a ClassLoader to a set of SharedLibHelper objects that
82
  // it has used.  We do things this way to ensure that a
83
  // SharedLibHelper is collected if and only if the ClassLoader is.
84
  private static WeakHashMap sharedHelperMap = new WeakHashMap();
85
 
86
  private static Vector precompiledMapFiles;
87
 
88
  // We create a single MD5 engine and then clone it whenever we want
89
  // a new one.
90
 
91
  // We don't use 
92
  //
93
  // md5Digest = MessageDigest.getInstance("MD5");
94
  //
95
  // here because that loads a great deal of security provider code as
96
  // interpreted bytecode -- before we're able to use this class to
97
  // load precompiled classes.
98
 
99
  private static final MD5 md5Digest
100
    = new gnu.java.security.hash.MD5();
101
 
102
  static
103
  {
104
    gcjJitCompiler = System.getProperty("gnu.gcj.jit.compiler");
105
    if (gcjJitCompiler == null)
106
      canUseCompiler = false;
107
    else
108
      {
109
        gcjJitCompilerOptions = System.getProperty("gnu.gcj.jit.options",
110
                                                   "-g");
111
        gcjJitTmpdir = System.getProperty("gnu.gcj.jit.cachedir");
112
        // Note that we *don't* choose java.io.tmpdir as a default --
113
        // that would allow easy attacks against the VM.
114
        if (gcjJitTmpdir == null)
115
          canUseCompiler = false;
116
        else
117
          canUseCompiler = true;
118
      }
119
 
120
    String prop = System.getProperty ("gnu.gcj.precompiled.db.path");
121
    if (prop != null)
122
      {
123
        precompiledMapFiles = new Vector();
124
        // Add the 
125
        StringTokenizer st
126
          = new StringTokenizer (prop,
127
                                 System.getProperty ("path.separator", ":"));
128
        {
129
          while (st.hasMoreElements ())
130
            {
131
              String e = st.nextToken ();
132
              try
133
                {
134
                  PersistentByteMap map
135
                    = new PersistentByteMap
136
                    (e, PersistentByteMap.AccessMode.READ_ONLY);
137
                  precompiledMapFiles.add(map);
138
                }
139
              catch (IllegalArgumentException _)
140
                {
141
                  // Not a map file           
142
                }
143
              catch (java.io.IOException _)
144
                {
145
                }
146
              catch (java.nio.BufferUnderflowException _)
147
                {
148
                  // Invalid map file.
149
                }
150
            }
151
        }
152
      }
153
  }
154
 
155
  /**
156
   * Don't allow new `Compiler's to be made.
157
   */
158
  private VMCompiler()
159
  {
160
  }
161
 
162
  private static Class loadSharedLibrary(ClassLoader loader,
163
                                         String fileName,
164
                                         ProtectionDomain domain,
165
                                         String className)
166
  {
167
    Class c = null;
168
    SharedLibHelper helper
169
        = SharedLibHelper.findHelper (loader, fileName, domain.getCodeSource(),
170
                                      domain, false);
171
    c = helper.findClass (className);
172
    if (c != null)
173
      {
174
        HashSet hs = (HashSet) sharedHelperMap.get(loader);
175
        if (hs == null)
176
          {
177
            hs = new HashSet();
178
            sharedHelperMap.put(loader, hs);
179
          }
180
        hs.add(helper);
181
      }
182
    return c;
183
  }
184
 
185
  /**
186
   * Compile a class given the bytes for it.  Returns the Class, or
187
   * null if compilation failed or otherwise could not be done.
188
   */
189
  public static Class compileClass(ClassLoader loader,
190
                                   String name, byte[] data,
191
                                   int offset, int len,
192
                                   ProtectionDomain domain)
193
  {
194
    if (precompiledMapFiles == null && !precompiles())
195
      return null;
196
 
197
    byte digest[];
198
 
199
    try
200
      {
201
        MD5 md = (MD5) md5Digest.clone();
202
        md.update(data);
203
        digest = md.digest();
204
      }
205
    catch (NullPointerException _)
206
      {
207
        // If md5Digest==null -- but really this should never happen
208
        // either, since the MD5 digest is in libgcj.
209
        return null;
210
      }
211
 
212
    // We use lookaside cache files to determine whether these bytes
213
    // correspond to a class file that is part of a precompiled DSO.
214
    if (precompiledMapFiles != null)
215
      {
216
        try
217
          {
218
            Enumeration elements = precompiledMapFiles.elements();
219
            while (elements.hasMoreElements())
220
              {
221
                PersistentByteMap map = (PersistentByteMap)elements.nextElement();
222
                byte[] soName = map.get(digest);
223
                if (soName != null)
224
                  return loadSharedLibrary(loader,
225
                                           new String(soName),
226
                                           domain, name);
227
              }
228
          }
229
        catch (Exception _)
230
          {
231
          }
232
        catch (UnknownError _)
233
          {
234
            // SharedLibHelper will throw UnknownError if the dlopen
235
            // fails for some reason.  We ignore it and continue on.
236
          }
237
      }
238
 
239
    if (!precompiles())
240
      return null;
241
 
242
    try
243
      {
244
        // FIXME: Make sure that the class represented by the
245
        // bytes in DATA really is the class named in NAME.  Make
246
        // sure it's not "java.*".
247
        StringBuffer hexBytes = new StringBuffer(gcjJitTmpdir);
248
        hexBytes.append(File.separatorChar);
249
        int digestLength = digest.length;
250
        for (int i = 0; i < digestLength; ++i)
251
          {
252
            int v = digest[i] & 0xff;
253
            if (v < 16)
254
              hexBytes.append('0');
255
            hexBytes.append(Integer.toHexString(v));
256
          }
257
 
258
        // FIXME: use System.mapLibraryName?
259
        // I'm thinking we should use that, plus a class specified
260
        // via a property that determines lookup policy.
261
        File soFile = new File(hexBytes + ".so");
262
        if (soFile.isFile())
263
          return loadSharedLibrary (loader, soFile.toString(), domain,
264
                                    name);
265
 
266
        File classFile = new File(hexBytes + ".class");
267
        classFile.delete();
268
        if (classFile.createNewFile() != true)
269
          return null;
270
 
271
        FileOutputStream f = new FileOutputStream (classFile);
272
        // FIXME: race condition if bytes change... ?
273
        f.write(data, offset, len);
274
 
275
        // Invoke the compiler.
276
        StringBuffer command = new StringBuffer(gcjJitCompiler);
277
        command.append(" ");
278
        command.append(classFile);
279
        command.append(" ");
280
        command.append(gcjJitCompilerOptions);
281
        // These options are required.
282
        command.append(" -findirect-dispatch -fjni -shared -fPIC -o ");
283
        command.append(soFile);
284
        Process p = Runtime.getRuntime().exec(command.toString());
285
 
286
        // Read the process' stderr into a string.
287
        StringBuffer err = new StringBuffer();
288
        InputStreamReader stderr = new InputStreamReader (p.getErrorStream());
289
        char[] inBuf = new char[500];
290
        int bytesRead;
291
        while ((bytesRead = stderr.read (inBuf)) != -1)
292
          err.append(inBuf, 0, bytesRead);
293
 
294
        if (p.waitFor() != 0)
295
          {
296
            // FIXME: we could log err.toString() somewhere...
297
            return null;
298
          }
299
 
300
        return loadSharedLibrary(loader, soFile.toString(), domain, name);
301
      }
302
    catch (Exception _)
303
      {
304
        return null;
305
      }
306
  }
307
 
308
  /**
309
   * Compile the class named by <code>oneClass</code>.
310
   *
311
   * @param oneClass the class to compile
312
   * @return <code>false</code> if no compiler is available or
313
   *         compilation failed, <code>true</code> if compilation succeeded
314
   * @throws NullPointerException if oneClass is null
315
   */
316
  public static boolean compileClass(Class oneClass)
317
  {
318
    // Never succeed.
319
    return false;
320
  }
321
 
322
  /**
323
   * Compile the classes whose name matches <code>classNames</code>.
324
   *
325
   * @param classNames the name of classes to compile
326
   * @return <code>false</code> if no compiler is available or
327
   *         compilation failed, <code>true</code> if compilation succeeded
328
   * @throws NullPointerException if classNames is null
329
   */
330
  public static boolean compileClasses(String classNames)
331
  {
332
    // Note the incredibly lame interface.  Always fail.
333
    return false;
334
  }
335
 
336
  /**
337
   * This method examines the argument and performs an operation
338
   * according to the compilers documentation.  No specific operation
339
   * is required.
340
   *
341
   * @param arg a compiler-specific argument
342
   * @return a compiler-specific value, including null
343
   * @throws NullPointerException if the compiler doesn't like a null arg
344
   */
345
  public static Object command(Object arg)
346
  {
347
    // Our implementation defines this to a no-op.
348
    return null;
349
  }
350
 
351
  /**
352
   * Calling <code>Compiler.enable()</code> will cause the compiler
353
   * to resume operation if it was previously disabled; provided that a
354
   * compiler even exists.
355
   */
356
  public static void enable()
357
  {
358
    useCompiler = true;
359
  }
360
 
361
  /**
362
   * Calling <code>Compiler.disable()</code> will cause the compiler
363
   * to be suspended; provided that a compiler even exists.
364
   */
365
  public static void disable()
366
  {
367
    useCompiler = false;
368
  }
369
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.