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