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