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