/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Common Public License (CPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/cpl1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.memorymanagers.mminterface; import org.jikesrvm.VM; import org.jikesrvm.VM_Constants; import org.jikesrvm.classloader.VM_Array; import org.jikesrvm.classloader.VM_Type; import org.jikesrvm.objectmodel.VM_ObjectModel; import org.jikesrvm.runtime.VM_BootRecord; import org.jikesrvm.runtime.VM_Magic; import org.jikesrvm.scheduler.VM_Scheduler; import org.mmtk.policy.Space; import org.mmtk.utility.Constants; import org.mmtk.utility.heap.Mmapper; import org.vmmagic.pragma.Interruptible; import org.vmmagic.pragma.Uninterruptible; import org.vmmagic.unboxed.Address; import org.vmmagic.unboxed.ObjectReference; /** * Common debugging utility functions used by various garbage collectors */ @Uninterruptible public class DebugUtil implements VM_Constants, Constants { private static Object[] tibForArrayType; private static Object[] tibForClassType; private static Object[] tibForPrimitiveType; @Interruptible static void boot(VM_BootRecord theBootRecord) { // get addresses of TIBs for VM_Array & VM_Class used for testing Type ptrs VM_Type t = VM_Array.IntArray; tibForArrayType = VM_ObjectModel.getTIB(t); tibForPrimitiveType = VM_ObjectModel.getTIB(VM_Type.IntType); t = VM_Magic.getObjectType(VM_BootRecord.the_boot_record); tibForClassType = VM_ObjectModel.getTIB(t); } /** * Check if an address appears to point to an instance of VM_Type * * @param typeAddress the address to check */ @Uninterruptible public static boolean validType(ObjectReference typeAddress) { if (!Space.isMappedObject(typeAddress)) { return false; // type address is outside of heap } // check if types tib is one of three possible values Object[] typeTib = VM_ObjectModel.getTIB(typeAddress); return ((typeTib == tibForClassType) || (typeTib == tibForArrayType) || (typeTib == tibForPrimitiveType)); } /** * Dump all threads & their stacks starting at the frame identified * by the threads saved contextRegisters (ip & fp fields). */ @Uninterruptible public static void dumpAllThreadStacks() { VM_Scheduler.dumpVirtualMachine(); } // dumpAllThreadStacks /** * Check if a ref, its tib pointer & type pointer are all in the heap */ @Uninterruptible public static boolean validObject(Object ref) { return validRef(ObjectReference.fromObject(ref)); } @Uninterruptible public static boolean validRef(ObjectReference ref) { if (ref.isNull()) return true; if (!Space.isMappedObject(ref)) { VM.sysWrite("validRef: REF outside heap, ref = "); VM.sysWrite(ref); VM.sysWrite("\n"); Space.printVMMap(); return false; } if (MM_Constants.MOVES_OBJECTS) { /* TODO: Work out how to check if forwarded if (Plan.isForwardedOrBeingForwarded(ref)) { // TODO: actually follow forwarding pointer // (need to bound recursion when things are broken!!) return true; } */ } Object[] tib = VM_ObjectModel.getTIB(ref); Address tibAddr = VM_Magic.objectAsAddress(tib); if (!Space.isMappedObject(ObjectReference.fromObject(tib))) { VM.sysWrite("validRef: TIB outside heap, ref = "); VM.sysWrite(ref); VM.sysWrite(" tib = "); VM.sysWrite(tibAddr); VM.sysWrite("\n"); return false; } if (tibAddr.isZero()) { VM.sysWrite("validRef: TIB is Zero! "); VM.sysWrite(ref); VM.sysWrite("\n"); return false; } if (tib.length == 0) { VM.sysWrite("validRef: TIB length zero, ref = "); VM.sysWrite(ref); VM.sysWrite(" tib = "); VM.sysWrite(tibAddr); VM.sysWrite("\n"); return false; } ObjectReference type = ObjectReference.fromObject(tib[0]); if (!validType(type)) { VM.sysWrite("validRef: invalid TYPE, ref = "); VM.sysWrite(ref); VM.sysWrite(" tib = "); VM.sysWrite(VM_Magic.objectAsAddress(tib)); VM.sysWrite(" type = "); VM.sysWrite(type); VM.sysWrite("\n"); return false; } return true; } // validRef @Uninterruptible public static boolean mappedVMRef(ObjectReference ref) { return Space.isMappedObject(ref) && Mmapper.objectIsMapped(ref); } @Uninterruptible public static void dumpRef(ObjectReference ref) { VM.sysWrite("REF="); if (ref.isNull()) { VM.sysWrite("NULL\n"); return; } VM.sysWrite(ref); if (!mappedVMRef(ref)) { VM.sysWrite(" (REF OUTSIDE OF HEAP OR NOT MAPPED)\n"); return; } VM_ObjectModel.dumpHeader(ref); ObjectReference tib = ObjectReference.fromObject(VM_ObjectModel.getTIB(ref)); if (!MM_Interface.mightBeTIB(tib)) { VM.sysWrite(" (INVALID TIB: CLASS NOT ACCESSIBLE)\n"); return; } VM_Type type = VM_Magic.getObjectType(ref.toObject()); ObjectReference itype = ObjectReference.fromObject(type); VM.sysWrite(" TYPE="); VM.sysWrite(itype); if (!validType(itype)) { VM.sysWrite(" (INVALID TYPE: CLASS NOT ACCESSIBLE)\n"); return; } VM.sysWrite(" CLASS="); VM.sysWrite(type.getDescriptor()); VM.sysWrite("\n"); } public static boolean addrInBootImage(Address addr) { return (addr.GE(BOOT_IMAGE_DATA_START) && addr.LT(BOOT_IMAGE_DATA_END)) || (addr.GE(BOOT_IMAGE_CODE_START) && addr.LT(BOOT_IMAGE_CODE_END)); } }