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 }