--- old/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java Fri Sep 9 14:16:04 2011 +++ new/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java Fri Sep 9 14:16:04 2011 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -150,6 +150,19 @@ return VM.getVM().getOopSize(); } + static HashMap typeToVtbl = new HashMap(); + + private Address vtblForType(Type type) { + Address vtblAddr = (Address)typeToVtbl.get(type); + if (vtblAddr == null) { + vtblAddr = vtblAccess.getVtblForType(type); + if (vtblAddr != null) { + typeToVtbl.put(type, vtblAddr); + } + } + return vtblAddr; + } + public boolean addressTypeIsEqualToType(Address addr, Type type) { if (addr == null) { return false; @@ -158,7 +171,7 @@ // This implementation should be suitably platform-independent; we // search nearby memory for the vtbl value of the given type. - Address vtblAddr = vtblAccess.getVtblForType(type); + Address vtblAddr = vtblForType(type); if (vtblAddr == null) { // Type was not polymorphic, or an error occurred during lookup @@ -251,6 +264,78 @@ return false; } + public Type findDynamicTypeForAddress(Address addr, Type baseType) { + // This implementation should be suitably platform-independent; we + // search nearby memory for the vtbl value of the given type. + + if (vtblForType(baseType) == null) { + // Type was not polymorphic which is an error of some sort + throw new InternalError(baseType + " does not appear to be polymorphic"); + } + + // This is a more restricted version of guessTypeForAddress since + // that function has some limitations since it doesn't really know + // where in the hierarchy a virtual type starts and just poking + // around in memory is likely to trip over some vtable address, + // resulting in false positives. Eventually all uses should + // switch to this logic but in the interests of stability it will + // be separate for the moment. + + // Assuming that the base type is truly the first polymorphic type + // then the vtbl for all subclasss should be at several defined + // locations so only those locations will be checked. It's also + // required that the caller knows that the static type is at least + // baseType. See the notes in guessTypeForAddress for the logic of + // the locations searched. + + Address loc1 = addr.getAddressAt(0); + Address loc2 = null; + Address loc3 = null; + long offset2 = baseType.getSize(); + // I don't think this should be misaligned under any + // circumstances, but I'm not sure (FIXME: also not sure which + // way to go here, up or down -- assuming down) + offset2 = offset2 - (offset2 % getAddressSize()) - getAddressSize(); + if (offset2 > 0) { + loc2 = addr.getAddressAt(offset2); + } + long offset3 = offset2 - getAddressSize(); + if (offset3 > 0) { + loc3 = addr.getAddressAt(offset3); + } + + Type loc2Match = null; + Type loc3Match = null; + for (Iterator iter = getTypes(); iter.hasNext(); ) { + Type type = (Type) iter.next(); + Type superClass = type; + while (superClass != baseType && superClass != null) { + superClass = superClass.getSuperclass(); + } + if (superClass == null) continue; + Address vtblAddr = vtblForType(type); + if (vtblAddr == null) { + // This occurs sometimes for intermediate types that are never + // instantiated. + if (DEBUG) { + System.err.println("null vtbl for " + type); + } + continue; + } + // Prefer loc1 match + if (vtblAddr.equals(loc1)) return type; + if (loc2 != null && loc2Match == null && vtblAddr.equals(loc2)) { + loc2Match = type; + } + if (loc3 != null && loc3Match == null && vtblAddr.equals(loc3)) { + loc3Match = type; + } + } + if (loc2Match != null) return loc2Match; + if (loc3Match != null) return loc3Match; + return null; + } + public Type guessTypeForAddress(Address addr) { for (Iterator iter = getTypes(); iter.hasNext(); ) { Type t = (Type) iter.next();