001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.mmtk.plan; 014 015import static org.mmtk.utility.Constants.*; 016import static org.mmtk.vm.VM.EXIT_CODE_REFLECTION_FAILURE; 017 018import org.mmtk.policy.MarkSweepSpace; 019import org.mmtk.policy.Space; 020import org.mmtk.policy.ImmortalSpace; 021import org.mmtk.policy.RawPageSpace; 022import org.mmtk.policy.LargeObjectSpace; 023import org.mmtk.utility.alloc.LinearScan; 024import org.mmtk.utility.Conversions; 025import org.mmtk.utility.HeaderByte; 026import org.mmtk.utility.heap.HeapGrowthManager; 027import org.mmtk.utility.heap.Map; 028import org.mmtk.utility.heap.VMRequest; 029import org.mmtk.utility.Log; 030import org.mmtk.utility.options.*; 031import org.mmtk.utility.sanitychecker.SanityChecker; 032import org.mmtk.utility.statistics.Timer; 033import org.mmtk.utility.statistics.Stats; 034import org.mmtk.vm.VM; 035import org.vmmagic.pragma.*; 036import org.vmmagic.unboxed.*; 037 038/** 039 * This abstract class implements the global core functionality for all 040 * memory management schemes. All global MMTk plans should inherit from 041 * this class.<p> 042 * 043 * All plans make a clear distinction between <i>global</i> and 044 * <i>thread-local</i> activities, and divides global and local state 045 * into separate class hierarchies. Global activities must be 046 * synchronized, whereas no synchronization is required for 047 * thread-local activities. There is a single instance of Plan (or the 048 * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel 049 * threads" (aka CPUs). Thus instance 050 * methods of PlanLocal allow fast, unsynchronized access to functions such as 051 * allocation and collection. 052 * 053 * The global instance defines and manages static resources 054 * (such as memory and virtual memory resources). This mapping of threads to 055 * instances is crucial to understanding the correctness and 056 * performance properties of MMTk plans. 057 */ 058@Uninterruptible 059public abstract class Plan { 060 /**************************************************************************** 061 * Constants 062 */ 063 064 /** 065 * 066 */ 067 068 /* GC State */ 069 public static final int NOT_IN_GC = 0; // this must be zero for C code 070 public static final int GC_PREPARE = 1; // before setup and obtaining root 071 public static final int GC_PROPER = 2; 072 073 /* Space Size Constants. */ 074 public static final boolean USE_CODE_SPACE = true; 075 076 /* Allocator Constants */ 077 public static final int ALLOC_DEFAULT = 0; 078 public static final int ALLOC_NON_REFERENCE = 1; 079 public static final int ALLOC_NON_MOVING = 2; 080 public static final int ALLOC_IMMORTAL = 3; 081 public static final int ALLOC_LOS = 4; 082 public static final int ALLOC_PRIMITIVE_LOS = 5; 083 public static final int ALLOC_GCSPY = 6; 084 public static final int ALLOC_CODE = 7; 085 public static final int ALLOC_LARGE_CODE = 8; 086 public static final int ALLOC_HOT_CODE = USE_CODE_SPACE ? ALLOC_CODE : ALLOC_DEFAULT; 087 public static final int ALLOC_COLD_CODE = USE_CODE_SPACE ? ALLOC_CODE : ALLOC_DEFAULT; 088 public static final int ALLOC_STACK = ALLOC_LOS; 089 public static final int ALLOCATORS = 9; 090 public static final int DEFAULT_SITE = -1; 091 092 /* Miscellaneous Constants */ 093// public static final int LOS_SIZE_THRESHOLD = SegregatedFreeListSpace.MAX_CELL_SIZE; 094 public static final int NON_PARTICIPANT = 0; 095 public static final boolean GATHER_WRITE_BARRIER_STATS = false; 096 public static final int DEFAULT_MIN_NURSERY = (2 << 20) >> LOG_BYTES_IN_PAGE; 097 public static final int DEFAULT_MAX_NURSERY = (32 << 20) >> LOG_BYTES_IN_PAGE; 098 public static final boolean SCAN_BOOT_IMAGE = true; // scan it for roots rather than trace it 099 // public static final boolean REQUIRES_LOS = VM.activePlan.constraints().requiresLOS(); 100 public static final int MAX_NON_LOS_DEFAULT_ALLOC_BYTES = VM.activePlan.constraints().maxNonLOSDefaultAllocBytes(); 101 public static final int MAX_NON_LOS_NONMOVING_ALLOC_BYTES = VM.activePlan.constraints().maxNonLOSNonMovingAllocBytes(); 102 public static final int MAX_NON_LOS_COPY_BYTES = VM.activePlan.constraints().maxNonLOSCopyBytes(); 103 104 /* Do we support a log bit in the object header? Some write barriers may use it */ 105 public static final boolean NEEDS_LOG_BIT_IN_HEADER = VM.activePlan.constraints().needsLogBitInHeader(); 106 107 /**************************************************************************** 108 * Class variables 109 */ 110 111 /** The space that holds any VM specific objects (e.g. a boot image) */ 112 public static final Space vmSpace = VM.memory.getVMSpace(); 113 114 /** Any immortal objects allocated after booting are allocated here. */ 115 public static final ImmortalSpace immortalSpace = new ImmortalSpace("immortal", VMRequest.discontiguous()); 116 117 /** All meta data that is used by MMTk is allocated (and accounted for) in the meta data space. */ 118 public static final RawPageSpace metaDataSpace = new RawPageSpace("meta", VMRequest.discontiguous()); 119 120 /** Large objects are allocated into a special large object space. */ 121 public static final LargeObjectSpace loSpace = new LargeObjectSpace("los", VMRequest.discontiguous()); 122 123 /** Space used by the sanity checker (used at runtime only if sanity checking enabled */ 124 public static final RawPageSpace sanitySpace = new RawPageSpace("sanity", VMRequest.discontiguous()); 125 126 /** Space used to allocate objects that cannot be moved. we do not need a large space as the LOS is non-moving. */ 127 public static final MarkSweepSpace nonMovingSpace = new MarkSweepSpace("non-moving", VMRequest.discontiguous()); 128 129 public static final MarkSweepSpace smallCodeSpace = USE_CODE_SPACE ? new MarkSweepSpace("sm-code", VMRequest.discontiguous()) : null; 130 public static final LargeObjectSpace largeCodeSpace = USE_CODE_SPACE ? new LargeObjectSpace("lg-code", VMRequest.discontiguous()) : null; 131 132 public static int pretenureThreshold = Integer.MAX_VALUE; 133 134 /* Space descriptors */ 135 public static final int IMMORTAL = immortalSpace.getDescriptor(); 136 public static final int VM_SPACE = vmSpace.getDescriptor(); 137 public static final int META = metaDataSpace.getDescriptor(); 138 public static final int LOS = loSpace.getDescriptor(); 139 public static final int SANITY = sanitySpace.getDescriptor(); 140 public static final int NON_MOVING = nonMovingSpace.getDescriptor(); 141 public static final int SMALL_CODE = USE_CODE_SPACE ? smallCodeSpace.getDescriptor() : 0; 142 public static final int LARGE_CODE = USE_CODE_SPACE ? largeCodeSpace.getDescriptor() : 0; 143 144 /** Timer that counts total time */ 145 public static final Timer totalTime = new Timer("time"); 146 147 /** Support for allocation-site identification */ 148 protected static int allocationSiteCount = 0; 149 150 /** Global sanity checking state **/ 151 public static final SanityChecker sanityChecker = new SanityChecker(); 152 153 /** Default collector context */ 154 protected final Class<? extends ParallelCollector> defaultCollectorContext; 155 156 /**************************************************************************** 157 * Constructor. 158 */ 159 public Plan() { 160 /* Create base option instances */ 161 Options.verbose = new Verbose(); 162 Options.verboseTiming = new VerboseTiming(); 163 Options.stressFactor = new StressFactor(); 164 Options.noFinalizer = new NoFinalizer(); 165 Options.noReferenceTypes = new NoReferenceTypes(); 166 Options.fullHeapSystemGC = new FullHeapSystemGC(); 167 Options.harnessAll = new HarnessAll(); 168 Options.ignoreSystemGC = new IgnoreSystemGC(); 169 Options.metaDataLimit = new MetaDataLimit(); 170 Options.nurserySize = new NurserySize(); 171 Options.nurseryZeroing = new NurseryZeroing(); 172 Options.pretenureThresholdFraction = new PretenureThresholdFraction(); 173 Options.variableSizeHeap = new VariableSizeHeap(); 174 Options.eagerMmapSpaces = new EagerMmapSpaces(); 175 Options.sanityCheck = new SanityCheck(); 176 Options.debugAddress = new DebugAddress(); 177 Options.perfEvents = new PerfEvents(); 178 Options.useReturnBarrier = new UseReturnBarrier(); 179 Options.useShortStackScans = new UseShortStackScans(); 180 Options.threads = new Threads(); 181 Options.cycleTriggerThreshold = new CycleTriggerThreshold(); 182 Map.finalizeStaticSpaceMap(); 183 registerSpecializedMethods(); 184 185 // Determine the default collector context. 186 Class<? extends Plan> mmtkPlanClass = this.getClass().asSubclass(Plan.class); 187 while (!mmtkPlanClass.getName().startsWith("org.mmtk.plan")) { 188 mmtkPlanClass = mmtkPlanClass.getSuperclass().asSubclass(Plan.class); 189 } 190 String contextClassName = mmtkPlanClass.getName() + "Collector"; 191 Class<? extends ParallelCollector> mmtkCollectorClass = null; 192 try { 193 mmtkCollectorClass = Class.forName(contextClassName).asSubclass(ParallelCollector.class); 194 } catch (Throwable t) { 195 t.printStackTrace(); 196 System.exit(EXIT_CODE_REFLECTION_FAILURE); 197 } 198 defaultCollectorContext = mmtkCollectorClass; 199 } 200 201 /**************************************************************************** 202 * The complete boot Sequence is: 203 * 204 * 1. enableAllocation: allow allocation (but not collection). 205 * 2. processOptions : the VM has parsed/prepared options for MMTk to react to. 206 * 3. enableCollection: the VM can support the spawning of MMTk collector contexts. 207 * 4. fullyBooted : control is just about to be given to application code. 208 */ 209 210 /** 211 * The enableAllocation method is called early in the boot process to allow 212 * allocation. 213 */ 214 @Interruptible 215 public void enableAllocation() { 216 } 217 218 /** 219 * The processOptions method is called by the runtime immediately after 220 * command-line arguments are available. Allocation must be supported 221 * prior to this point because the runtime infrastructure may require 222 * allocation in order to parse the command line arguments. For this 223 * reason all plans should operate gracefully on the default minimum 224 * heap size until the point that processOptions is called. 225 */ 226 @Interruptible 227 public void processOptions() { 228 VM.statistics.perfEventInit(Options.perfEvents.getValue()); 229 if (Options.verbose.getValue() > 2) Space.printVMMap(); 230 if (Options.verbose.getValue() > 3) VM.config.printConfig(); 231 if (Options.verbose.getValue() > 0) Stats.startAll(); 232 if (Options.eagerMmapSpaces.getValue()) Space.eagerlyMmapMMTkSpaces(); 233 pretenureThreshold = (int) ((Options.nurserySize.getMaxNursery() << LOG_BYTES_IN_PAGE) * Options.pretenureThresholdFraction.getValue()); 234 } 235 236 /** 237 * The enableCollection method is called by the runtime after it is 238 * safe to spawn collector contexts and allow garbage collection. 239 */ 240 @Interruptible 241 public void enableCollection() { 242 int actualThreadCount = determineThreadCount(); 243 244 if (VM.VERIFY_ASSERTIONS) { 245 VM.assertions._assert(actualThreadCount == VM.activePlan.collectorCount(), 246 "Actual thread count does not match collector count from active plan."); 247 } 248 249 preCollectorSpawn(); 250 251 spawnCollectorThreads(actualThreadCount); 252 } 253 254 /** 255 * Determines the number of threads that will be used for collection.<p> 256 * 257 * Collectors that need fine-grained control over the number of spawned collector 258 * threads may override this method. Subclasses must ensure that the return value 259 * of this method is consistent with the number of collector threads in 260 * the active plan. 261 * 262 * @return number of threads to be used for collection 263 * @see PlanConstraints#maxNumGCThreads() setting only the maximum number 264 * of collectors 265 */ 266 @Interruptible("Options methods and Math.min are interruptible") 267 protected int determineThreadCount() { 268 int defaultThreadCount = VM.collection.getDefaultThreads(); 269 int maxThreadCount = VM.activePlan.constraints().maxNumGCThreads(); 270 int safeDefaultValue = Math.min(defaultThreadCount, maxThreadCount); 271 272 // Make sure that if we have not explicitly set threads, then we use the right default. 273 if (Options.verbose.getValue() > 0) { 274 Log.write("Setting default thread count for MMTk to minimum of "); 275 Log.write("default thread count "); 276 Log.write(defaultThreadCount); 277 Log.write(" and maximal thread count "); 278 Log.write(maxThreadCount); 279 Log.write(" supported by current GC plan."); 280 Log.writeln(); 281 Log.write("New default thread count value is "); 282 Log.write(safeDefaultValue); 283 Log.writeln(); 284 } 285 Options.threads.updateDefaultValue(safeDefaultValue); 286 287 int desiredThreadCount = Options.threads.getValue(); 288 int actualThreadCount = Math.min(desiredThreadCount, maxThreadCount); 289 if (Options.verbose.getValue() > 0) { 290 Log.write("Setting actual thread count for MMTk to minimum of "); 291 Log.write("desired thread count "); 292 Log.write(desiredThreadCount); 293 Log.write(" and maximal thread count "); 294 Log.write(maxThreadCount); 295 Log.write(" supported by current GC plan."); 296 Log.writeln(); 297 Log.write("New actual thread count is "); 298 Log.write(actualThreadCount); 299 Log.writeln(); 300 } 301 Options.threads.setValue(actualThreadCount); 302 303 if (VM.VERIFY_ASSERTIONS) { 304 VM.assertions._assert(actualThreadCount > 0, 305 "Determining the number of gc threads yieled a result <= 0"); 306 } 307 308 return actualThreadCount; 309 } 310 311 /** 312 * Prepares for spawning of collectors.<p> 313 * 314 * This is a good place to do initialization work that depends on 315 * options that are only known at runtime. Collectors must keep allocation 316 * to a minimum because collection is not yet enabled. 317 */ 318 @Interruptible 319 protected void preCollectorSpawn() { 320 // most collectors do not need to do any work here 321 } 322 323 /** 324 * Spawns the collector threads.<p> 325 * 326 * Collection is enabled after this method returns. 327 * 328 * @param numThreads the number of collector threads to spawn 329 */ 330 @Interruptible("Spawning collector threads requires allocation") 331 protected void spawnCollectorThreads(int numThreads) { 332 // Create our parallel workers 333 parallelWorkers.initGroup(numThreads, defaultCollectorContext); 334 335 // Create the concurrent worker threads. 336 if (VM.activePlan.constraints().needsConcurrentWorkers()) { 337 concurrentWorkers.initGroup(numThreads, defaultCollectorContext); 338 } 339 340 // Create our control thread. 341 VM.collection.spawnCollectorContext(controlCollectorContext); 342 343 // Allow mutators to trigger collection. 344 initialized = true; 345 } 346 347 @Interruptible 348 public void fullyBooted() { 349 if (Options.harnessAll.getValue()) harnessBegin(); 350 } 351 352 public static final ParallelCollectorGroup parallelWorkers = new ParallelCollectorGroup("ParallelWorkers"); 353 public static final ParallelCollectorGroup concurrentWorkers = new ParallelCollectorGroup("ConcurrentWorkers"); 354 public static final ControllerCollectorContext controlCollectorContext = new ControllerCollectorContext(parallelWorkers); 355 356 /** 357 * The VM is about to exit. Perform any clean up operations. 358 * 359 * @param value The exit value 360 */ 361 @Interruptible 362 public void notifyExit(int value) { 363 if (Options.harnessAll.getValue()) harnessEnd(); 364 if (Options.verbose.getValue() == 1) { 365 Log.write("[End "); 366 totalTime.printTotalSecs(); 367 Log.writeln(" s]"); 368 } else if (Options.verbose.getValue() == 2) { 369 Log.write("[End "); 370 totalTime.printTotalMillis(); 371 Log.writeln(" ms]"); 372 } 373 if (Options.verboseTiming.getValue()) printDetailedTiming(true); 374 } 375 376 /** 377 * Any Plan can override this to provide additional plan specific 378 * timing information. 379 * 380 * @param totals Print totals 381 */ 382 protected void printDetailedTiming(boolean totals) {} 383 384 /** 385 * Perform any required write barrier action when installing an object reference 386 * a boot time. 387 * 388 * @param reference the reference value that is to be stored 389 * @return The raw value to be stored 390 */ 391 public Word bootTimeWriteBarrier(Word reference) { 392 return reference; 393 } 394 395 /** 396 * Performs any required initialization of the GC portion of the header. 397 * Called for objects created at boot time. 398 * 399 * @param object the Address representing the storage to be initialized 400 * @param typeRef the type reference for the instance being created 401 * @param size the number of bytes allocated by the GC system for 402 * this object. 403 * @return The new value of the status word 404 */ 405 public byte setBuildTimeGCByte(Address object, ObjectReference typeRef, int size) { 406 if (HeaderByte.NEEDS_UNLOGGED_BIT) { 407 return HeaderByte.UNLOGGED_BIT; 408 } else { 409 return 0; 410 } 411 } 412 413 /**************************************************************************** 414 * Allocation 415 */ 416 417 /** 418 * @param compileTime is this a call by the compiler? 419 * @return an allocation site 420 * 421 */ 422 public static int getAllocationSite(boolean compileTime) { 423 if (compileTime) // a new allocation site is being compiled 424 return allocationSiteCount++; 425 else // an anonymous site 426 return DEFAULT_SITE; 427 } 428 429 /**************************************************************************** 430 * Collection. 431 */ 432 433 /** 434 * Perform a (global) collection phase. 435 * 436 * @param phaseId The unique id of the phase to perform. 437 */ 438 public abstract void collectionPhase(short phaseId); 439 440 /** 441 * Replace a phase. 442 * 443 * @param oldScheduledPhase The scheduled phase to insert after 444 * @param scheduledPhase The scheduled phase to insert 445 */ 446 @Interruptible 447 public void replacePhase(int oldScheduledPhase, int scheduledPhase) { 448 VM.assertions.fail("replacePhase not implemented for this plan"); 449 } 450 451 /** 452 * Insert a phase. 453 * 454 * @param markerScheduledPhase The scheduled phase to insert after 455 * @param scheduledPhase The scheduled phase to insert 456 */ 457 @Interruptible 458 public void insertPhaseAfter(int markerScheduledPhase, int scheduledPhase) { 459 short tempPhase = Phase.createComplex("auto-gen", null, markerScheduledPhase, scheduledPhase); 460 replacePhase(markerScheduledPhase, Phase.scheduleComplex(tempPhase)); 461 } 462 463 /** 464 * @return Whether last GC was an exhaustive attempt to collect the heap. For many collectors this is the same as asking whether the last GC was a full heap collection. 465 */ 466 public boolean lastCollectionWasExhaustive() { 467 return lastCollectionFullHeap(); 468 } 469 470 /** 471 * @return Whether last GC is a full GC. 472 */ 473 public boolean lastCollectionFullHeap() { 474 return true; 475 } 476 477 /** 478 * @return Is last GC a full collection? 479 */ 480 public static boolean isEmergencyCollection() { 481 return emergencyCollection; 482 } 483 484 /** 485 * Force the next collection to be full heap. 486 */ 487 public void forceFullHeapCollection() {} 488 489 /** 490 * @return Is current GC only collecting objects allocated since last GC. 491 */ 492 public boolean isCurrentGCNursery() { 493 return false; 494 } 495 496 private long lastStressPages = 0; 497 498 /** 499 * Return the expected reference count. For non-reference counting 500 * collectors this becomes a {@code true/false} relationship. 501 * 502 * @param object The object to check. 503 * @param sanityRootRC The number of root references to the object. 504 * @return The expected (root excluded) reference count. 505 */ 506 public int sanityExpectedRC(ObjectReference object, int sanityRootRC) { 507 Space space = Space.getSpaceForObject(object); 508 return space.isReachable(object) ? SanityChecker.ALIVE : SanityChecker.DEAD; 509 } 510 511 /** 512 * Perform a linear scan of all spaces to check for possible leaks. 513 * This is only called after a full-heap GC. 514 * 515 * @param scanner The scanner callback to use. 516 */ 517 public void sanityLinearScan(LinearScan scanner) { 518 } 519 520 /** 521 * @return {@code true} is a stress test GC is required 522 */ 523 @Inline 524 public final boolean stressTestGCRequired() { 525 long pages = Space.cumulativeCommittedPages(); 526 if (initialized && 527 ((pages ^ lastStressPages) > Options.stressFactor.getPages())) { 528 lastStressPages = pages; 529 return true; 530 } else 531 return false; 532 } 533 534 /**************************************************************************** 535 * GC State 536 */ 537 538 /** 539 * 540 */ 541 protected static boolean userTriggeredCollection; 542 protected static boolean internalTriggeredCollection; 543 protected static boolean lastInternalTriggeredCollection; 544 protected static boolean emergencyCollection; 545 protected static boolean stacksPrepared; 546 547 private static boolean initialized = false; 548 549 @Entrypoint 550 private static int gcStatus = NOT_IN_GC; // shared variable 551 552 /** @return Is the memory management system initialized? */ 553 public static boolean isInitialized() { 554 return initialized; 555 } 556 557 /** 558 * Return {@code true} if stacks have been prepared in this collection cycle. 559 * 560 * @return {@code true} if stacks have been prepared in this collection cycle. 561 */ 562 public static boolean stacksPrepared() { 563 return stacksPrepared; 564 } 565 /** 566 * Return {@code true} if a collection is in progress. 567 * 568 * @return {@code true} if a collection is in progress. 569 */ 570 public static boolean gcInProgress() { 571 return gcStatus != NOT_IN_GC; 572 } 573 574 /** 575 * Return {@code true} if a collection is in progress and past the preparatory stage. 576 * 577 * @return {@code true} if a collection is in progress and past the preparatory stage. 578 */ 579 public static boolean gcInProgressProper() { 580 return gcStatus == GC_PROPER; 581 } 582 583 /** 584 * Sets the GC status. 585 * 586 * @param s The new GC status. 587 */ 588 public static void setGCStatus(int s) { 589 if (gcStatus == NOT_IN_GC) { 590 /* From NOT_IN_GC to any phase */ 591 stacksPrepared = false; 592 // Need to call this method to get a correct collection 593 // count (which we need for JMX). This call won't cause 594 // gathering of additional stats unless stats are enabled. 595 Stats.startGC(); 596 if (Stats.gatheringStats()) { 597 VM.activePlan.global().printPreStats(); 598 } 599 } 600 VM.memory.isync(); 601 gcStatus = s; 602 VM.memory.sync(); 603 if (gcStatus == NOT_IN_GC) { 604 /* From any phase to NOT_IN_GC */ 605 if (Stats.gatheringStats()) { 606 Stats.endGC(); 607 VM.activePlan.global().printPostStats(); 608 } 609 } 610 } 611 612 /** 613 * Print pre-collection statistics. 614 */ 615 public void printPreStats() { 616 if ((Options.verbose.getValue() == 1) || 617 (Options.verbose.getValue() == 2)) { 618 Log.write("[GC "); Log.write(Stats.gcCount()); 619 if (Options.verbose.getValue() == 1) { 620 Log.write(" Start "); 621 Plan.totalTime.printTotalSecs(); 622 Log.write(" s"); 623 } else { 624 Log.write(" Start "); 625 Plan.totalTime.printTotalMillis(); 626 Log.write(" ms"); 627 } 628 Log.write(" "); 629 Log.write(Conversions.pagesToKBytes(getPagesUsed())); 630 Log.write("KB "); 631 Log.flush(); 632 } 633 if (Options.verbose.getValue() > 2) { 634 Log.write("Collection "); Log.write(Stats.gcCount()); 635 Log.write(": "); 636 printUsedPages(); 637 Log.write(" Before Collection: "); 638 Space.printUsageMB(); 639 if (Options.verbose.getValue() >= 4) { 640 Log.write(" "); 641 Space.printUsagePages(); 642 } 643 if (Options.verbose.getValue() >= 5) { 644 Space.printVMMap(); 645 } 646 } 647 } 648 649 /** 650 * Print out statistics at the end of a GC 651 */ 652 public final void printPostStats() { 653 if ((Options.verbose.getValue() == 1) || 654 (Options.verbose.getValue() == 2)) { 655 Log.write("-> "); 656 Log.writeDec(Conversions.pagesToBytes(getPagesUsed()).toWord().rshl(10)); 657 Log.write("KB "); 658 if (Options.verbose.getValue() == 1) { 659 totalTime.printLast(); 660 Log.writeln(" ms]"); 661 } else { 662 Log.write("End "); 663 totalTime.printTotal(); 664 Log.writeln(" ms]"); 665 } 666 } 667 if (Options.verbose.getValue() > 2) { 668 Log.write(" After Collection: "); 669 Space.printUsageMB(); 670 if (Options.verbose.getValue() >= 4) { 671 Log.write(" "); 672 Space.printUsagePages(); 673 } 674 if (Options.verbose.getValue() >= 5) { 675 Space.printVMMap(); 676 } 677 Log.write(" "); 678 printUsedPages(); 679 Log.write(" Collection time: "); 680 totalTime.printLast(); 681 Log.writeln(" ms"); 682 } 683 } 684 685 public final void printUsedPages() { 686 Log.write("reserved = "); 687 Log.write(Conversions.pagesToMBytes(getPagesReserved())); 688 Log.write(" MB ("); 689 Log.write(getPagesReserved()); 690 Log.write(" pgs)"); 691 Log.write(" used = "); 692 Log.write(Conversions.pagesToMBytes(getPagesUsed())); 693 Log.write(" MB ("); 694 Log.write(getPagesUsed()); 695 Log.write(" pgs)"); 696 Log.write(" total = "); 697 Log.write(Conversions.pagesToMBytes(getTotalPages())); 698 Log.write(" MB ("); 699 Log.write(getTotalPages()); 700 Log.write(" pgs)"); 701 Log.writeln(); 702 } 703 704 /** 705 * The application code has requested a collection. 706 */ 707 @Unpreemptible 708 public static void handleUserCollectionRequest() { 709 if (Options.ignoreSystemGC.getValue()) { 710 // Ignore the user GC request. 711 return; 712 } 713 // Mark this as a user triggered collection 714 userTriggeredCollection = true; 715 // Request the collection 716 controlCollectorContext.request(); 717 // Wait for the collection to complete 718 VM.collection.blockForGC(); 719 } 720 721 /** 722 * MMTK has requested stop-the-world activity (e.g., stw within a concurrent gc). 723 */ 724 public static void triggerInternalCollectionRequest() { 725 // Mark this as a user triggered collection 726 internalTriggeredCollection = lastInternalTriggeredCollection = true; 727 // Request the collection 728 controlCollectorContext.request(); 729 } 730 731 /** 732 * Reset collection state information. 733 */ 734 public static void resetCollectionTrigger() { 735 lastInternalTriggeredCollection = internalTriggeredCollection; 736 internalTriggeredCollection = false; 737 userTriggeredCollection = false; 738 } 739 740 /** 741 * @return {@code true} if this collection was triggered by application code. 742 */ 743 public static boolean isUserTriggeredCollection() { 744 return userTriggeredCollection; 745 } 746 747 /** 748 * @return {@code true} if this collection was triggered internally. 749 */ 750 public static boolean isInternalTriggeredCollection() { 751 return lastInternalTriggeredCollection; 752 } 753 754 /**************************************************************************** 755 * Harness 756 */ 757 758 /** 759 * 760 */ 761 protected static boolean insideHarness = false; 762 763 /** 764 * Generic hook to allow benchmarks to be harnessed. A plan may use 765 * this to perform certain actions prior to the commencement of a 766 * benchmark, such as a full heap collection, turning on 767 * instrumentation, etc. By default we do a full heap GC, 768 * and then start stats collection. 769 */ 770 @Interruptible 771 public static void harnessBegin() { 772 // Save old values. 773 boolean oldFullHeap = Options.fullHeapSystemGC.getValue(); 774 boolean oldIgnore = Options.ignoreSystemGC.getValue(); 775 776 // Set desired values. 777 Options.fullHeapSystemGC.setValue(true); 778 Options.ignoreSystemGC.setValue(false); 779 780 // Trigger a full heap GC. 781 System.gc(); 782 783 // Restore old values. 784 Options.ignoreSystemGC.setValue(oldIgnore); 785 Options.fullHeapSystemGC.setValue(oldFullHeap); 786 787 // Start statistics 788 insideHarness = true; 789 Stats.startAll(); 790 } 791 792 /** 793 * Generic hook to allow benchmarks to be harnessed. A plan may use 794 * this to perform certain actions after the completion of a 795 * benchmark, such as a full heap collection, turning off 796 * instrumentation, etc. By default we stop all statistics objects 797 * and print their values. 798 */ 799 @Interruptible 800 public static void harnessEnd() { 801 Stats.stopAll(); 802 insideHarness = false; 803 } 804 805 /**************************************************************************** 806 * VM Accounting 807 */ 808 809 /* Global accounting and static access */ 810 811 /** 812 * Return the amount of <i>free memory</i>, in bytes (where free is 813 * defined as not in use). Note that this may overstate the amount 814 * of <i>available memory</i>, which must account for unused memory 815 * that is held in reserve for copying, and therefore unavailable 816 * for allocation. 817 * 818 * @return The amount of <i>free memory</i>, in bytes (where free is 819 * defined as not in use). 820 */ 821 public static Extent freeMemory() { 822 return totalMemory().minus(usedMemory()); 823 } 824 825 /** 826 * Return the amount of <i>available memory</i>, in bytes. Note 827 * that this accounts for unused memory that is held in reserve 828 * for copying, and therefore unavailable for allocation. 829 * 830 * @return The amount of <i>available memory</i>, in bytes. 831 */ 832 public static Extent availableMemory() { 833 return totalMemory().minus(reservedMemory()); 834 } 835 836 /** 837 * Return the amount of <i>memory in use</i>, in bytes. Note that 838 * this excludes unused memory that is held in reserve for copying, 839 * and therefore unavailable for allocation. 840 * 841 * @return The amount of <i>memory in use</i>, in bytes. 842 */ 843 public static Extent usedMemory() { 844 return Conversions.pagesToBytes(VM.activePlan.global().getPagesUsed()); 845 } 846 847 /** 848 * Return the amount of <i>memory in use</i>, in bytes. Note that 849 * this includes unused memory that is held in reserve for copying, 850 * and therefore unavailable for allocation. 851 * 852 * @return The amount of <i>memory in use</i>, in bytes. 853 */ 854 public static Extent reservedMemory() { 855 return Conversions.pagesToBytes(VM.activePlan.global().getPagesReserved()); 856 } 857 858 /** 859 * Return the total amount of memory managed to the memory 860 * management system, in bytes. 861 * 862 * @return The total amount of memory managed to the memory 863 * management system, in bytes. 864 */ 865 public static Extent totalMemory() { 866 return HeapGrowthManager.getCurrentHeapSize(); 867 } 868 869 /* Instance methods */ 870 871 /** 872 * Return the total amount of memory managed to the memory 873 * management system, in pages. 874 * 875 * @return The total amount of memory managed to the memory 876 * management system, in pages. 877 */ 878 public final int getTotalPages() { 879 return totalMemory().toWord().rshl(LOG_BYTES_IN_PAGE).toInt(); 880 } 881 882 /** 883 * Return the number of pages available for allocation. 884 * 885 * @return The number of pages available for allocation. 886 */ 887 public int getPagesAvail() { 888 return getTotalPages() - getPagesReserved(); 889 } 890 891 /** 892 * Return the number of pages reserved for use given the pending 893 * allocation. Sub-classes must override the getCopyReserve method, 894 * as the arithmetic here is fixed. 895 * 896 * @return The number of pages reserved given the pending 897 * allocation, including space reserved for copying. 898 */ 899 public final int getPagesReserved() { 900 return getPagesUsed() + getCollectionReserve(); 901 } 902 903 /** 904 * Return the number of pages reserved for collection. 905 * In most cases this is a copy reserve, all subclasses that 906 * manage a copying space must add the copying contribution. 907 * 908 * @return The number of pages reserved given the pending 909 * allocation, including space reserved for collection. 910 */ 911 public int getCollectionReserve() { 912 return 0; 913 } 914 915 /** 916 * Return the number of pages reserved for use given the pending 917 * allocation. 918 * 919 * @return The number of pages reserved given the pending 920 * allocation, excluding space reserved for copying. 921 */ 922 public int getPagesUsed() { 923 return loSpace.reservedPages() + immortalSpace.reservedPages() + 924 metaDataSpace.reservedPages() + nonMovingSpace.reservedPages(); 925 } 926 927 /**************************************************************************** 928 * Internal read/write barriers. 929 */ 930 931 /** 932 * Store an object reference 933 * 934 * @param slot The location of the reference 935 * @param value The value to store 936 */ 937 @Inline 938 public void storeObjectReference(Address slot, ObjectReference value) { 939 slot.store(value); 940 } 941 942 /** 943 * Load an object reference 944 * 945 * @param slot The location of the reference 946 * @return the object reference loaded from slot 947 */ 948 @Inline 949 public ObjectReference loadObjectReference(Address slot) { 950 return slot.loadObjectReference(); 951 } 952 953 /**************************************************************************** 954 * Collection. 955 */ 956 957 /** 958 * This method is called periodically by the allocation subsystem 959 * (by default, each time a page is consumed), and provides the 960 * collector with an opportunity to collect. 961 * 962 * @param spaceFull Space request failed, must recover pages within 'space'. 963 * @param space The space that triggered the poll. 964 * @return <code>true</code> if a collection is required. 965 */ 966 public final boolean poll(boolean spaceFull, Space space) { 967 if (collectionRequired(spaceFull, space)) { 968 if (space == metaDataSpace) { 969 /* In general we must not trigger a GC on metadata allocation since 970 * this is not, in general, in a GC safe point. Instead we initiate 971 * an asynchronous GC, which will occur at the next safe point. 972 */ 973 logPoll(space, "Asynchronous collection requested"); 974 controlCollectorContext.request(); 975 return false; 976 } 977 logPoll(space, "Triggering collection"); 978 controlCollectorContext.request(); 979 return true; 980 } 981 982 if (concurrentCollectionRequired()) { 983 if (space == metaDataSpace) { 984 logPoll(space, "Triggering async concurrent collection"); 985 triggerInternalCollectionRequest(); 986 return false; 987 } else { 988 logPoll(space, "Triggering concurrent collection"); 989 triggerInternalCollectionRequest(); 990 return true; 991 } 992 } 993 994 return false; 995 } 996 997 protected void logPoll(Space space, String message) { 998 if (Options.verbose.getValue() >= 5) { 999 Log.write(" [POLL] "); 1000 Log.write(space.getName()); 1001 Log.write(": "); 1002 Log.writeln(message); 1003 } 1004 } 1005 1006 /** 1007 * This method controls the triggering of a GC. It is called periodically 1008 * during allocation. Returns <code>true</code> to trigger a collection. 1009 * 1010 * @param spaceFull Space request failed, must recover pages within 'space'. 1011 * @param space TODO 1012 * @return <code>true</code> if a collection is requested by the plan. 1013 */ 1014 protected boolean collectionRequired(boolean spaceFull, Space space) { 1015 boolean stressForceGC = stressTestGCRequired(); 1016 boolean heapFull = getPagesReserved() > getTotalPages(); 1017 1018 return spaceFull || stressForceGC || heapFull; 1019 } 1020 1021 /** 1022 * This method controls the triggering of an atomic phase of a concurrent 1023 * collection. It is called periodically during allocation. 1024 * 1025 * @return <code>true</code> if a collection is requested by the plan. 1026 */ 1027 protected boolean concurrentCollectionRequired() { 1028 return false; 1029 } 1030 1031 /** 1032 * Start GCspy server. 1033 * 1034 * @param port The port to listen on, 1035 * @param wait Should we wait for a client to connect? 1036 */ 1037 @Interruptible 1038 public void startGCspyServer(int port, boolean wait) { 1039 VM.assertions.fail("startGCspyServer called on non GCspy plan"); 1040 } 1041 1042 /** 1043 * Can this object ever move. Used by the VM to make decisions about 1044 * whether it needs to copy IO buffers etc. 1045 * 1046 * @param object The object in question 1047 * @return <code>true</code> if it is not possible that the object will ever move. 1048 */ 1049 public boolean willNeverMove(ObjectReference object) { 1050 if (!VM.activePlan.constraints().movesObjects()) 1051 return true; 1052 if (Space.isInSpace(LOS, object)) 1053 return true; 1054 if (Space.isInSpace(IMMORTAL, object)) 1055 return true; 1056 if (Space.isInSpace(VM_SPACE, object)) 1057 return true; 1058 if (Space.isInSpace(NON_MOVING, object)) 1059 return true; 1060 if (USE_CODE_SPACE && Space.isInSpace(SMALL_CODE, object)) 1061 return true; 1062 if (USE_CODE_SPACE && Space.isInSpace(LARGE_CODE, object)) 1063 return true; 1064 /* 1065 * Default to false- this preserves correctness over efficiency. 1066 * Individual plans should override for non-moving spaces they define. 1067 */ 1068 return false; 1069 } 1070 1071 /**************************************************************************** 1072 * Specialized Methods 1073 */ 1074 1075 /** 1076 * Registers specialized methods. 1077 */ 1078 @Interruptible 1079 protected void registerSpecializedMethods() {} 1080 1081 /** 1082 * @param id the id of the specialized scan class 1083 * @return the specialized scan with the given id 1084 */ 1085 public final Class<?> getSpecializedScanClass(int id) { 1086 return TransitiveClosure.getSpecializedScanClass(id); 1087 } 1088}