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.jikesrvm.mm.mminterface; 014 015import static org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_CODE_END; 016import static org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_CODE_START; 017import static org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_END; 018import static org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_START; 019import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.MOVES_OBJECTS; 020 021import org.jikesrvm.VM; 022import org.jikesrvm.classloader.RVMArray; 023import org.jikesrvm.classloader.RVMType; 024import org.jikesrvm.objectmodel.ObjectModel; 025import org.jikesrvm.objectmodel.TIB; 026import org.jikesrvm.runtime.BootRecord; 027import org.jikesrvm.runtime.Magic; 028import org.jikesrvm.scheduler.RVMThread; 029import org.mmtk.policy.Space; 030import org.mmtk.utility.heap.Mmapper; 031import org.vmmagic.pragma.Interruptible; 032import org.vmmagic.pragma.Uninterruptible; 033import org.vmmagic.unboxed.Address; 034import org.vmmagic.unboxed.ObjectReference; 035 036/** 037 * Common debugging utility functions used by various garbage collectors 038 */ 039@Uninterruptible 040public class DebugUtil { 041 042 private static TIB tibForArrayType; 043 private static TIB tibForClassType; 044 private static TIB tibForPrimitiveType; 045 046 @Interruptible 047 static void boot(BootRecord theBootRecord) { 048 // get addresses of TIBs for RVMArray & RVMClass used for testing Type ptrs 049 RVMType t = RVMArray.IntArray; 050 tibForArrayType = ObjectModel.getTIB(t); 051 tibForPrimitiveType = ObjectModel.getTIB(RVMType.IntType); 052 t = Magic.getObjectType(BootRecord.the_boot_record); 053 tibForClassType = ObjectModel.getTIB(t); 054 } 055 056 /** 057 * Check if an address appears to point to an instance of RVMType 058 * 059 * @param typeAddress the address to check 060 * @return {@code true} if and only if the address appears to 061 * be an an instance of RVMType 062 */ 063 @Uninterruptible 064 public static boolean validType(ObjectReference typeAddress) { 065 if (!Space.isMappedObject(typeAddress)) { 066 return false; // type address is outside of heap 067 } 068 069 // check if types tib is one of three possible values 070 TIB typeTib = ObjectModel.getTIB(typeAddress); 071 return ((typeTib == tibForClassType) || (typeTib == tibForArrayType) || (typeTib == tibForPrimitiveType)); 072 } 073 074 /** 075 * Dump all threads & their stacks starting at the frame identified 076 * by the threads saved contextRegisters (ip & fp fields). 077 */ 078 @Uninterruptible 079 public static void dumpAllThreadStacks() { 080 RVMThread.dumpVirtualMachine(); 081 } // dumpAllThreadStacks 082 083 /** 084 * Checks if a reference, its TIB pointer and type pointer 085 * are all in the heap. 086 * 087 * @param ref the reference to check 088 * @return {@code true} if and only if the reference 089 * refers to a valid object 090 */ 091 @Uninterruptible 092 public static boolean validObject(Object ref) { 093 return validRef(ObjectReference.fromObject(ref)); 094 } 095 096 @Uninterruptible 097 public static boolean validRef(ObjectReference ref) { 098 099 if (ref.isNull()) return true; 100 if (!Space.isMappedObject(ref)) { 101 VM.sysWrite("validRef: REF outside heap, ref = "); 102 VM.sysWrite(ref); 103 VM.sysWrite("\n"); 104 Space.printVMMap(); 105 return false; 106 } 107 if (MOVES_OBJECTS) { 108 /* 109 TODO: Work out how to check if forwarded 110 if (Plan.isForwardedOrBeingForwarded(ref)) { 111 // TODO: actually follow forwarding pointer 112 // (need to bound recursion when things are broken!!) 113 return true; 114 } 115 */ 116 } 117 118 TIB tib = ObjectModel.getTIB(ref); 119 Address tibAddr = Magic.objectAsAddress(tib); 120 if (!Space.isMappedObject(ObjectReference.fromObject(tib))) { 121 VM.sysWrite("validRef: TIB outside heap, ref = "); 122 VM.sysWrite(ref); 123 VM.sysWrite(" tib = "); 124 VM.sysWrite(tibAddr); 125 VM.sysWrite("\n"); 126 ObjectModel.dumpHeader(ref); 127 return false; 128 } 129 if (tibAddr.isZero()) { 130 VM.sysWrite("validRef: TIB is Zero! "); 131 VM.sysWrite(ref); 132 VM.sysWrite("\n"); 133 ObjectModel.dumpHeader(ref); 134 return false; 135 } 136 if (tib.length() == 0) { 137 VM.sysWrite("validRef: TIB length zero, ref = "); 138 VM.sysWrite(ref); 139 VM.sysWrite(" tib = "); 140 VM.sysWrite(tibAddr); 141 VM.sysWrite("\n"); 142 ObjectModel.dumpHeader(ref); 143 return false; 144 } 145 146 ObjectReference type = ObjectReference.fromObject(tib.getType()); 147 if (!validType(type)) { 148 VM.sysWrite("validRef: invalid TYPE, ref = "); 149 VM.sysWrite(ref); 150 VM.sysWrite(" tib = "); 151 VM.sysWrite(Magic.objectAsAddress(tib)); 152 VM.sysWrite(" type = "); 153 VM.sysWrite(type); 154 VM.sysWrite("\n"); 155 ObjectModel.dumpHeader(ref); 156 return false; 157 } 158 return true; 159 } // validRef 160 161 @Uninterruptible 162 public static boolean mappedVMRef(ObjectReference ref) { 163 return Space.isMappedObject(ref) && Mmapper.objectIsMapped(ref); 164 } 165 166 @Uninterruptible 167 public static void dumpRef(ObjectReference ref) { 168 VM.sysWrite("REF="); 169 if (ref.isNull()) { 170 VM.sysWrite("NULL\n"); 171 return; 172 } 173 VM.sysWrite(ref); 174 if (!mappedVMRef(ref)) { 175 VM.sysWrite(" (REF OUTSIDE OF HEAP OR NOT MAPPED)\n"); 176 return; 177 } 178 ObjectModel.dumpHeader(ref); 179 ObjectReference tib = ObjectReference.fromObject(ObjectModel.getTIB(ref)); 180 if (!MemoryManager.mightBeTIB(tib)) { 181 VM.sysWrite(" (INVALID TIB: CLASS NOT ACCESSIBLE)\n"); 182 return; 183 } 184 RVMType type = Magic.getObjectType(ref.toObject()); 185 ObjectReference itype = ObjectReference.fromObject(type); 186 VM.sysWrite(" TYPE="); 187 VM.sysWrite(itype); 188 if (!validType(itype)) { 189 VM.sysWrite(" (INVALID TYPE: CLASS NOT ACCESSIBLE)\n"); 190 return; 191 } 192 VM.sysWrite(" CLASS="); 193 VM.sysWrite(type.getDescriptor()); 194 VM.sysWrite("\n"); 195 } 196 197 public static boolean addrInBootImage(Address addr) { 198 return (addr.GE(BOOT_IMAGE_DATA_START) && addr.LT(BOOT_IMAGE_DATA_END)) || 199 (addr.GE(BOOT_IMAGE_CODE_START) && addr.LT(BOOT_IMAGE_CODE_END)); 200 } 201}