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.mm.mmtk; 014 015 import org.mmtk.plan.CollectorContext; 016 import org.mmtk.plan.TraceLocal; 017 import org.mmtk.utility.Constants; 018 import org.mmtk.utility.Log; 019 import org.jikesrvm.VM; 020 import org.jikesrvm.runtime.Statics; 021 import org.jikesrvm.runtime.Magic; 022 import org.jikesrvm.scheduler.RVMThread; 023 import org.jikesrvm.mm.mminterface.MemoryManager; 024 025 import org.vmmagic.unboxed.*; 026 import org.vmmagic.pragma.*; 027 028 /** 029 * Class that determines all JTOC slots (statics) that hold references 030 */ 031 public final class ScanStatics implements Constants { 032 /** 033 * Size in 32bits words of a JTOC slot (ie 32bit addresses = 1, 034 * 64bit addresses =2) 035 */ 036 private static final int refSlotSize = Statics.getReferenceSlotSize(); 037 /** 038 * Mask used when calculating the chunkSize to ensure chunks are 039 * 64bit aligned on 64bit architectures 040 */ 041 private static final int chunkSizeMask = 0xFFFFFFFF - (refSlotSize - 1); 042 /** 043 * Scan static variables (JTOC) for object references. Executed by 044 * all GC threads in parallel, with each doing a portion of the 045 * JTOC. 046 */ 047 @Inline 048 @Uninterruptible 049 public static void scanStatics(TraceLocal trace) { 050 // The address of the statics table 051 // equivalent to Statics.getSlots() 052 final Address slots = Magic.getJTOC(); 053 // This thread as a collector 054 final CollectorContext cc = RVMThread.getCurrentThread().getCollectorContext(); 055 // The number of collector threads 056 final int numberOfCollectors = cc.parallelWorkerCount(); 057 // The number of static references 058 final int numberOfReferences = Statics.getNumberOfReferenceSlots(); 059 // The size to give each thread 060 final int chunkSize = (numberOfReferences / numberOfCollectors) & chunkSizeMask; 061 // The number of this collector thread (1...n) 062 final int threadOrdinal = cc.parallelWorkerOrdinal(); 063 064 // Start and end of statics region to be processed 065 final int start = (threadOrdinal == 0) ? refSlotSize : threadOrdinal * chunkSize; 066 final int end = (threadOrdinal+1 == numberOfCollectors) ? numberOfReferences : (threadOrdinal+1) * chunkSize; 067 068 // Process region 069 for (int slot=start; slot < end; slot+=refSlotSize) { 070 Offset slotOffset = Offset.fromIntSignExtend(slot << LOG_BYTES_IN_INT); 071 if (ScanThread.VALIDATE_REFS) checkReference(slots.plus(slotOffset), slot); 072 trace.processRootEdge(slots.plus(slotOffset), true); 073 } 074 } 075 076 /** 077 * Check that a reference encountered during scanning is valid. If 078 * the reference is invalid, dump stack and die. 079 * 080 * @param refaddr The address of the reference in question. 081 */ 082 @Uninterruptible 083 private static void checkReference(Address refaddr, int slot) { 084 ObjectReference ref = refaddr.loadObjectReference(); 085 if (!MemoryManager.validRef(ref)) { 086 Log.writeln(); 087 Log.writeln("Invalid ref reported while scanning statics"); 088 Log.write("Static slot: "); Log.writeln(slot); 089 Log.writeln(); 090 Log.write(refaddr); Log.write(":"); Log.flush(); MemoryManager.dumpRef(ref); 091 Log.writeln(); 092 Log.writeln("Dumping stack:"); 093 RVMThread.dumpStack(); 094 VM.sysFail("\n\nScanStack: Detected bad GC map; exiting RVM with fatal error"); 095 } 096 } 097 }