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