001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.jikesrvm;
014
015import static org.jikesrvm.runtime.ExitStatus.EXIT_STATUS_BOGUS_COMMAND_LINE_ARG;
016import static org.jikesrvm.runtime.ExitStatus.EXIT_STATUS_RECURSIVELY_SHUTTING_DOWN;
017import static org.jikesrvm.runtime.ExitStatus.EXIT_STATUS_SYSFAIL;
018
019import org.jikesrvm.adaptive.controller.Controller;
020import org.jikesrvm.adaptive.util.CompilerAdvice;
021import org.jikesrvm.architecture.StackFrameLayout;
022import org.jikesrvm.classloader.Atom;
023import org.jikesrvm.classloader.BootstrapClassLoader;
024import org.jikesrvm.classloader.JMXSupport;
025import org.jikesrvm.classloader.RVMClass;
026import org.jikesrvm.classloader.RVMClassLoader;
027import org.jikesrvm.classloader.RVMMember;
028import org.jikesrvm.classloader.MemberReference;
029import org.jikesrvm.classloader.RVMMethod;
030import org.jikesrvm.classloader.TypeDescriptorParsing;
031import org.jikesrvm.classloader.TypeReference;
032import org.jikesrvm.compilers.baseline.BaselineCompiler;
033import org.jikesrvm.compilers.common.BootImageCompiler;
034import org.jikesrvm.compilers.common.RuntimeCompiler;
035import org.jikesrvm.mm.mminterface.MemoryManager;
036import org.jikesrvm.runtime.BootRecord;
037import org.jikesrvm.runtime.Callbacks;
038import org.jikesrvm.runtime.CommandLineArgs;
039import org.jikesrvm.runtime.DynamicLibrary;
040import org.jikesrvm.runtime.Entrypoints;
041import org.jikesrvm.runtime.Magic;
042import org.jikesrvm.runtime.RuntimeEntrypoints;
043import org.jikesrvm.runtime.SysCall;
044import org.jikesrvm.runtime.Time;
045
046import static org.jikesrvm.runtime.SysCall.sysCall;
047
048import org.jikesrvm.scheduler.Lock;
049import org.jikesrvm.scheduler.MainThread;
050import org.jikesrvm.scheduler.Synchronization;
051import org.jikesrvm.scheduler.RVMThread;
052import org.jikesrvm.runtime.FileSystem;
053import org.jikesrvm.tuningfork.TraceEngine;
054import org.jikesrvm.util.Services;
055import org.vmmagic.pragma.Entrypoint;
056import org.vmmagic.pragma.Inline;
057import org.vmmagic.pragma.Interruptible;
058import org.vmmagic.pragma.NoInline;
059import org.vmmagic.pragma.Uninterruptible;
060import org.vmmagic.pragma.UninterruptibleNoWarn;
061import org.vmmagic.pragma.Unpreemptible;
062import org.vmmagic.pragma.UnpreemptibleNoWarn;
063import org.vmmagic.unboxed.Address;
064import org.vmmagic.unboxed.Extent;
065import org.vmmagic.unboxed.ObjectReference;
066import org.vmmagic.unboxed.Offset;
067import org.vmmagic.unboxed.Word;
068
069/**
070 * A virtual machine.
071 */
072@Uninterruptible
073public class VM extends Properties {
074
075  /**
076   * For assertion checking things that should never happen.
077   */
078  public static final boolean NOT_REACHED = false;
079
080  /**
081   * Reference to the main thread that is the first none VM thread run
082   */
083  public static MainThread mainThread;
084
085  //----------------------------------------------------------------------//
086  //                          Initialization.                             //
087  //----------------------------------------------------------------------//
088
089  /**
090   * Prepare VM classes for use by boot image writer.
091   * @param classPath class path to be used by RVMClassLoader
092   * @param bootCompilerArgs command line arguments for the bootimage compiler
093   */
094  @Interruptible
095  public static void initForBootImageWriter(String classPath, String[] bootCompilerArgs) {
096    if (VM.VerifyAssertions) VM._assert(!VM.runningVM);
097    if (VM.VerifyAssertions) VM._assert(!VM.runningTool);
098    writingBootImage = true;
099    init(classPath, bootCompilerArgs);
100  }
101
102  /**
103   * Prepare VM classes for use by tools.
104   */
105  @Interruptible
106  public static void initForTool() {
107    initForTool(System.getProperty("java.class.path"));
108  }
109
110  /**
111   * Prepare VM classes for use by tools.
112   * @param classpath class path to be used by RVMClassLoader
113   */
114  @Interruptible
115  public static void initForTool(String classpath) {
116    if (VM.VerifyAssertions) VM._assert(!VM.runningVM);
117    if (VM.VerifyAssertions) VM._assert(!VM.writingBootImage);
118    runningTool = true;
119    init(classpath, null);
120  }
121
122  /**
123   * Begin VM execution.<p>
124   *
125   * Uninterruptible because we are not setup to execute a yieldpoint
126   * or stackoverflow check in the prologue this early in booting.<p>
127   *
128   * The following machine registers are set by "C" bootstrap program
129   * before calling this method:
130   * <ol>
131   *   <li>JTOC_POINTER - required for accessing globals
132   *   <li>FRAME_POINTER - required for accessing locals
133   *   <li>THREAD_ID_REGISTER - required for method prolog (stack overflow check)
134   * </ol>
135   */
136  @UnpreemptibleNoWarn("No point threading until threading is booted")
137  @Entrypoint
138  public static void boot() {
139    writingBootImage = false;
140    runningVM = true;
141    verboseBoot = BootRecord.the_boot_record.verboseBoot;
142    verboseSignalHandling = BootRecord.the_boot_record.verboseSignalHandling != 0;
143
144    sysWriteLockOffset = Entrypoints.sysWriteLockField.getOffset();
145    if (verboseBoot >= 1) VM.sysWriteln("Booting");
146
147    // Set up the current RVMThread object.  The bootstrap program
148    // has placed a pointer to the current RVMThread in a special
149    // register.
150    if (verboseBoot >= 1) VM.sysWriteln("Setting up current RVMThread");
151    if (VM.BuildForIA32) {
152      org.jikesrvm.ia32.ThreadLocalState.boot();
153    } else {
154      if (VM.VerifyAssertions) VM._assert(VM.BuildForPowerPC);
155      org.jikesrvm.ppc.ThreadLocalState.boot();
156    }
157
158    // Finish thread initialization that couldn't be done in boot image.
159    // The "stackLimit" must be set before any interruptible methods are called
160    // because it's accessed by compiler-generated stack overflow checks.
161    //
162    if (verboseBoot >= 1) VM.sysWriteln("Doing thread initialization");
163    RVMThread currentThread = RVMThread.getCurrentThread();
164    currentThread.stackLimit = Magic.objectAsAddress(
165        currentThread.getStack()).plus(StackFrameLayout.getStackSizeGuard());
166
167    finishBooting();
168  }
169
170  /**
171   * Complete the task of booting Jikes RVM.
172   * Done in a secondary method mainly because this code
173   * doesn't have to be uninterruptible and this is the cleanest
174   * way to make that distinction.
175   */
176  @Interruptible
177  private static void finishBooting() {
178
179    // get pthread_id from OS and store into vm_processor field
180    //
181    RVMThread.getCurrentThread().pthread_id = sysCall.sysGetThreadId();
182    RVMThread.getCurrentThread().priority_handle = sysCall.sysGetThreadPriorityHandle();
183    RVMThread.availableProcessors = SysCall.sysCall.sysNumProcessors();
184
185    // Set up buffer locks used by Thread for logging and status dumping.
186    //    This can happen at any point before we start running
187    //    multi-threaded.
188    Services.boot();
189
190    // Initialize memory manager.
191    //    This must happen before any uses of "new".
192    //
193    if (verboseBoot >= 1) {
194      VM.sysWriteln("Setting up memory manager: bootrecord = ",
195                    Magic.objectAsAddress(BootRecord.the_boot_record));
196    }
197    MemoryManager.boot(BootRecord.the_boot_record);
198
199    // Reset the options for the baseline compiler to avoid carrying
200    // them over from bootimage writing time.
201    //
202    if (verboseBoot >= 1) VM.sysWriteln("Initializing baseline compiler options to defaults");
203    BaselineCompiler.initOptions();
204
205    // Fetch arguments from program command line.
206    //
207    if (verboseBoot >= 1) VM.sysWriteln("Fetching command-line arguments");
208    CommandLineArgs.fetchCommandLineArguments();
209
210    // Process most virtual machine command line arguments.
211    //
212    if (verboseBoot >= 1) VM.sysWriteln("Early stage processing of command line");
213    CommandLineArgs.earlyProcessCommandLineArguments();
214
215    // Early initialization of TuningFork tracing engine.
216    TraceEngine.engine.earlyStageBooting();
217
218    // Allow Memory Manager to respond to its command line arguments
219    //
220    if (verboseBoot >= 1) VM.sysWriteln("Collector processing rest of boot options");
221    MemoryManager.postBoot();
222
223    // Initialize class loader.
224    //
225    String bootstrapClasses = CommandLineArgs.getBootstrapClasses();
226    if (verboseBoot >= 1) VM.sysWriteln("Initializing bootstrap class loader: ", bootstrapClasses);
227    Callbacks.addClassLoadedMonitor(JMXSupport.CLASS_LOADING_JMX_SUPPORT);
228    RVMClassLoader.boot();      // Wipe out cached application class loader
229    BootstrapClassLoader.boot(bootstrapClasses);
230
231    // Initialize statics that couldn't be placed in bootimage, either
232    // because they refer to external state (open files), or because they
233    // appear in fields that are unique to Jikes RVM implementation of
234    // standard class library (not part of standard JDK).
235    // We discover the latter by observing "host has no field" and
236    // "object not part of bootimage" messages printed out by bootimage
237    // writer.
238    //
239    if (verboseBoot >= 1) VM.sysWriteln("Running various class initializers");
240
241    if (VM.BuildForGnuClasspath) {
242      runClassInitializer("java.util.WeakHashMap"); // Need for ThreadLocal
243    }
244    runClassInitializer("org.jikesrvm.classloader.Atom$InternedStrings");
245
246    if (VM.BuildForGnuClasspath) {
247      runClassInitializer("gnu.classpath.SystemProperties");
248      runClassInitializer("java.lang.Throwable$StaticData");
249    }
250
251    runClassInitializer("java.lang.Runtime");
252    runClassInitializer("java.lang.System");
253    runClassInitializer("sun.misc.Unsafe");
254
255    runClassInitializer("java.lang.Character");
256    runClassInitializer("org.jikesrvm.classloader.TypeReferenceVector");
257    runClassInitializer("org.jikesrvm.classloader.MethodVector");
258    runClassInitializer("org.jikesrvm.classloader.FieldVector");
259    // Turn off security checks; about to hit EncodingManager.
260    // Commented out because we haven't incorporated this into the CVS head
261    // yet.
262    // java.security.JikesRVMSupport.turnOffChecks();
263    if (VM.BuildForGnuClasspath) {
264      runClassInitializer("java.lang.ThreadGroup");
265    }
266    /* We can safely allocate a java.lang.Thread now.  The boot
267       thread (running right now, as a Thread) has to become a full-fledged
268       Thread, since we're about to encounter a security check:
269
270       EncodingManager checks a system property,
271        which means that the permissions checks have to be working,
272        which means that VMAccessController will be invoked,
273        which means that ThreadLocal.get() will be called,
274        which calls Thread.getCurrentThread().
275
276        So the boot Thread needs to be associated with a real Thread for
277        Thread.getCurrentThread() to return. */
278    VM.safeToAllocateJavaThread = true;
279
280    if (VM.BuildForGnuClasspath) {
281      runClassInitializer("java.lang.ThreadLocal");
282      runClassInitializer("java.lang.ThreadLocalMap");
283    }
284    // Possibly fix VMAccessController's contexts and inGetContext fields
285    if (VM.BuildForGnuClasspath) {
286      runClassInitializer("java.security.VMAccessController");
287    }
288    if (VM.BuildForHarmony) {
289      runClassInitializer("java.security.AccessController");
290    }
291    if (verboseBoot >= 1) VM.sysWriteln("Booting Lock");
292    Lock.boot();
293
294    // Enable multiprocessing.
295    // Among other things, after this returns, GC and dynamic class loading are enabled.
296    //
297    if (verboseBoot >= 1) VM.sysWriteln("Booting scheduler");
298    RVMThread.boot();
299    DynamicLibrary.boot();
300
301    if (verboseBoot >= 1) VM.sysWriteln("Enabling GC");
302    MemoryManager.enableCollection();
303
304    if (verboseBoot >= 1) VM.sysWriteln("Setting up boot thread");
305    RVMThread.getCurrentThread().setupBootJavaThread();
306
307    // Create JNI Environment for boot thread.
308    // After this point the boot thread can invoke native methods.
309    org.jikesrvm.jni.JNIEnvironment.boot();
310    if (verboseBoot >= 1) VM.sysWriteln("Initializing JNI for boot thread");
311    RVMThread.getCurrentThread().initializeJNIEnv();
312    if (verboseBoot >= 1) VM.sysWriteln("JNI initialized for boot thread");
313
314    if (VM.BuildForHarmony) {
315      System.loadLibrary("hyluni");
316      System.loadLibrary("hythr");
317      System.loadLibrary("hyniochar");
318    }
319    runClassInitializer("java.io.File"); // needed for when we initialize the
320    // system/application class loader.
321    runClassInitializer("java.lang.String");
322    if (VM.BuildForGnuClasspath) {
323      runClassInitializer("gnu.java.security.provider.DefaultPolicy");
324    }
325    runClassInitializer("java.net.URL"); // needed for URLClassLoader
326    /* Needed for ApplicationClassLoader, which in turn is needed by
327       VMClassLoader.getSystemClassLoader()  */
328    if (VM.BuildForGnuClasspath) {
329      runClassInitializer("java.net.URLClassLoader");
330    }
331    /* Used if we start up Jikes RVM with the -jar argument; that argument
332     * means that we need a working -jar before we can return an
333     * Application Class Loader. */
334    runClassInitializer("java.net.URLConnection");
335    if (VM.BuildForGnuClasspath) {
336      runClassInitializer("gnu.java.net.protocol.jar.Connection$JarFileCache");
337      runClassInitializer("java.lang.ClassLoader$StaticData");
338    }
339    runClassInitializer("java.lang.Class$StaticData");
340
341    runClassInitializer("java.nio.charset.Charset");
342    if (VM.BuildForGnuClasspath) {
343      runClassInitializer("java.nio.charset.CharsetEncoder");
344    }
345    runClassInitializer("java.nio.charset.CoderResult");
346    if (VM.BuildForHarmony) {
347      runClassInitializer("org.apache.harmony.niochar.CharsetProviderImpl");
348    }
349
350    runClassInitializer("java.io.PrintWriter"); // Uses System.getProperty
351    System.setProperty("line.separator", "\n");
352    runClassInitializer("java.io.PrintStream"); // Uses System.getProperty
353    runClassInitializer("java.util.Locale");
354    runClassInitializer("java.util.ResourceBundle");
355    runClassInitializer("java.util.zip.CRC32");
356    if (VM.BuildForHarmony) {
357      System.loadLibrary("hyarchive");
358    }
359    runClassInitializer("java.util.zip.Inflater");
360    if (VM.BuildForGnuClasspath) {
361      runClassInitializer("java.util.zip.DeflaterHuffman");
362      runClassInitializer("java.util.zip.InflaterDynHeader");
363      runClassInitializer("java.util.zip.InflaterHuffmanTree");
364    }
365    // Run class initializers that require JNI
366    if (verboseBoot >= 1) VM.sysWriteln("Running late class initializers");
367    if (VM.BuildForGnuClasspath) {
368      System.loadLibrary("javaio");
369    }
370    runClassInitializer("java.lang.Math");
371    runClassInitializer("java.util.TreeMap");
372    if (VM.BuildForGnuClasspath) {
373      runClassInitializer("gnu.java.nio.VMChannel");
374      runClassInitializer("gnu.java.nio.FileChannelImpl");
375    }
376    runClassInitializer("java.io.FileDescriptor");
377    runClassInitializer("java.io.FilePermission");
378    runClassInitializer("java.util.jar.JarFile");
379    if (VM.BuildForGnuClasspath) {
380      runClassInitializer("java.util.zip.ZipFile$PartialInputStream");
381    }
382    runClassInitializer("java.util.zip.ZipFile");
383    if (VM.BuildForHarmony) {
384      runClassInitializer("java.util.Hashtable");
385      runClassInitializer("java.util.jar.Manifest");
386      runClassInitializer("java.util.jar.Attributes$Name");
387      runClassInitializer("java.util.BitSet");
388      runClassInitializer("java.util.regex.Matcher");
389      runClassInitializer("java.util.regex.Pattern");
390      runClassInitializer("org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnection");
391      runClassInitializer("org.apache.harmony.luni.platform.OSMemory");
392      runClassInitializer("org.apache.harmony.luni.platform.Platform");
393      runClassInitializer("org.apache.harmony.luni.platform.AbstractMemorySpy");
394      runClassInitializer("org.apache.harmony.luni.platform.PlatformAddress");
395      runClassInitializer("org.apache.harmony.nio.internal.FileChannelImpl");
396      runClassInitializer("com.ibm.icu.util.ULocale");
397      runClassInitializer("java.io.ObjectStreamClass");
398      runClassInitializer("java.io.ObjectStreamClass$OSCThreadLocalCache");
399      runClassInitializer("java.io.ObjectInputStream");
400      runClassInitializer("java.security.MessageDigest");
401    }
402    if (VM.BuildForGnuClasspath) {
403      runClassInitializer("java.lang.VMDouble");
404    }
405    runClassInitializer("java.util.PropertyPermission");
406    runClassInitializer("org.jikesrvm.classloader.RVMAnnotation");
407    runClassInitializer("java.lang.annotation.RetentionPolicy");
408    runClassInitializer("java.lang.annotation.ElementType");
409    runClassInitializer("java.lang.Thread$State");
410    if (VM.BuildForGnuClasspath) {
411      runClassInitializer("gnu.java.nio.charset.EncodingHelper");
412      runClassInitializer("java.lang.VMClassLoader");
413    }
414
415    if (verboseBoot >= 1) VM.sysWriteln("initializing standard streams");
416    // Initialize java.lang.System.out, java.lang.System.err, java.lang.System.in
417    FileSystem.initializeStandardStreams();
418
419    ///////////////////////////////////////////////////////////////
420    // The VM is now fully booted.                               //
421    // By this we mean that we can execute arbitrary Java code.  //
422    ///////////////////////////////////////////////////////////////
423    if (verboseBoot >= 1) VM.sysWriteln("VM is now fully booted");
424
425    // Inform interested subsystems that VM is fully booted.
426    VM.fullyBooted = true;
427    MemoryManager.fullyBootedVM();
428    org.jikesrvm.mm.mminterface.JMXSupport.fullyBootedVM();
429    BaselineCompiler.fullyBootedVM();
430    TraceEngine.engine.fullyBootedVM();
431
432    runClassInitializer("java.util.logging.Level");
433    if (VM.BuildForGnuClasspath) {
434      runClassInitializer("java.lang.reflect.Proxy");
435      runClassInitializer("java.lang.reflect.Proxy$ProxySignature");
436    }
437    runClassInitializer("java.util.logging.Logger");
438    if (VM.BuildForHarmony) {
439      Entrypoints.luni1.setObjectValueUnchecked(null, null);
440      Entrypoints.luni2.setObjectValueUnchecked(null, null);
441      Entrypoints.luni3.setObjectValueUnchecked(null, null);
442      Entrypoints.luni4.setObjectValueUnchecked(null, null);
443      Entrypoints.luni5.setObjectValueUnchecked(null, null);
444      Entrypoints.luni6.setObjectValueUnchecked(null, null);
445      //runClassInitializer("java.lang.String$ConsolePrintStream");
446      runClassInitializer("org.apache.harmony.luni.util.Msg");
447      runClassInitializer("org.apache.harmony.archive.internal.nls.Messages");
448      runClassInitializer("org.apache.harmony.luni.internal.nls.Messages");
449      runClassInitializer("org.apache.harmony.nio.internal.nls.Messages");
450      runClassInitializer("org.apache.harmony.niochar.internal.nls.Messages");
451      runClassInitializer("java.util.logging.LogManager");
452    }
453
454    // Initialize compiler that compiles dynamically loaded classes.
455    //
456    if (verboseBoot >= 1) VM.sysWriteln("Initializing runtime compiler");
457    RuntimeCompiler.boot();
458
459    // Process remainder of the VM's command line arguments.
460    if (verboseBoot >= 1) VM.sysWriteln("Late stage processing of command line");
461    String[] applicationArguments = CommandLineArgs.lateProcessCommandLineArguments();
462
463    if (VM.verboseClassLoading || verboseBoot >= 1) VM.sysWrite("[VM booted]\n");
464
465    if (VM.BuildForAdaptiveSystem) {
466      if (verboseBoot >= 1) VM.sysWriteln("Initializing adaptive system");
467      Controller.boot();
468    }
469
470    // The first argument must be a class name.
471    if (verboseBoot >= 1) VM.sysWriteln("Extracting name of class to execute");
472    if (applicationArguments.length == 0) {
473      pleaseSpecifyAClass();
474    }
475    if (applicationArguments.length > 0 && !TypeDescriptorParsing.isJavaClassName(applicationArguments[0])) {
476      VM.sysWrite("vm: \"");
477      VM.sysWrite(applicationArguments[0]);
478      VM.sysWrite("\" is not a legal Java class name.\n");
479      pleaseSpecifyAClass();
480    }
481
482    if (applicationArguments.length > 0 && applicationArguments[0].startsWith("-X")) {
483        VM.sysWrite("vm: \"");
484        VM.sysWrite(applicationArguments[0]);
485        VM.sysWrite("\" is not a recognized Jikes RVM command line argument.\n");
486        VM.sysExit(EXIT_STATUS_BOGUS_COMMAND_LINE_ARG);
487    }
488
489    if (verboseBoot >= 1) VM.sysWriteln("Initializing Application Class Loader");
490    RVMClassLoader.getApplicationClassLoader();
491    RVMClassLoader.declareApplicationClassLoaderIsReady();
492
493    if (verboseBoot >= 1) {
494      VM.sysWriteln("Turning back on security checks.  Letting people see the ApplicationClassLoader.");
495    }
496    // Turn on security checks again.
497    // Commented out because we haven't incorporated this into the main CVS
498    // tree yet.
499    // java.security.JikesRVMSupport.fullyBootedVM();
500
501    if (VM.BuildForGnuClasspath) {
502      runClassInitializer("java.lang.ClassLoader$StaticData");
503    }
504
505    if (VM.BuildForAdaptiveSystem) {
506      CompilerAdvice.postBoot();
507    }
508
509    // enable alignment checking
510    if (VM.AlignmentChecking) {
511      SysCall.sysCall.sysEnableAlignmentChecking();
512    }
513
514    Time.boot();
515
516    // Schedule "main" thread for execution.
517    if (verboseBoot >= 2) VM.sysWriteln("Creating main thread");
518    // Create main thread.
519    if (verboseBoot >= 1) VM.sysWriteln("Constructing mainThread");
520    mainThread = new MainThread(applicationArguments);
521
522    // Schedule "main" thread for execution.
523    if (verboseBoot >= 1) VM.sysWriteln("Starting main thread");
524    mainThread.start();
525
526    // End of boot thread.
527    //
528    if (VM.TraceThreads) RVMThread.trace("VM.boot", "completed - terminating");
529    if (verboseBoot >= 2) {
530      VM.sysWriteln("Boot sequence completed; finishing boot thread");
531    }
532
533    RVMThread.getCurrentThread().terminate();
534    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
535  }
536
537  @Interruptible
538  private static void pleaseSpecifyAClass() {
539    VM.sysWrite("vm: Please specify a class to execute.\n");
540    VM.sysWrite("vm:   You can invoke the VM with the \"-help\" flag for usage information.\n");
541    VM.sysExit(EXIT_STATUS_BOGUS_COMMAND_LINE_ARG);
542  }
543
544  /**
545   * Run {@code <clinit>} method of specified class, if that class appears
546   * in bootimage and actually has a clinit method (we are flexible to
547   * allow one list of classes to work with different bootimages and
548   * different version of classpath (eg 0.05 vs. cvs head).
549   * <p>
550   * This method is called only while the VM boots.
551   *
552   * @param className class whose initializer needs to be run
553   */
554  @Interruptible
555  static void runClassInitializer(String className) {
556    if (verboseBoot >= 2) {
557      sysWrite("running class initializer for ");
558      sysWriteln(className);
559    }
560    Atom classDescriptor = Atom.findOrCreateAsciiAtom(className.replace('.', '/')).descriptorFromClassName();
561    TypeReference tRef =
562        TypeReference.findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), classDescriptor);
563    RVMClass cls = (RVMClass) tRef.peekType();
564    if (null == cls) {
565      sysWrite("Failed to run class initializer for ");
566      sysWrite(className);
567      sysWriteln(" as the class does not exist.");
568    } else if (!cls.isInBootImage()) {
569      sysWrite("Failed to run class initializer for ");
570      sysWrite(className);
571      sysWriteln(" as the class is not in the boot image.");
572    } else {
573      RVMMethod clinit = cls.getClassInitializerMethod();
574      if (clinit != null) {
575        clinit.compile();
576        if (verboseBoot >= 10) VM.sysWriteln("invoking method " + clinit);
577        try {
578          Magic.invokeClassInitializer(clinit.getCurrentEntryCodeArray());
579        } catch (Error e) {
580          throw e;
581        } catch (Throwable t) {
582          ExceptionInInitializerError eieio =
583              new ExceptionInInitializerError(t);
584          throw eieio;
585        }
586        // <clinit> is no longer needed: reclaim space by removing references to it
587        clinit.invalidateCompiledMethod(clinit.getCurrentCompiledMethod());
588      } else {
589        if (verboseBoot >= 10) VM.sysWriteln("has no clinit method ");
590      }
591      cls.setAllFinalStaticJTOCEntries();
592    }
593  }
594
595  //----------------------------------------------------------------------//
596  //                         Execution environment.                       //
597  //----------------------------------------------------------------------//
598
599  /**
600   * Verify a runtime assertion (die w/traceback if assertion fails).<p>
601   *
602   * Note: code your assertion checks as
603   * {@code if (VM.VerifyAssertions) VM._assert(xxx);}
604   * @param b the assertion to verify
605   */
606  @Inline(value = Inline.When.AllArgumentsAreConstant)
607  public static void _assert(boolean b) {
608    _assert(b, null, null);
609  }
610
611  /**
612   * Verify a runtime assertion (die w/message and traceback if
613   * assertion fails).<p>
614   *
615   * Note: code your assertion checks as
616   * {@code if (VM.VerifyAssertions) VM._assert(xxx);}
617   *
618   * @param b the assertion to verify
619   * @param message the message to print if the assertion is false
620   */
621  @Inline(value = Inline.When.ArgumentsAreConstant, arguments = {0})
622  public static void _assert(boolean b, String message) {
623    _assert(b, message, null);
624  }
625
626  @Inline(value = Inline.When.ArgumentsAreConstant, arguments = {0})
627  public static void _assert(boolean b, String msg1, String msg2) {
628    if (!VM.VerifyAssertions) {
629      sysWriteln("vm: somebody forgot to conditionalize their call to assert with");
630      sysWriteln("vm: if (VM.VerifyAssertions)");
631      _assertionFailure("vm internal error: assert called when !VM.VerifyAssertions", null);
632    }
633    if (!b) _assertionFailure(msg1, msg2);
634  }
635
636  @NoInline
637  @UninterruptibleNoWarn("Interruptible code not reachable at runtime")
638  private static void _assertionFailure(String msg1, String msg2) {
639    if (msg1 == null && msg2 == null) {
640      msg1 = "vm internal error at:";
641    }
642    if (msg2 == null) {
643      msg2 = msg1;
644      msg1 = null;
645    }
646    if (VM.runningVM) {
647      if (msg1 != null) {
648        sysWrite(msg1);
649      }
650      sysFail(msg2);
651    }
652    throw new RuntimeException((msg1 != null ? msg1 : "") + msg2);
653  }
654
655  @SuppressWarnings({"unused", "CanBeFinal", "UnusedDeclaration"})
656  // accessed via EntryPoints
657  @Entrypoint
658  private static int sysWriteLock = 0;
659  private static Offset sysWriteLockOffset = Offset.max();
660
661  private static void swLock() {
662    if (sysWriteLockOffset.isMax()) return;
663    while (!Synchronization.testAndSet(Magic.getJTOC(), sysWriteLockOffset, 1)) {
664      ;
665    }
666  }
667
668  private static void swUnlock() {
669    if (sysWriteLockOffset.isMax()) return;
670    Synchronization.fetchAndStore(Magic.getJTOC(), sysWriteLockOffset, 0);
671  }
672
673  /**
674   * Low level print to console.
675   * @param value  what is printed
676   */
677  @NoInline
678  /* don't waste code space inlining these --dave */
679  private static void write(Atom value) {
680    value.sysWrite();
681  }
682
683  /**
684   * Low level print to console.
685   * @param value  what is printed
686   */
687  @NoInline
688  /* don't waste code space inlining these --dave */
689  public static void write(RVMMember value) {
690    write(value.getMemberRef());
691  }
692
693  /**
694   * Low level print to console.
695   * @param value  what is printed
696   */
697  @NoInline
698  /* don't waste code space inlining these --dave */
699  public static void write(MemberReference value) {
700    write(value.getType().getName());
701    write(".");
702    write(value.getName());
703    write(" ");
704    write(value.getDescriptor());
705  }
706
707  /**
708   * Low level print to console.
709   * @param value   what is printed
710   */
711  @NoInline
712  /* don't waste code space inlining these --dave */
713  public static void write(String value) {
714    if (value == null) {
715      write("null");
716    } else {
717      if (runningVM) {
718        char[] chars = java.lang.JikesRVMSupport.getBackingCharArray(value);
719        int numChars = java.lang.JikesRVMSupport.getStringLength(value);
720        int offset = java.lang.JikesRVMSupport.getStringOffset(value);
721        for (int i = 0; i < numChars; i++) {
722          write(chars[offset + i]);
723        }
724      } else {
725        writeNotRunningVM(value);
726      }
727    }
728  }
729  @UninterruptibleNoWarn("Interruptible code not reachable at runtime")
730  private static void writeNotRunningVM(String value) {
731    if (VM.VerifyAssertions) VM._assert(!VM.runningVM);
732    System.err.print(value);
733  }
734
735  /**
736   * Low level print to console.
737   * @param value character array that is printed
738   * @param len number of characters printed
739   */
740  @NoInline
741  /* don't waste code space inlining these --dave */
742  public static void write(char[] value, int len) {
743    for (int i = 0, n = len; i < n; ++i) {
744      if (runningVM) {
745        //  Avoid triggering a potential read barrier
746        write(Services.getArrayNoBarrier(value, i));
747      } else {
748        write(value[i]);
749      }
750    }
751  }
752
753  /**
754   * Low level print of a <code>char</code>to console.
755   * @param value       The character to print
756   */
757  @NoInline
758  /* don't waste code space inlining these --dave */
759  public static void write(char value) {
760    if (runningVM) {
761      sysCall.sysConsoleWriteChar(value);
762    } else {
763      writeNotRunningVM(value);
764    }
765  }
766  @UninterruptibleNoWarn("Interruptible code not reachable at runtime")
767  private static void writeNotRunningVM(char value) {
768    if (VM.VerifyAssertions) VM._assert(!VM.runningVM);
769    System.err.print(value);
770  }
771
772  /**
773   * Low level print of <code>double</code> to console.
774   *
775   * @param value               <code>double</code> to be printed
776   * @param postDecimalDigits   Number of decimal places
777   */
778  @NoInline
779  /* don't waste code space inlining these --dave */
780  public static void write(double value, int postDecimalDigits) {
781    if (runningVM) {
782      sysCall.sysConsoleWriteDouble(value, postDecimalDigits);
783    } else {
784      writeNotRunningVM(value);
785    }
786  }
787  @UninterruptibleNoWarn("Interruptible code not reachable at runtime")
788  private static void writeNotRunningVM(double value) {
789    if (VM.VerifyAssertions) VM._assert(!VM.runningVM);
790    System.err.print(value);
791  }
792
793  /**
794   * Low level print of an <code>int</code> to console.
795   * @param value       what is printed
796   */
797  @NoInline
798  /* don't waste code space inlining these --dave */
799  public static void write(int value) {
800    if (runningVM) {
801      int mode = (value < -(1 << 20) || value > (1 << 20)) ? 2 : 0; // hex only or decimal only
802      sysCall.sysConsoleWriteInteger(value, mode);
803    } else {
804      writeNotRunningVM(value);
805    }
806  }
807  @UninterruptibleNoWarn("Interruptible code not reachable at runtime")
808  private static void writeNotRunningVM(int value) {
809    if (VM.VerifyAssertions) VM._assert(!VM.runningVM);
810    System.err.print(value);
811  }
812
813  /**
814   * Low level print to console.
815   * @param value       What is printed, as hex only
816   */
817  @NoInline
818  /* don't waste code space inlining these --dave */
819  public static void writeHex(int value) {
820    if (runningVM) {
821      sysCall.sysConsoleWriteInteger(value, 2 /*just hex*/);
822    } else {
823      writeHexNotRunningVM(value);
824    }
825  }
826  @UninterruptibleNoWarn("Interruptible code not reachable at runtime")
827  private static void writeHexNotRunningVM(int value) {
828    if (VM.VerifyAssertions) VM._assert(!VM.runningVM);
829    System.err.print(Integer.toHexString(value));
830  }
831
832  /**
833   * Low level print to console.
834   * @param value       what is printed, as hex only
835   */
836  @NoInline
837  /* don't waste code space inlining these --dave */
838  public static void writeHex(long value) {
839    if (runningVM) {
840      sysCall.sysConsoleWriteLong(value, 2);
841    } else {
842      writeHexNotRunningVM(value);
843    }
844  }
845  @UninterruptibleNoWarn("Interruptible code not reachable at runtime")
846  private static void writeHexNotRunningVM(long value) {
847    if (VM.VerifyAssertions) VM._assert(!VM.runningVM);
848    System.err.print(Long.toHexString(value));
849  }
850
851  @NoInline
852  /* don't waste code space inlining these --dave */
853  public static void writeDec(Word value) {
854    if (VM.BuildFor32Addr) {
855      write(value.toInt());
856    } else {
857      write(value.toLong());
858    }
859  }
860
861  @NoInline
862  /* don't waste code space inlining these --dave */
863  public static void writeHex(Word value) {
864    if (VM.BuildFor32Addr) {
865      writeHex(value.toInt());
866    } else {
867      writeHex(value.toLong());
868    }
869  }
870
871  @NoInline
872  /* don't waste code space inlining these --dave */
873  public static void writeHex(Address value) {
874    writeHex(value.toWord());
875  }
876
877  @NoInline
878  /* don't waste code space inlining these --dave */
879  public static void writeHex(ObjectReference value) {
880    writeHex(value.toAddress().toWord());
881  }
882
883  @NoInline
884  /* don't waste code space inlining these --dave */
885  public static void writeHex(Extent value) {
886    writeHex(value.toWord());
887  }
888
889  @NoInline
890  /* don't waste code space inlining these --dave */
891  public static void writeHex(Offset value) {
892    writeHex(value.toWord());
893  }
894
895  /**
896   * Low level print to console.
897   * @param value       what is printed, as int only
898   */
899  @NoInline
900  /* don't waste code space inlining these --dave */
901  public static void writeInt(int value) {
902    if (runningVM) {
903      sysCall.sysConsoleWriteInteger(value, 0 /*just decimal*/);
904    } else {
905      writeNotRunningVM(value);
906    }
907  }
908  @UninterruptibleNoWarn("Interruptible code not reachable at runtime")
909  private static void writeNotRunningVM(long value) {
910    if (VM.VerifyAssertions) VM._assert(!VM.runningVM);
911    System.err.print(value);
912  }
913
914  /**
915   * Low level print to console.
916   * @param value   what is printed
917   */
918  @NoInline
919  /* don't waste code space inlining these --dave */
920  public static void write(long value) {
921    write(value, true);
922  }
923
924  /**
925   * Low level print to console.
926   * @param value   what is printed
927   * @param hexToo  how to print: true  - print as decimal followed by hex
928   *                              false - print as decimal only
929   */
930  @NoInline
931  /* don't waste code space inlining these --dave */
932  public static void write(long value, boolean hexToo) {
933    if (runningVM) {
934      sysCall.sysConsoleWriteLong(value, hexToo ? 1 : 0);
935    } else {
936      writeNotRunningVM(value);
937    }
938  }
939
940  @NoInline
941  /* don't waste code space inlining these --dave */
942  public static void writeField(int fieldWidth, String s) {
943    write(s);
944    int len = getStringLength(s);
945    while (fieldWidth > len++) write(" ");
946  }
947
948  @UninterruptibleNoWarn("Interruptible code not reachable at runtime")
949  private static int getStringLength(String s) {
950    if (VM.runningVM) {
951      return java.lang.JikesRVMSupport.getStringLength(s);
952    } else {
953      return s.length();
954    }
955  }
956  /**
957   * Low level print to console.
958   * @param value print value
959   * @param fieldWidth the number of characters that the output should contain. If the value
960   *  is too small, the output will be filled up with enough spaces, starting from the left
961   */
962  @NoInline
963  /* don't waste code space inlining these --dave */
964  public static void writeField(int fieldWidth, int value) {
965    int len = 1, temp = value;
966    if (temp < 0) {
967      len++;
968      temp = -temp;
969    }
970    while (temp >= 10) {
971      len++;
972      temp /= 10;
973    }
974    while (fieldWidth > len++) write(" ");
975    if (runningVM) {
976      sysCall.sysConsoleWriteInteger(value, 0);
977    } else {
978      writeNotRunningVM(value);
979    }
980  }
981
982  /**
983   * Low level print of the {@link Atom} <code>s</code> to the console.
984   * Left-fill with enough spaces to print at least <code>fieldWidth</code>
985   * characters
986   * @param fieldWidth  Minimum width to print.
987   * @param s       The {@link Atom} to print.
988   */
989  @NoInline
990  /* don't waste code space inlining these --dave */
991  public static void writeField(int fieldWidth, Atom s) {
992    int len = s.length();
993    while (fieldWidth > len++) write(" ");
994    write(s);
995  }
996
997  public static void writeln() {
998    write('\n');
999  }
1000
1001  public static void write(double d) {
1002    write(d, 2);
1003  }
1004
1005  public static void write(Word addr) {
1006    writeHex(addr);
1007  }
1008
1009  public static void write(Address addr) {
1010    writeHex(addr);
1011  }
1012
1013  public static void write(ObjectReference object) {
1014    writeHex(object);
1015  }
1016
1017  public static void write(Offset addr) {
1018    writeHex(addr);
1019  }
1020
1021  public static void write(Extent addr) {
1022    writeHex(addr);
1023  }
1024
1025  public static void write(boolean b) {
1026    write(b ? "true" : "false");
1027  }
1028
1029  /*
1030   * A group of multi-argument sysWrites with optional newline.  Externally visible methods.
1031   */
1032
1033  @NoInline
1034  public static void sysWrite(Atom a) {
1035    swLock();
1036    write(a);
1037    swUnlock();
1038  }
1039
1040  @NoInline
1041  public static void sysWriteln(Atom a) {
1042    swLock();
1043    write(a);
1044    write("\n");
1045    swUnlock();
1046  }
1047
1048  @NoInline
1049  public static void sysWrite(RVMMember m) {
1050    swLock();
1051    write(m);
1052    swUnlock();
1053  }
1054
1055  @NoInline
1056  public static void sysWrite(MemberReference mr) {
1057    swLock();
1058    write(mr);
1059    swUnlock();
1060  }
1061
1062  @NoInline
1063  public static void sysWriteln() {
1064    swLock();
1065    write("\n");
1066    swUnlock();
1067  }
1068
1069  @NoInline
1070  public static void sysWrite(char c) {
1071    write(c);
1072  }
1073
1074  @NoInline
1075  public static void sysWriteField(int w, int v) {
1076    swLock();
1077    writeField(w, v);
1078    swUnlock();
1079  }
1080
1081  @NoInline
1082  public static void sysWriteField(int w, String s) {
1083    swLock();
1084    writeField(w, s);
1085    swUnlock();
1086  }
1087
1088  @NoInline
1089  public static void sysWriteHex(int v) {
1090    swLock();
1091    writeHex(v);
1092    swUnlock();
1093  }
1094
1095  @NoInline
1096  public static void sysWriteHex(long v) {
1097    swLock();
1098    writeHex(v);
1099    swUnlock();
1100  }
1101
1102  @NoInline
1103  public static void sysWriteHex(Address v) {
1104    swLock();
1105    writeHex(v);
1106    swUnlock();
1107  }
1108
1109  @NoInline
1110  public static void sysWriteInt(int v) {
1111    swLock();
1112    writeInt(v);
1113    swUnlock();
1114  }
1115
1116  @NoInline
1117  public static void sysWriteLong(long v) {
1118    swLock();
1119    write(v, false);
1120    swUnlock();
1121  }
1122
1123  @NoInline
1124  public static void sysWrite(double d, int p) {
1125    swLock();
1126    write(d, p);
1127    swUnlock();
1128  }
1129
1130  @NoInline
1131  public static void sysWrite(double d) {
1132    swLock();
1133    write(d);
1134    swUnlock();
1135  }
1136
1137  @NoInline
1138  public static void sysWrite(String s) {
1139    swLock();
1140    write(s);
1141    swUnlock();
1142  }
1143
1144  @NoInline
1145  public static void sysWrite(char[] c, int l) {
1146    swLock();
1147    write(c, l);
1148    swUnlock();
1149  }
1150
1151  @NoInline
1152  public static void sysWrite(Address a) {
1153    swLock();
1154    write(a);
1155    swUnlock();
1156  }
1157
1158  @NoInline
1159  public static void sysWriteln(Address a) {
1160    swLock();
1161    write(a);
1162    writeln();
1163    swUnlock();
1164  }
1165
1166  @NoInline
1167  public static void sysWrite(ObjectReference o) {
1168    swLock();
1169    write(o);
1170    swUnlock();
1171  }
1172
1173  @NoInline
1174  public static void sysWriteln(ObjectReference o) {
1175    swLock();
1176    write(o);
1177    writeln();
1178    swUnlock();
1179  }
1180
1181  @NoInline
1182  public static void sysWrite(Offset o) {
1183    swLock();
1184    write(o);
1185    swUnlock();
1186  }
1187
1188  @NoInline
1189  public static void sysWriteln(Offset o) {
1190    swLock();
1191    write(o);
1192    writeln();
1193    swUnlock();
1194  }
1195
1196  @NoInline
1197  public static void sysWrite(Word w) {
1198    swLock();
1199    write(w);
1200    swUnlock();
1201  }
1202
1203  @NoInline
1204  public static void sysWriteln(Word w) {
1205    swLock();
1206    write(w);
1207    writeln();
1208    swUnlock();
1209  }
1210
1211  @NoInline
1212  public static void sysWrite(Extent e) {
1213    swLock();
1214    write(e);
1215    swUnlock();
1216  }
1217
1218  @NoInline
1219  public static void sysWriteln(Extent e) {
1220    swLock();
1221    write(e);
1222    writeln();
1223    swUnlock();
1224  }
1225
1226  @NoInline
1227  public static void sysWrite(boolean b) {
1228    swLock();
1229    write(b);
1230    swUnlock();
1231  }
1232
1233  @NoInline
1234  public static void sysWrite(int i) {
1235    swLock();
1236    write(i);
1237    swUnlock();
1238  }
1239
1240  @NoInline
1241  public static void sysWriteln(int i) {
1242    swLock();
1243    write(i);
1244    writeln();
1245    swUnlock();
1246  }
1247
1248  @NoInline
1249  public static void sysWriteln(double d) {
1250    swLock();
1251    write(d);
1252    writeln();
1253    swUnlock();
1254  }
1255
1256  @NoInline
1257  public static void sysWriteln(long l) {
1258    swLock();
1259    write(l);
1260    writeln();
1261    swUnlock();
1262  }
1263
1264  @NoInline
1265  public static void sysWriteln(boolean b) {
1266    swLock();
1267    write(b);
1268    writeln();
1269    swUnlock();
1270  }
1271
1272  @NoInline
1273  public static void sysWriteln(String s) {
1274    swLock();
1275    write(s);
1276    writeln();
1277    swUnlock();
1278  }
1279
1280  @NoInline
1281  public static void sysWriteln(String s, Atom a) {
1282    swLock();
1283    write(s);
1284    write(a);
1285    writeln();
1286    swUnlock();
1287  }
1288
1289  @NoInline
1290  public static void sysWrite(String s, int i) {
1291    swLock();
1292    write(s);
1293    write(i);
1294    swUnlock();
1295  }
1296
1297  @NoInline
1298  public static void sysWriteln(String s, int i) {
1299    swLock();
1300    write(s);
1301    write(i);
1302    writeln();
1303    swUnlock();
1304  }
1305
1306  @NoInline
1307  public static void sysWrite(String s, boolean b) {
1308    swLock();
1309    write(s);
1310    write(b);
1311    swUnlock();
1312  }
1313
1314  @NoInline
1315  public static void sysWriteln(String s, boolean b) {
1316    swLock();
1317    write(s);
1318    write(b);
1319    writeln();
1320    swUnlock();
1321  }
1322
1323  @NoInline
1324  public static void sysWrite(String s, double d) {
1325    swLock();
1326    write(s);
1327    write(d);
1328    swUnlock();
1329  }
1330
1331  @NoInline
1332  public static void sysWriteln(String s, double d) {
1333    swLock();
1334    write(s);
1335    write(d);
1336    writeln();
1337    swUnlock();
1338  }
1339
1340  @NoInline
1341  public static void sysWrite(double d, String s) {
1342    swLock();
1343    write(d);
1344    write(s);
1345    swUnlock();
1346  }
1347
1348  @NoInline
1349  public static void sysWriteln(double d, String s) {
1350    swLock();
1351    write(d);
1352    write(s);
1353    writeln();
1354    swUnlock();
1355  }
1356
1357  @NoInline
1358  public static void sysWrite(String s, long i) {
1359    swLock();
1360    write(s);
1361    write(i);
1362    swUnlock();
1363  }
1364
1365  @NoInline
1366  public static void sysWriteln(String s, long i) {
1367    swLock();
1368    write(s);
1369    write(i);
1370    writeln();
1371    swUnlock();
1372  }
1373
1374  @NoInline
1375  public static void sysWriteln(String s1, long i1,String s2, long i2) {
1376    swLock();
1377    write(s1);
1378    write(i1);
1379    write(s2);
1380    write(i2);
1381    writeln();
1382    swUnlock();
1383  }
1384
1385  @NoInline
1386  public static void sysWrite(int i, String s) {
1387    swLock();
1388    write(i);
1389    write(s);
1390    swUnlock();
1391  }
1392
1393  @NoInline
1394  public static void sysWriteln(int i, String s) {
1395    swLock();
1396    write(i);
1397    write(s);
1398    writeln();
1399    swUnlock();
1400  }
1401
1402  @NoInline
1403  public static void sysWrite(String s1, String s2) {
1404    swLock();
1405    write(s1);
1406    write(s2);
1407    swUnlock();
1408  }
1409
1410  @NoInline
1411  public static void sysWriteln(String s1, String s2) {
1412    swLock();
1413    write(s1);
1414    write(s2);
1415    writeln();
1416    swUnlock();
1417  }
1418
1419  @NoInline
1420  public static void sysWrite(String s, Address a) {
1421    swLock();
1422    write(s);
1423    write(a);
1424    swUnlock();
1425  }
1426
1427  @NoInline
1428  public static void sysWriteln(String s, Address a) {
1429    swLock();
1430    write(s);
1431    write(a);
1432    writeln();
1433    swUnlock();
1434  }
1435
1436  @NoInline
1437  public static void sysWrite(String s, ObjectReference r) {
1438    swLock();
1439    write(s);
1440    write(r);
1441    swUnlock();
1442  }
1443
1444  @NoInline
1445  public static void sysWriteln(String s, ObjectReference r) {
1446    swLock();
1447    write(s);
1448    write(r);
1449    writeln();
1450    swUnlock();
1451  }
1452
1453  @NoInline
1454  public static void sysWrite(String s, Offset o) {
1455    swLock();
1456    write(s);
1457    write(o);
1458    swUnlock();
1459  }
1460
1461  @NoInline
1462  public static void sysWriteln(String s, Offset o) {
1463    swLock();
1464    write(s);
1465    write(o);
1466    writeln();
1467    swUnlock();
1468  }
1469
1470  @NoInline
1471  public static void sysWrite(String s, Word w) {
1472    swLock();
1473    write(s);
1474    write(w);
1475    swUnlock();
1476  }
1477
1478  @NoInline
1479  public static void sysWriteln(String s, Word w) {
1480    swLock();
1481    write(s);
1482    write(w);
1483    writeln();
1484    swUnlock();
1485  }
1486
1487  @NoInline
1488  public static void sysWrite(String s1, String s2, Address a) {
1489    swLock();
1490    write(s1);
1491    write(s2);
1492    write(a);
1493    swUnlock();
1494  }
1495
1496  @NoInline
1497  public static void sysWrite(String s1, Address a, String s2) {
1498    swLock();
1499    write(s1);
1500    write(a);
1501    write(s2);
1502    swUnlock();
1503  }
1504
1505  @NoInline
1506  public static void sysWriteln(String s1, String s2, Address a) {
1507    swLock();
1508    write(s1);
1509    write(s2);
1510    write(a);
1511    writeln();
1512    swUnlock();
1513  }
1514
1515  @NoInline
1516  public static void sysWriteln(String s1, Address a,String s2) {
1517    swLock();
1518    write(s1);
1519    write(a);
1520    write(s2);
1521    writeln();
1522    swUnlock();
1523  }
1524  @NoInline
1525  public static void sysWriteln(String s1, Address a1,Address a2) {
1526    swLock();
1527    write(s1);
1528    write(a1);
1529    write(" ");
1530    write(a2);
1531    writeln();
1532    swUnlock();
1533  }
1534  @NoInline
1535  public static void sysWrite(String s1, String s2, int i) {
1536    swLock();
1537    write(s1);
1538    write(s2);
1539    write(i);
1540    swUnlock();
1541  }
1542
1543  @NoInline
1544  public static void sysWriteln(int i, Address a, RVMMethod m) {
1545    swLock();
1546    write(i);
1547    write(" ");
1548    write(a);
1549    write(" ");
1550    write(m.getDeclaringClass().getDescriptor());
1551    write(".");
1552    write(m.getName());
1553    write(m.getDescriptor());
1554    write("\n");
1555    swUnlock();
1556  }
1557
1558  @NoInline
1559  public static void sysWriteln(int i, Address a, Address b) {
1560    swLock();
1561    write(i);
1562    write(" ");
1563    write(a);
1564    write(" ");
1565    write(b);
1566    write("\n");
1567    swUnlock();
1568  }
1569
1570  @NoInline
1571  public static void sysWriteln(String s1, String s2, int i) {
1572    swLock();
1573    write(s1);
1574    write(s2);
1575    write(i);
1576    writeln();
1577    swUnlock();
1578  }
1579
1580  @NoInline
1581  public static void sysWrite(String s1, int i, String s2) {
1582    swLock();
1583    write(s1);
1584    write(i);
1585    write(s2);
1586    swUnlock();
1587  }
1588
1589  @NoInline
1590  public static void sysWriteln(String s1, int i, String s2) {
1591    swLock();
1592    write(s1);
1593    write(i);
1594    write(s2);
1595    writeln();
1596    swUnlock();
1597  }
1598
1599  @NoInline
1600  public static void sysWrite(String s1, Offset o, String s2) {
1601    swLock();
1602    write(s1);
1603    write(o);
1604    write(s2);
1605    swUnlock();
1606  }
1607
1608  @NoInline
1609  public static void sysWriteln(String s1, Offset o, String s2) {
1610    swLock();
1611    write(s1);
1612    write(o);
1613    write(s2);
1614    writeln();
1615    swUnlock();
1616  }
1617
1618  @NoInline
1619  public static void sysWrite(String s1, String s2, String s3) {
1620    swLock();
1621    write(s1);
1622    write(s2);
1623    write(s3);
1624    swUnlock();
1625  }
1626
1627  @NoInline
1628  public static void sysWriteln(String s1, String s2, String s3) {
1629    swLock();
1630    write(s1);
1631    write(s2);
1632    write(s3);
1633    writeln();
1634    swUnlock();
1635  }
1636
1637  @NoInline
1638  public static void sysWriteln(String s1, String s2, String s3, Address a) {
1639    swLock();
1640    write(s1);
1641    write(s2);
1642    write(s3);
1643    write(a);
1644    writeln();
1645    swUnlock();
1646  }
1647
1648  @NoInline
1649  public static void sysWrite(int i1, String s, int i2) {
1650    swLock();
1651    write(i1);
1652    write(s);
1653    write(i2);
1654    swUnlock();
1655  }
1656
1657  @NoInline
1658  public static void sysWriteln(int i1, String s, int i2) {
1659    swLock();
1660    write(i1);
1661    write(s);
1662    write(i2);
1663    writeln();
1664    swUnlock();
1665  }
1666
1667  @NoInline
1668  public static void sysWrite(int i1, String s1, String s2) {
1669    swLock();
1670    write(i1);
1671    write(s1);
1672    write(s2);
1673    swUnlock();
1674  }
1675
1676  @NoInline
1677  public static void sysWriteln(int i1, String s1, String s2) {
1678    swLock();
1679    write(i1);
1680    write(s1);
1681    write(s2);
1682    writeln();
1683    swUnlock();
1684  }
1685
1686  @NoInline
1687  public static void sysWriteln(String s1, int i1, String s2, String s3) {
1688    swLock();
1689    write(s1);
1690    write(i1);
1691    write(s2);
1692    write(s3);
1693    writeln();
1694    swUnlock();
1695  }
1696
1697  @NoInline
1698  public static void sysWrite(String s1, String s2, String s3, String s4) {
1699    swLock();
1700    write(s1);
1701    write(s2);
1702    write(s3);
1703    write(s4);
1704    swUnlock();
1705  }
1706
1707  @NoInline
1708  public static void sysWriteln(String s1, String s2, String s3, String s4) {
1709    swLock();
1710    write(s1);
1711    write(s2);
1712    write(s3);
1713    write(s4);
1714    writeln();
1715    swUnlock();
1716  }
1717
1718  @NoInline
1719  public static void sysWrite(String s1, String s2, String s3, String s4, String s5) {
1720    swLock();
1721    write(s1);
1722    write(s2);
1723    write(s3);
1724    write(s4);
1725    write(s5);
1726    swUnlock();
1727  }
1728
1729  @NoInline
1730  public static void sysWriteln(String s1, String s2, String s3, String s4, String s5) {
1731    swLock();
1732    write(s1);
1733    write(s2);
1734    write(s3);
1735    write(s4);
1736    write(s5);
1737    writeln();
1738    swUnlock();
1739  }
1740
1741  @NoInline
1742  public static void sysWriteln(String s1, int i, String s3, Address a, String s5) {
1743    swLock();
1744    write(s1);
1745    write(i);
1746    write(s3);
1747    write(a);
1748    write(s5);
1749    writeln();
1750    swUnlock();
1751  }
1752
1753  @NoInline
1754  public static void sysWriteln(int i, String s, Address a) {
1755    swLock();
1756    write(i);
1757    write(s);
1758    write(a);
1759    writeln();
1760    swUnlock();
1761  }
1762
1763  @NoInline
1764  public static void sysWrite(String s1, int i1, String s2, int i2) {
1765    swLock();
1766    write(s1);
1767    write(i1);
1768    write(s2);
1769    write(i2);
1770    swUnlock();
1771  }
1772
1773  @NoInline
1774  public static void sysWriteln(String s1, int i1, String s2, int i2) {
1775    swLock();
1776    write(s1);
1777    write(i1);
1778    write(s2);
1779    write(i2);
1780    writeln();
1781    swUnlock();
1782  }
1783
1784  @NoInline
1785  public static void sysWriteln(String s1, int i, String s2, Address a) {
1786    swLock();
1787    write(s1);
1788    write(i);
1789    write(s2);
1790    write(a);
1791    writeln();
1792    swUnlock();
1793  }
1794
1795  @NoInline
1796  public static void sysWriteln(String s1, int i, String s2, Word w) {
1797    swLock();
1798    write(s1);
1799    write(i);
1800    write(s2);
1801    write(w);
1802    writeln();
1803    swUnlock();
1804  }
1805
1806  @NoInline
1807  public static void sysWriteln(String s1, int i, String s2, double d) {
1808    swLock();
1809    write(s1);
1810    write(i);
1811    write(s2);
1812    write(d);
1813    writeln();
1814    swUnlock();
1815  }
1816
1817  @NoInline
1818  public static void sysWriteln(String s1, int i, String s2, Word w, String s3) {
1819    swLock();
1820    write(s1);
1821    write(i);
1822    write(s2);
1823    write(w);
1824    write(s3);
1825    writeln();
1826    swUnlock();
1827  }
1828
1829  @NoInline
1830  public static void sysWriteln(String s1, int i1, String s2, int i2, String s3) {
1831    swLock();
1832    write(s1);
1833    write(i1);
1834    write(s2);
1835    write(i2);
1836    write(s3);
1837    writeln();
1838    swUnlock();
1839  }
1840
1841  @NoInline
1842  public static void sysWriteln(String s1, int i1, String s2, int i2, String s3, int i3) {
1843    swLock();
1844    write(s1);
1845    write(i1);
1846    write(s2);
1847    write(i2);
1848    write(s3);
1849    write(i3);
1850    writeln();
1851    swUnlock();
1852  }
1853
1854  @NoInline
1855  public static void sysWrite(String s1, int i1, String s2, long l1) {
1856    swLock();
1857    write(s1);
1858    write(i1);
1859    write(s2);
1860    write(l1);
1861    swUnlock();
1862  }
1863
1864  @NoInline
1865  public static void sysWriteln(String s1, int i1, String s2, long l1) {
1866    swLock();
1867    write(s1);
1868    write(i1);
1869    write(s2);
1870    write(l1);
1871    writeln();
1872    swUnlock();
1873  }
1874
1875  @NoInline
1876  public static void sysWrite(String s1, Offset o, String s2, int i) {
1877    swLock();
1878    write(s1);
1879    write(o);
1880    write(s2);
1881    write(i);
1882    swUnlock();
1883  }
1884
1885  @NoInline
1886  public static void sysWriteln(String s1, Offset o, String s2, int i) {
1887    swLock();
1888    write(s1);
1889    write(o);
1890    write(s2);
1891    write(i);
1892    writeln();
1893    swUnlock();
1894  }
1895
1896  @NoInline
1897  public static void sysWrite(String s1, double d, String s2) {
1898    swLock();
1899    write(s1);
1900    write(d);
1901    write(s2);
1902    swUnlock();
1903  }
1904
1905  @NoInline
1906  public static void sysWriteln(String s1, double d, String s2) {
1907    swLock();
1908    write(s1);
1909    write(d);
1910    write(s2);
1911    writeln();
1912    swUnlock();
1913  }
1914
1915  @NoInline
1916  public static void sysWriteln(String s1, long l1, String s2, long l2, String s3) {
1917    swLock();
1918    write(s1);
1919    write(l1);
1920    write(s2);
1921    write(l2);
1922    write(s3);
1923    writeln();
1924    swUnlock();
1925  }
1926
1927  @NoInline
1928  public static void sysWrite(String s1, String s2, int i1, String s3) {
1929    swLock();
1930    write(s1);
1931    write(s2);
1932    write(i1);
1933    write(s3);
1934    swUnlock();
1935  }
1936
1937  @NoInline
1938  public static void sysWriteln(String s1, String s2, int i1, String s3) {
1939    swLock();
1940    write(s1);
1941    write(s2);
1942    write(i1);
1943    write(s3);
1944    writeln();
1945    swUnlock();
1946  }
1947
1948  @NoInline
1949  public static void sysWrite(String s1, String s2, String s3, int i1) {
1950    swLock();
1951    write(s1);
1952    write(s2);
1953    write(s3);
1954    write(i1);
1955    swUnlock();
1956  }
1957
1958  @NoInline
1959  public static void sysWriteln(String s1, String s2, String s3, int i1) {
1960    swLock();
1961    write(s1);
1962    write(s2);
1963    write(s3);
1964    write(i1);
1965    writeln();
1966    swUnlock();
1967  }
1968
1969  @NoInline
1970  public static void sysWrite(String s1, String s2, String s3, String s4, int i5, String s6) {
1971    swLock();
1972    write(s1);
1973    write(s2);
1974    write(s3);
1975    write(s4);
1976    write(i5);
1977    write(s6);
1978    swUnlock();
1979  }
1980
1981  @NoInline
1982  public static void sysWriteln(String s1, String s2, String s3, String s4, int i5, String s6) {
1983    swLock();
1984    write(s1);
1985    write(s2);
1986    write(s3);
1987    write(s4);
1988    write(i5);
1989    write(s6);
1990    writeln();
1991    swUnlock();
1992  }
1993
1994  @NoInline
1995  public static void sysWrite(int i, String s1, double d, String s2) {
1996    swLock();
1997    write(i);
1998    write(s1);
1999    write(d);
2000    write(s2);
2001    swUnlock();
2002  }
2003
2004  @NoInline
2005  public static void sysWriteln(int i, String s1, double d, String s2) {
2006    swLock();
2007    write(i);
2008    write(s1);
2009    write(d);
2010    write(s2);
2011    writeln();
2012    swUnlock();
2013  }
2014
2015  @NoInline
2016  public static void sysWrite(String s1, String s2, String s3, int i1, String s4) {
2017    swLock();
2018    write(s1);
2019    write(s2);
2020    write(s3);
2021    write(i1);
2022    write(s4);
2023    swUnlock();
2024  }
2025
2026  @NoInline
2027  public static void sysWriteln(String s1, String s2, String s3, int i1, String s4) {
2028    swLock();
2029    write(s1);
2030    write(s2);
2031    write(s3);
2032    write(i1);
2033    write(s4);
2034    writeln();
2035    swUnlock();
2036  }
2037
2038  @NoInline
2039  public static void sysWrite(String s1, Address a1, String s2, Address a2) {
2040    swLock();
2041    write(s1);
2042    write(a1);
2043    write(s2);
2044    write(a2);
2045    swUnlock();
2046  }
2047
2048  @NoInline
2049  public static void sysWriteln(String s1, Address a1, String s2, Address a2) {
2050    swLock();
2051    write(s1);
2052    write(a1);
2053    write(s2);
2054    write(a2);
2055    writeln();
2056    swUnlock();
2057  }
2058
2059  @NoInline
2060  public static void sysWrite(String s1, Address a, String s2, int i) {
2061    swLock();
2062    write(s1);
2063    write(a);
2064    write(s2);
2065    write(i);
2066    swUnlock();
2067  }
2068
2069  @NoInline
2070  public static void sysWriteln(String s1, Address a, String s2, int i) {
2071    swLock();
2072    write(s1);
2073    write(a);
2074    write(s2);
2075    write(i);
2076    writeln();
2077    swUnlock();
2078  }
2079
2080  @NoInline
2081  public static void sysWriteln(String s0, Address a1, String s1, Word w1, String s2, int i1, String s3, int i2, String s4, Word w2, String s5, int i3) {
2082    swLock();
2083    write(s0);
2084    write(a1);
2085    write(s1);
2086    write(w1);
2087    write(s2);
2088    write(i1);
2089    write(s3);
2090    write(i2);
2091    write(s4);
2092    write(w2);
2093    write(s5);
2094    write(i3);
2095    writeln();
2096    swUnlock();
2097  }
2098
2099  private static void showThread() {
2100    write("Thread ");
2101    write(RVMThread.getCurrentThread().getThreadSlot());
2102    write(": ");
2103  }
2104
2105  @NoInline
2106  public static void tsysWriteln(String s) {
2107    swLock();
2108    showThread();
2109    write(s);
2110    writeln();
2111    swUnlock();
2112  }
2113
2114  @NoInline
2115  public static void tsysWriteln(String s1, String s2, String s3, int i4, String s5, String s6) {
2116    swLock();
2117    showThread();
2118    write(s1);
2119    write(s2);
2120    write(s3);
2121    write(i4);
2122    write(s5);
2123    write(s6);
2124    writeln();
2125    swUnlock();
2126  }
2127
2128  @NoInline
2129  public static void tsysWriteln(String s1, String s2, String s3, String s4, String s5, String s6, String s7, int i8,
2130                                  String s9, String s10, String s11, String s12, String s13) {
2131    swLock();
2132    showThread();
2133    write(s1);
2134    write(s2);
2135    write(s3);
2136    write(s4);
2137    write(s5);
2138    write(s6);
2139    write(s7);
2140    write(i8);
2141    write(s9);
2142    write(s10);
2143    write(s11);
2144    write(s12);
2145    write(s13);
2146    writeln();
2147    swUnlock();
2148  }
2149
2150  @NoInline
2151  public static void tsysWriteln(String s1, String s2, String s3, String s4, String s5, String s6, String s7, int i8,
2152                                  String s9, String s10, String s11, String s12, String s13, int i14) {
2153    swLock();
2154    showThread();
2155    write(s1);
2156    write(s2);
2157    write(s3);
2158    write(s4);
2159    write(s5);
2160    write(s6);
2161    write(s7);
2162    write(i8);
2163    write(s9);
2164    write(s10);
2165    write(s11);
2166    write(s12);
2167    write(s13);
2168    write(i14);
2169    writeln();
2170    swUnlock();
2171  }
2172  @NoInline
2173  public static void tsysWrite(char[] c, int l) {
2174    swLock();
2175    showThread();
2176    write(c, l);
2177    swUnlock();
2178  }
2179
2180  @NoInline
2181  public static void tsysWriteln(Address a) {
2182    swLock();
2183    showThread();
2184    write(a);
2185    writeln();
2186    swUnlock();
2187  }
2188
2189  @NoInline
2190  public static void tsysWriteln(String s, int i) {
2191    swLock();
2192    showThread();
2193    write(s);
2194    write(i);
2195    writeln();
2196    swUnlock();
2197  }
2198
2199  @NoInline
2200  public static void tsysWriteln(String s, Address a) {
2201    swLock();
2202    showThread();
2203    write(s);
2204    write(a);
2205    writeln();
2206    swUnlock();
2207  }
2208
2209  @NoInline
2210  public static void tsysWriteln(String s1, Address a1, String s2, Address a2) {
2211    swLock();
2212    showThread();
2213    write(s1);
2214    write(a1);
2215    write(s2);
2216    write(a2);
2217    writeln();
2218    swUnlock();
2219  }
2220
2221  @NoInline
2222  public static void tsysWriteln(String s1, Address a1, String s2, Address a2, String s3, Address a3) {
2223    swLock();
2224    showThread();
2225    write(s1);
2226    write(a1);
2227    write(s2);
2228    write(a2);
2229    write(s3);
2230    write(a3);
2231    writeln();
2232    swUnlock();
2233  }
2234
2235  @NoInline
2236  public static void tsysWriteln(String s1, Address a1, String s2, Address a2, String s3, Address a3, String s4,
2237                                 Address a4) {
2238    swLock();
2239    showThread();
2240    write(s1);
2241    write(a1);
2242    write(s2);
2243    write(a2);
2244    write(s3);
2245    write(a3);
2246    write(s4);
2247    write(a4);
2248    writeln();
2249    swUnlock();
2250  }
2251
2252  @NoInline
2253  public static void tsysWriteln(String s1, Address a1, String s2, Address a2, String s3, Address a3, String s4,
2254                                 Address a4, String s5, Address a5) {
2255    swLock();
2256    showThread();
2257    write(s1);
2258    write(a1);
2259    write(s2);
2260    write(a2);
2261    write(s3);
2262    write(a3);
2263    write(s4);
2264    write(a4);
2265    write(s5);
2266    write(a5);
2267    writeln();
2268    swUnlock();
2269  }
2270
2271  /**
2272   * Produce a message requesting a bug report be submitted
2273   */
2274  @NoInline
2275  public static void bugReportMessage() {
2276    VM.sysWriteln("********************************************************************************");
2277    VM.sysWriteln("*                      Abnormal termination of Jikes RVM                       *\n" +
2278                  "* Jikes RVM terminated abnormally indicating a problem in the virtual machine. *\n" +
2279                  "* Jikes RVM relies on community support to get debug information. Help improve *\n" +
2280                  "* Jikes RVM for everybody by reporting this error. Please see:                 *\n" +
2281                  "*                    http://www.jikesrvm.org/ReportingBugs/                    *");
2282    VM.sysWriteln("********************************************************************************");
2283  }
2284
2285  /**
2286   * Exit virtual machine due to internal failure of some sort.
2287   * @param message  error message describing the problem
2288   */
2289  @NoInline
2290  public static void sysFail(String message) {
2291    handlePossibleRecursiveCallToSysFail(message);
2292
2293    // print a traceback and die
2294    if (!RVMThread.getCurrentThread().isCollectorThread()) {
2295      RVMThread.traceback(message);
2296    } else {
2297      VM.sysWriteln("Died in GC:");
2298      RVMThread.traceback(message);
2299      VM.sysWriteln("Virtual machine state:");
2300      RVMThread.dumpVirtualMachine();
2301    }
2302    bugReportMessage();
2303    if (VM.runningVM) {
2304      VM.shutdown(EXIT_STATUS_SYSFAIL);
2305    } else {
2306      VM.sysExit(EXIT_STATUS_SYSFAIL);
2307    }
2308    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
2309  }
2310
2311  /**
2312   * Exit virtual machine due to internal failure of some sort.  This
2313   * two-argument form is  needed for us to call before the VM's Integer class
2314   * is initialized.
2315   *
2316   * @param message  error message describing the problem
2317   * @param number  an integer to append to <code>message</code>.
2318   */
2319  @NoInline
2320  public static void sysFail(String message, int number) {
2321    handlePossibleRecursiveCallToSysFail(message, number);
2322
2323    // print a traceback and die
2324    RVMThread.traceback(message, number);
2325    bugReportMessage();
2326    if (VM.runningVM) {
2327      VM.shutdown(EXIT_STATUS_SYSFAIL);
2328    } else {
2329      VM.sysExit(EXIT_STATUS_SYSFAIL);
2330    }
2331    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
2332  }
2333
2334  /**
2335   * Exit virtual machine.
2336   * @param value  value to pass to host o/s
2337   */
2338  @NoInline
2339  @UninterruptibleNoWarn("We're never returning to the caller, so even though this code is preemptible it is safe to call from any context")
2340  public static void sysExit(int value) {
2341    handlePossibleRecursiveCallToSysExit();
2342
2343    if (VM.countThreadTransitions) {
2344      RVMThread.reportThreadTransitionCounts();
2345    }
2346
2347    if (Options.stackTraceAtExit) {
2348      VM.sysWriteln("[Here is the context of the call to VM.sysExit(", value, ")...:");
2349      VM.disableGC();
2350      RVMThread.dumpStack();
2351      VM.enableGC();
2352      VM.sysWriteln("... END context of the call to VM.sysExit]");
2353    }
2354    if (runningVM) {
2355      Callbacks.notifyExit(value);
2356      VM.shutdown(value);
2357    } else {
2358      System.exit(value);
2359    }
2360    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
2361  }
2362
2363  /**
2364   * Shut down the virtual machine.
2365   * Should only be called if the VM is running.
2366   * @param value  exit value
2367   */
2368  @Uninterruptible
2369  public static void shutdown(int value) {
2370    handlePossibleRecursiveShutdown();
2371
2372    if (VM.VerifyAssertions) VM._assert(VM.runningVM);
2373    sysCall.sysExit(value);
2374    if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
2375  }
2376
2377  private static int inSysFail = 0;
2378
2379  public static boolean sysFailInProgress() {
2380    return inSysFail > 0;
2381  }
2382
2383  private static void handlePossibleRecursiveCallToSysFail(String message) {
2384    handlePossibleRecursiveExit("sysFail", ++inSysFail, message);
2385  }
2386
2387  private static void handlePossibleRecursiveCallToSysFail(String message, int number) {
2388    handlePossibleRecursiveExit("sysFail", ++inSysFail, message, number);
2389  }
2390
2391  private static int inSysExit = 0;
2392
2393  private static void handlePossibleRecursiveCallToSysExit() {
2394    handlePossibleRecursiveExit("sysExit", ++inSysExit);
2395  }
2396
2397  private static int inShutdown = 0;
2398
2399  /** Used only by VM.shutdown() */
2400  private static void handlePossibleRecursiveShutdown() {
2401    handlePossibleRecursiveExit("shutdown", ++inShutdown);
2402  }
2403
2404  private static void handlePossibleRecursiveExit(String called, int depth) {
2405    handlePossibleRecursiveExit(called, depth, null);
2406  }
2407
2408  private static void handlePossibleRecursiveExit(String called, int depth, String message) {
2409    handlePossibleRecursiveExit(called, depth, message, false, -9999999);
2410  }
2411
2412  private static void handlePossibleRecursiveExit(String called, int depth, String message, int number) {
2413    handlePossibleRecursiveExit(called, depth, message, true, number);
2414  }
2415
2416  /** @param called Name of the function called: "sysExit", "sysFail", or
2417   *    "shutdown".
2418   * @param depth How deep are we in that function?
2419   * @param message What message did it have?  null means this particular
2420   *    shutdown function  does not come with a message.
2421   * @param showNumber Print <code>number</code> following
2422   *    <code>message</code>?
2423   * @param number Print this number, if <code>showNumber</code> is {@code true}. */
2424  private static void handlePossibleRecursiveExit(String called, int depth, String message, boolean showNumber,
2425                                                  int number) {
2426    if (depth > 1 &&
2427        (depth <=
2428         maxSystemTroubleRecursionDepth + VM.maxSystemTroubleRecursionDepthBeforeWeStopVMSysWrite)) {
2429      if (showNumber) {
2430        tsysWriteln("VM.",
2431                     called,
2432                     "(): We're in a",
2433                     " (likely)",
2434                     " recursive call to VM.",
2435                     called,
2436                     "(), ",
2437                     depth,
2438                     " deep\n",
2439                     message == null ? "" : "   ",
2440                     message == null ? "" : called,
2441                     message == null ? "" : " was called with the message: ",
2442                     message == null ? "" : message,
2443                     number);
2444      } else {
2445        tsysWriteln("VM.",
2446                     called,
2447                     "(): We're in a",
2448                     " (likely)",
2449                     " recursive call to VM.",
2450                     called,
2451                     "(), ",
2452                     depth,
2453                     " deep\n",
2454                     message == null ? "" : "   ",
2455                     message == null ? "" : called,
2456                     message == null ? "" : " was called with the message: ",
2457                     message == null ? "" : message);
2458      }
2459    }
2460    if (depth > maxSystemTroubleRecursionDepth) {
2461      dieAbruptlyRecursiveSystemTrouble();
2462      if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
2463    }
2464  }
2465
2466  /** Have we already called dieAbruptlyRecursiveSystemTrouble()?
2467   Only for use if we're recursively shutting down!  Used by
2468   dieAbruptlyRecursiveSystemTrouble() only.  */
2469
2470  private static boolean inDieAbruptlyRecursiveSystemTrouble = false;
2471
2472  public static void dieAbruptlyRecursiveSystemTrouble() {
2473    if (!inDieAbruptlyRecursiveSystemTrouble) {
2474      inDieAbruptlyRecursiveSystemTrouble = true;
2475      sysWriteln("VM.dieAbruptlyRecursiveSystemTrouble(): Dying abruptly",
2476                 "; we're stuck in a recursive shutdown/exit.");
2477    }
2478    /* Emergency death. */
2479    sysCall.sysExit(EXIT_STATUS_RECURSIVELY_SHUTTING_DOWN);
2480    /* And if THAT fails, go into an infinite loop.  Ugly, but it's better than
2481       returning from this function and leading to yet more cascading errors.
2482       and misleading error messages.   (To the best of my knowledge, we have
2483       never yet reached this point.)  */
2484    while (true) {
2485      ;
2486    }
2487  }
2488
2489  //----------------//
2490  // implementation //
2491  //----------------//
2492
2493  /**
2494   * Create class instances needed for boot image or initialize classes
2495   * needed by tools.
2496   * @param bootstrapClasspath places where VM implementation class reside
2497   * @param bootCompilerArgs command line arguments to pass along to the
2498   *                         boot compiler's init routine.
2499   */
2500  @Interruptible
2501  private static void init(String bootstrapClasspath, String[] bootCompilerArgs) {
2502    if (VM.VerifyAssertions) VM._assert(!VM.runningVM);
2503
2504    // create dummy boot record
2505    //
2506    BootRecord.the_boot_record = new BootRecord();
2507
2508    // initialize type subsystem and classloader
2509    RVMClassLoader.init(bootstrapClasspath);
2510
2511    // initialize remaining subsystems needed for compilation
2512    //
2513    if (writingBootImage) {
2514      // initialize compiler that builds boot image
2515      BootImageCompiler.init(bootCompilerArgs);
2516    }
2517    RuntimeEntrypoints.init();
2518    RVMThread.init();
2519  }
2520
2521  public static void disableYieldpoints() {
2522    RVMThread.getCurrentThread().disableYieldpoints();
2523  }
2524
2525  public static void enableYieldpoints() {
2526    RVMThread.getCurrentThread().enableYieldpoints();
2527  }
2528
2529  /**
2530   * The disableGC() and enableGC() methods are for use as guards to protect
2531   * code that must deal with raw object addresses in a collection-safe manner
2532   * (i.e. code that holds raw pointers across "gc-sites").<p>
2533   *
2534   * Authors of code running while GC is disabled must be certain not to
2535   * allocate objects explicitly via "new", or implicitly via methods that,
2536   * in turn, call "new" (such as string concatenation expressions that are
2537   * translated by the java compiler into String() and StringBuffer()
2538   * operations). Furthermore, to prevent deadlocks, code running with GC
2539   * disabled must not lock any objects. This means the code must not execute
2540   * any bytecodes that require runtime support (e.g. via RuntimeEntrypoints)
2541   * such as:
2542   * <ul>
2543   *   <li>calling methods or accessing fields of classes that haven't yet
2544   *     been loaded/resolved/instantiated
2545   *   <li>calling synchronized methods
2546   *   <li>entering synchronized blocks
2547   *   <li>allocating objects with "new"
2548   *   <li>throwing exceptions
2549   *   <li>executing trap instructions (including stack-growing traps)
2550   *   <li>storing into object arrays, except when runtime types of lhs &amp; rhs
2551   *     match exactly
2552   *   <li>typecasting objects, except when runtime types of lhs &amp; rhs
2553   *     match exactly
2554   * </ul>
2555   *
2556   * <p>
2557   * Recommendation: as a debugging aid, Allocator implementations
2558   * should test "Thread.disallowAllocationsByThisThread" to verify that
2559   * they are never called while GC is disabled.
2560   */
2561  @Inline
2562  @Unpreemptible("We may boost the size of the stack with GC disabled and may get preempted doing this")
2563  public static void disableGC() {
2564    disableGC(false);           // Recursion is not allowed in this context.
2565  }
2566
2567  /**
2568   * disableGC: Disable GC if it hasn't already been disabled.  This
2569   * enforces a stack discipline; we need it for the JNI Get*Critical and
2570   * Release*Critical functions.  Should be matched with a subsequent call to
2571   * enableGC().
2572   *
2573   * @param recursiveOK whether recursion is allowed.
2574   */
2575  @Inline
2576  @Unpreemptible("We may boost the size of the stack with GC disabled and may get preempted doing this")
2577  public static void disableGC(boolean recursiveOK) {
2578    // current (non-GC) thread is going to be holding raw addresses, therefore we must:
2579    //
2580    // 1. make sure we have enough stack space to run until GC is re-enabled
2581    //    (otherwise we might trigger a stack reallocation)
2582    //    (We can't resize the stack if there's a native frame, so don't
2583    //     do it and hope for the best)
2584    //
2585    // 2. force all other threads that need GC to wait until this thread
2586    //    is done with the raw addresses
2587    //
2588    // 3. ensure that this thread doesn't try to allocate any objects
2589    //    (because an allocation attempt might trigger a collection that
2590    //    would invalidate the addresses we're holding)
2591    //
2592
2593    RVMThread myThread = RVMThread.getCurrentThread();
2594
2595    // 0. Sanity Check; recursion
2596    int gcDepth = myThread.getDisableGCDepth();
2597    if (VM.VerifyAssertions) VM._assert(gcDepth >= 0);
2598    gcDepth++;
2599    myThread.setDisableGCDepth(gcDepth);
2600    if (gcDepth > 1) {
2601      return;                   // We've already disabled it.
2602    }
2603
2604    // 1.
2605    //
2606    if (Magic.getFramePointer().minus(StackFrameLayout.getStackSizeGCDisabled())
2607        .LT(myThread.stackLimit) && !myThread.hasNativeStackFrame()) {
2608      RVMThread.resizeCurrentStack(myThread.getStackLength() +
2609          StackFrameLayout.getStackSizeGCDisabled(), null);
2610    }
2611
2612    // 2.
2613    //
2614    myThread.disableYieldpoints();
2615
2616    // 3.
2617    //
2618    if (VM.VerifyAssertions) {
2619      if (!recursiveOK) {
2620        VM._assert(!myThread.getDisallowAllocationsByThisThread()); // recursion not allowed
2621      }
2622      myThread.setDisallowAllocationsByThisThread();
2623    }
2624  }
2625
2626  /**
2627   * enable GC; entry point when recursion is not OK.
2628   */
2629  @Inline
2630  public static void enableGC() {
2631    enableGC(false);            // recursion not OK.
2632  }
2633
2634  /**
2635   * enableGC(): Re-Enable GC if we're popping off the last
2636   * possibly-recursive {@link #disableGC} request.  This enforces a stack discipline;
2637   * we need it for the JNI Get*Critical and Release*Critical functions.
2638   * Should be matched with a preceding call to {@link #disableGC}.
2639   *
2640   * @param recursiveOK unused (!)
2641   */
2642  @Inline
2643  public static void enableGC(boolean recursiveOK) {
2644    RVMThread myThread = RVMThread.getCurrentThread();
2645    int gcDepth = myThread.getDisableGCDepth();
2646    if (VM.VerifyAssertions) {
2647      VM._assert(gcDepth >= 1);
2648      VM._assert(myThread.getDisallowAllocationsByThisThread());
2649    }
2650    gcDepth--;
2651    myThread.setDisableGCDepth(gcDepth);
2652    if (gcDepth > 0) {
2653      return;
2654    }
2655
2656    // Now the actual work of re-enabling GC.
2657    myThread.clearDisallowAllocationsByThisThread();
2658    myThread.enableYieldpoints();
2659  }
2660
2661  /**
2662   * @return whether this is a build for 32bit addressing.
2663   * NB. this method is provided to give a hook to the IA32
2664   * assembler that won't be compiled away by javac.
2665   */
2666  public static boolean buildFor32Addr() {
2667    return BuildFor32Addr;
2668  }
2669
2670  /**
2671   * @return whether this is a build for SSE2.
2672   * NB. this method is provided to give a hook to the IA32
2673   * assembler that won't be compiled away by javac.
2674
2675   */
2676  public static boolean buildForSSE2() {
2677    return BuildForSSE2;
2678  }
2679}
2680