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