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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [java/] [lang/] [VMCompiler.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* VMClassLoader.java -- Reference implementation of compiler interface
2
   Copyright (C) 2004, 2005 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
 
54
/**
55
 * This class is just a per-VM reflection of java.lang.Compiler.
56
 * All methods are defined identically.
57
 */
58
final class VMCompiler
59
{
60
  // True if we want to use gcj-jit.
61
  public static boolean useCompiler = true;
62
 
63
  // True if we're able to use gcj-jit.
64
  public static final boolean canUseCompiler;
65
 
66
  // Compiler to use.
67
  public static String gcjJitCompiler;
68
 
69
  // Compiler options.
70
  public static String gcjJitCompilerOptions;
71
 
72
  // Temporary directory to use.
73
  public static String gcjJitTmpdir;
74
 
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();
79
 
80
  private static Vector precompiledMapFiles;
81
 
82
  // We create a single MD5 engine and then clone it whenever we want
83
  // a new one.
84
 
85
  // We don't use 
86
  //
87
  // md5Digest = MessageDigest.getInstance("MD5");
88
  //
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.
92
 
93
  private static final MessageDigest md5Digest
94
    = new gnu.java.security.provider.MD5();
95
 
96
  static
97
  {
98
    gcjJitCompiler = System.getProperty("gnu.gcj.jit.compiler");
99
    if (gcjJitCompiler == null)
100
      canUseCompiler = false;
101
    else
102
      {
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;
112
      }
113
 
114
    String prop = System.getProperty ("gnu.gcj.precompiled.db.path");
115
    if (prop != null)
116
      {
117
        precompiledMapFiles = new Vector();
118
        // Add the 
119
        StringTokenizer st
120
          = new StringTokenizer (prop,
121
                                 System.getProperty ("path.separator", ":"));
122
        {
123
          while (st.hasMoreElements ())
124
            {
125
              String e = st.nextToken ();
126
              try
127
                {
128
                  PersistentByteMap map
129
                    = new PersistentByteMap
130
                    (e, PersistentByteMap.AccessMode.READ_ONLY);
131
                  precompiledMapFiles.add(map);
132
                }
133
              catch (IllegalArgumentException _)
134
                {
135
                  // Not a map file           
136
                }
137
              catch (java.io.IOException _)
138
                {
139
                }
140
              catch (java.nio.BufferUnderflowException _)
141
                {
142
                  // Invalid map file.
143
                }
144
            }
145
        }
146
      }
147
  }
148
 
149
  /**
150
   * Don't allow new `Compiler's to be made.
151
   */
152
  private VMCompiler()
153
  {
154
  }
155
 
156
  private static Class loadSharedLibrary(ClassLoader loader,
157
                                         String fileName,
158
                                         ProtectionDomain domain,
159
                                         String className)
160
  {
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)
167
      {
168
        HashSet hs = (HashSet) sharedHelperMap.get(loader);
169
        if (hs == null)
170
          {
171
            hs = new HashSet();
172
            sharedHelperMap.put(loader, hs);
173
          }
174
        hs.add(helper);
175
      }
176
    return c;
177
  }
178
 
179
  /**
180
   * Compile a class given the bytes for it.  Returns the Class, or
181
   * null if compilation failed or otherwise could not be done.
182
   */
183
  public static Class compileClass(ClassLoader loader,
184
                                   String name, byte[] data,
185
                                   int offset, int len,
186
                                   ProtectionDomain domain)
187
  {
188
    if (precompiledMapFiles == null
189
        && (! useCompiler || ! canUseCompiler))
190
      return null;
191
 
192
    byte digest[];
193
 
194
    try
195
      {
196
        MessageDigest md = (MessageDigest) md5Digest.clone();
197
        digest = md.digest(data);
198
      }
199
    catch (CloneNotSupportedException _)
200
      {
201
        // Can't happen.
202
        return null;
203
      }
204
    catch (NullPointerException _)
205
      {
206
        // If md5Digest==null -- but really this should never happen
207
        // either, since the MD5 digest is in libgcj.
208
        return null;
209
      }
210
 
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)
214
      {
215
        try
216
          {
217
            Enumeration elements = precompiledMapFiles.elements();
218
            while (elements.hasMoreElements())
219
              {
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);
226
              }
227
          }
228
        catch (Exception _)
229
          {
230
          }
231
        catch (UnknownError _)
232
          {
233
            // SharedLibHelper will throw UnknownError if the dlopen
234
            // fails for some reason.  We ignore it and continue on.
235
          }
236
      }
237
 
238
    if (! useCompiler || ! canUseCompiler)
239
      return null;
240
 
241
    try
242
      {
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));
251
 
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);
259
 
260
        File classFile = new File(hexBytes + ".class");
261
        classFile.delete();
262
        if (classFile.createNewFile() != true)
263
          return null;
264
 
265
        FileOutputStream f = new FileOutputStream (classFile);
266
        // FIXME: race condition if bytes change... ?
267
        f.write(data, offset, len);
268
 
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());
279
 
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);
287
 
288
        if (p.waitFor() != 0)
289
          {
290
            // FIXME: we could log err.toString() somewhere...
291
            return null;
292
          }
293
 
294
        return loadSharedLibrary(loader, soFile.toString(), domain, name);
295
      }
296
    catch (Exception _)
297
      {
298
        return null;
299
      }
300
  }
301
 
302
  /**
303
   * Compile the class named by <code>oneClass</code>.
304
   *
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
309
   */
310
  public static boolean compileClass(Class oneClass)
311
  {
312
    // Never succeed.
313
    return false;
314
  }
315
 
316
  /**
317
   * Compile the classes whose name matches <code>classNames</code>.
318
   *
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
323
   */
324
  public static boolean compileClasses(String classNames)
325
  {
326
    // Note the incredibly lame interface.  Always fail.
327
    return false;
328
  }
329
 
330
  /**
331
   * This method examines the argument and performs an operation
332
   * according to the compilers documentation.  No specific operation
333
   * is required.
334
   *
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
338
   */
339
  public static Object command(Object arg)
340
  {
341
    // Our implementation defines this to a no-op.
342
    return null;
343
  }
344
 
345
  /**
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.
349
   */
350
  public static void enable()
351
  {
352
    useCompiler = true;
353
  }
354
 
355
  /**
356
   * Calling <code>Compiler.disable()</code> will cause the compiler
357
   * to be suspended; provided that a compiler even exists.
358
   */
359
  public static void disable()
360
  {
361
    useCompiler = false;
362
  }
363
}

powered by: WebSVN 2.1.0

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