# HG changeset patch # User twisti # Date 1294401491 28800 # Node ID 0e52ef6e94d35ad169cf82a629916e871726baba # Parent 55f868e91c3bfaed0cda08afce220bf22d600e1e# Parent 5a1e52a439fac6fab2ddf52901b83eed50c86e42 Merge diff -r 55f868e91c3b -r 0e52ef6e94d3 .hgtags --- a/.hgtags Thu Jan 06 16:03:20 2011 -0800 +++ b/.hgtags Fri Jan 07 03:58:11 2011 -0800 @@ -134,4 +134,7 @@ 5484e7c53fa7da5e869902437ee08a9ae10c1c69 jdk7-b119 f5603a6e50422046ebc0d2f1671d55cb8f1bf1e9 jdk7-b120 3f3653ab7af8dc1ddb9fa75dad56bf94f89e81a8 jdk7-b121 +3a548dc9cb456110ca8fc1514441a8c3bda0014d jdk7-b122 5484e7c53fa7da5e869902437ee08a9ae10c1c69 hs20-b03 +9669f9b284108a9ee0a0ccbe215c37a130c9dcf5 jdk7-b123 +9669f9b284108a9ee0a0ccbe215c37a130c9dcf5 hs20-b04 diff -r 55f868e91c3b -r 0e52ef6e94d3 agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java --- a/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java Thu Jan 06 16:03:20 2011 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java Fri Jan 07 03:58:11 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, 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 @@ -99,15 +99,8 @@ long typeEntrySizeOffset; long typeEntryArrayStride; - typeEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset"); - typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset"); - typeEntryIsOopTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset"); - typeEntryIsIntegerTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset"); - typeEntryIsUnsignedOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset"); - typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset"); - typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride"); - - // Fetch the address of the VMTypeEntry* + // Fetch the address of the VMTypeEntry*. We get this symbol first + // and try to use it to make sure that symbol lookup is working. Address entryAddr = lookupInProcess("gHotSpotVMTypes"); // System.err.println("gHotSpotVMTypes address = " + entryAddr); // Dereference this once to get the pointer to the first VMTypeEntry @@ -118,6 +111,14 @@ throw new RuntimeException("gHotSpotVMTypes was not initialized properly in the remote process; can not continue"); } + typeEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset"); + typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset"); + typeEntryIsOopTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset"); + typeEntryIsIntegerTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset"); + typeEntryIsUnsignedOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset"); + typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset"); + typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride"); + // Start iterating down it until we find an entry with no name Address typeNameAddr = null; do { diff -r 55f868e91c3b -r 0e52ef6e94d3 agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java --- a/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java Thu Jan 06 16:03:20 2011 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java Fri Jan 07 03:58:11 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, 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 @@ -122,10 +122,14 @@ private MemoizedObject[] sectionHeaders; private MemoizedObject[] symbols; + // Init stringTable at decl time since other fields init'ed in the + // constructor need the String Table. private MemoizedObject stringTable = new MemoizedObject() { public Object computeValue() { + // the String Table follows the Symbol Table int ptr = getPointerToSymbolTable(); if (ptr == 0) { + // no Symbol Table so no String Table return new StringTable(0); } else { return new StringTable(ptr + SYMBOL_SIZE * getNumberOfSymbols()); @@ -140,6 +144,8 @@ timeDateStamp = readInt(); pointerToSymbolTable = readInt(); numberOfSymbols = readInt(); + // String Table can be accessed at this point because + // pointerToSymbolTable and numberOfSymbols fields are set. sizeOfOptionalHeader = readShort(); characteristics = readShort(); @@ -222,6 +228,8 @@ private MemoizedObject windowsSpecificFields; private MemoizedObject dataDirectories; + // We use an offset of 2 because OptionalHeaderStandardFieldsImpl doesn't + // include the 'magic' field. private static final int STANDARD_FIELDS_OFFSET = 2; private static final int PE32_WINDOWS_SPECIFIC_FIELDS_OFFSET = 28; private static final int PE32_DATA_DIRECTORIES_OFFSET = 96; @@ -288,7 +296,7 @@ private int sizeOfUninitializedData; private int addressOfEntryPoint; private int baseOfCode; - private int baseOfData; + private int baseOfData; // only set in PE32 OptionalHeaderStandardFieldsImpl(int offset, boolean isPE32Plus) { @@ -301,7 +309,8 @@ sizeOfUninitializedData = readInt(); addressOfEntryPoint = readInt(); baseOfCode = readInt(); - if (isPE32Plus) { + if (!isPE32Plus) { + // only available in PE32 baseOfData = readInt(); } } @@ -433,7 +442,10 @@ if (dir.getRVA() == 0 || dir.getSize() == 0) { return null; } - return new ExportDirectoryTableImpl(rvaToFileOffset(dir.getRVA()), dir.getSize()); + // ExportDirectoryTableImpl needs both the RVA and the + // RVA converted to a file offset. + return new + ExportDirectoryTableImpl(dir.getRVA(), dir.getSize()); } }; @@ -526,6 +538,7 @@ } class ExportDirectoryTableImpl implements ExportDirectoryTable { + private int exportDataDirRVA; private int offset; private int size; @@ -548,8 +561,9 @@ private MemoizedObject exportOrdinalTable; private MemoizedObject exportAddressTable; - ExportDirectoryTableImpl(int offset, int size) { - this.offset = offset; + ExportDirectoryTableImpl(int exportDataDirRVA, int size) { + this.exportDataDirRVA = exportDataDirRVA; + offset = rvaToFileOffset(exportDataDirRVA); this.size = size; seek(offset); exportFlags = readInt(); @@ -595,6 +609,7 @@ exportOrdinalTable = new MemoizedObject() { public Object computeValue() { + // number of ordinals is same as the number of name pointers short[] ordinals = new short[getNumberOfNamePointers()]; seek(rvaToFileOffset(getOrdinalTableRVA())); for (int i = 0; i < ordinals.length; i++) { @@ -608,14 +623,18 @@ public Object computeValue() { int[] addresses = new int[getNumberOfAddressTableEntries()]; seek(rvaToFileOffset(getExportAddressTableRVA())); - // Must make two passes to avoid rvaToFileOffset - // destroying seek() position + // The Export Address Table values are a union of two + // possible values: + // Export RVA - The address of the exported symbol when + // loaded into memory, relative to the image base. + // This value doesn't get converted into a file offset. + // Forwarder RVA - The pointer to a null-terminated ASCII + // string in the export section. This value gets + // converted into a file offset because we have to + // fetch the string. for (int i = 0; i < addresses.length; i++) { addresses[i] = readInt(); } - for (int i = 0; i < addresses.length; i++) { - addresses[i] = rvaToFileOffset(addresses[i]); - } return addresses; } }; @@ -648,11 +667,12 @@ public boolean isExportAddressForwarder(short ordinal) { int addr = getExportAddress(ordinal); - return ((offset <= addr) && (addr < (offset + size))); + return ((exportDataDirRVA <= addr) && + (addr < (exportDataDirRVA + size))); } public String getExportAddressForwarder(short ordinal) { - seek(getExportAddress(ordinal)); + seek(rvaToFileOffset(getExportAddress(ordinal))); return readCString(); } @@ -3371,10 +3391,17 @@ throw new COFFException(e); } // Look up in string table + // FIXME: this index value is assumed to be in the valid range name = getStringTable().get(index); } else { try { - name = new String(tmpName, US_ASCII); + int length = 0; + // find last non-NULL + for (; length < tmpName.length && tmpName[length] != '\0';) { + length++; + } + // don't include NULL chars in returned name String + name = new String(tmpName, 0, length, US_ASCII); } catch (UnsupportedEncodingException e) { throw new COFFException(e); } @@ -3487,6 +3514,7 @@ tmpName[5] << 16 | tmpName[6] << 8 | tmpName[7]); + // FIXME: stringOffset is assumed to be in the valid range name = getStringTable().getAtOffset(stringOffset); } @@ -3698,12 +3726,13 @@ StringTable(int offset) { if (offset == 0) { + // no String Table strings = new COFFString[0]; return; } seek(offset); - int length = readInt(); + int length = readInt(); // length includes itself byte[] data = new byte[length - 4]; int numBytesRead = readBytes(data); if (numBytesRead != data.length) { diff -r 55f868e91c3b -r 0e52ef6e94d3 agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java --- a/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java Thu Jan 06 16:03:20 2011 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java Fri Jan 07 03:58:11 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2010, 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 @@ -37,35 +37,48 @@ String filename = args[0]; COFFFile file = COFFFileParser.getParser().parse(filename); - ExportDirectoryTable exports = - file.getHeader(). - getOptionalHeader(). - getDataDirectories(). - getExportDirectoryTable(); + + // get common point for both things we want to dump + OptionalHeaderDataDirectories dataDirs = file.getHeader().getOptionalHeader(). + getDataDirectories(); + + // dump the header data directory for the Export Table: + DataDirectory dir = dataDirs.getExportTable(); + System.out.println("Export table: RVA = " + dir.getRVA() + "/0x" + + Integer.toHexString(dir.getRVA()) + ", size = " + dir.getSize() + "/0x" + + Integer.toHexString(dir.getSize())); + + System.out.println(file.getHeader().getNumberOfSections() + " sections in file"); + for (int i = 1; i <= file.getHeader().getNumberOfSections(); i++) { + SectionHeader sec = file.getHeader().getSectionHeader(i); + System.out.println(" Section " + i + ":"); + System.out.println(" Name = '" + sec.getName() + "'"); + System.out.println(" VirtualSize = " + sec.getSize() + "/0x" + + Integer.toHexString(sec.getSize())); + System.out.println(" VirtualAddress = " + sec.getVirtualAddress() + "/0x" + + Integer.toHexString(sec.getVirtualAddress())); + System.out.println(" SizeOfRawData = " + sec.getSizeOfRawData() + "/0x" + + Integer.toHexString(sec.getSizeOfRawData())); + System.out.println(" PointerToRawData = " + sec.getPointerToRawData() + "/0x" + + Integer.toHexString(sec.getPointerToRawData())); + } + + ExportDirectoryTable exports = dataDirs.getExportDirectoryTable(); if (exports == null) { System.out.println("No exports found."); } else { - System.out.println(file.getHeader().getNumberOfSections() + " sections in file"); - for (int i = 0; i < file.getHeader().getNumberOfSections(); i++) { - System.out.println(" Section " + i + ": " + file.getHeader().getSectionHeader(1 + i).getName()); - } - - DataDirectory dir = file.getHeader().getOptionalHeader().getDataDirectories().getExportTable(); - System.out.println("Export table: RVA = 0x" + Integer.toHexString(dir.getRVA()) + - ", size = 0x" + Integer.toHexString(dir.getSize())); - System.out.println("DLL name: " + exports.getDLLName()); System.out.println("Time/date stamp 0x" + Integer.toHexString(exports.getTimeDateStamp())); System.out.println("Major version 0x" + Integer.toHexString(exports.getMajorVersion() & 0xFFFF)); System.out.println("Minor version 0x" + Integer.toHexString(exports.getMinorVersion() & 0xFFFF)); - System.out.println(exports.getNumberOfNamePointers() + " functions found"); + System.out.println(exports.getNumberOfNamePointers() + " exports found"); for (int i = 0; i < exports.getNumberOfNamePointers(); i++) { - System.out.println(" 0x" + - Integer.toHexString(exports.getExportAddress(exports.getExportOrdinal(i))) + - " " + - (exports.isExportAddressForwarder(exports.getExportOrdinal(i)) ? - ("Forwarded to " + exports.getExportAddressForwarder(exports.getExportOrdinal(i))) : - exports.getExportName(i))); + short ordinal = exports.getExportOrdinal(i); + System.out.print("[" + i + "] '" + exports.getExportName(i) + "': [" + + ordinal + "] = 0x" + Integer.toHexString(exports.getExportAddress(ordinal))); + System.out.println(exports.isExportAddressForwarder(ordinal) + ? " Forwarded to '" + exports.getExportAddressForwarder(ordinal) + "'" + : ""); } } } diff -r 55f868e91c3b -r 0e52ef6e94d3 agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java --- a/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java Thu Jan 06 16:03:20 2011 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java Fri Jan 07 03:58:11 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, 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 @@ -42,8 +42,8 @@ COFFHeader header = file.getHeader(); int numSections = header.getNumberOfSections(); System.out.println(numSections + " sections detected."); - for (int i = 0; i < numSections; i++) { - SectionHeader secHeader = header.getSectionHeader(1 + i); + for (int i = 1; i <= numSections; i++) { + SectionHeader secHeader = header.getSectionHeader(i); System.out.println(secHeader.getName()); } diff -r 55f868e91c3b -r 0e52ef6e94d3 agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java --- a/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java Thu Jan 06 16:03:20 2011 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java Fri Jan 07 03:58:11 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2010, 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 @@ -506,7 +506,6 @@ throw new DebuggerException("Unimplemented"); } - private static String DTFWHome; private static String imagePath; private static String symbolPath; private static boolean useNativeLookup; @@ -514,81 +513,143 @@ static { /* - * sawindbg.dll depends on dbgeng.dll which - * itself depends on dbghelp.dll. dbgeng.dll and dbghelp.dll. - * On systems newer than Windows 2000, these two .dlls are - * in the standard system directory so we will find them there. - * On Windows 2000 and earlier, these files do not exist. - * The user must download Debugging Tools For Windows (DTFW) - * and install it in order to use SA. + * sawindbg.dll depends on dbgeng.dll which itself depends on + * dbghelp.dll. We have to make sure that the dbgeng.dll and + * dbghelp.dll that we load are compatible with each other. We + * load both of those libraries from the same directory based + * on the theory that co-located libraries are compatible. + * + * On Windows 2000 and earlier, dbgeng.dll and dbghelp.dll were + * not included as part of the standard system directory. On + * systems newer than Windows 2000, dbgeng.dll and dbghelp.dll + * are included in the standard system directory. However, the + * versions included in the standard system directory may not + * be able to handle symbol information for the newer compilers. + * + * We search for and explicitly load the libraries using the + * following directory search order: * - * We have to make sure we use the two files from the same directory - * in case there are more than one copy on the system because - * one version of dbgeng.dll might not be compatible with a - * different version of dbghelp.dll. - * We first look for them in the directory pointed at by - * env. var. DEBUGGINGTOOLSFORWINDOWS, next in the default - * installation dir for DTFW, and lastly in the standard - * system directory. We expect that that we will find - * them in the standard system directory on all systems - * newer than Windows 2000. + * - java.home/bin (same as $JAVA_HOME/jre/bin) + * - dir named by DEBUGGINGTOOLSFORWINDOWS environment variable + * - various "Debugging Tools For Windows" program directories + * - the system directory ($SYSROOT/system32) + * + * If SA is invoked with -Dsun.jvm.hotspot.loadLibrary.DEBUG=1, + * then debug messages about library loading are printed to + * System.err. */ - String dirName = null; - DTFWHome = System.getenv("DEBUGGINGTOOLSFORWINDOWS"); - if (DTFWHome == null) { - // See if we have the files in the default location. - String sysRoot = System.getenv("SYSTEMROOT"); - DTFWHome = sysRoot + File.separator + - ".." + File.separator + "Program Files" + - File.separator + "Debugging Tools For Windows"; - } + String dbgengPath = null; + String dbghelpPath = null; + String sawindbgPath = null; + List searchList = new ArrayList(); + + boolean loadLibraryDEBUG = + System.getProperty("sun.jvm.hotspot.loadLibrary.DEBUG") != null; { - String dbghelp = DTFWHome + File.separator + "dbghelp.dll"; - String dbgeng = DTFWHome + File.separator + "dbgeng.dll"; - File fhelp = new File(dbghelp); - File feng = new File(dbgeng); - if (fhelp.exists() && feng.exists()) { - // found both, we are happy. - // NOTE: The order of loads is important! If we load dbgeng.dll - // first, then the dependency - dbghelp.dll - will be loaded - // from usual DLL search thereby defeating the purpose! - System.load(dbghelp); - System.load(dbgeng); - } else if (! fhelp.exists() && ! feng.exists()) { - // neither exist. We will ignore this dir and assume - // they are in the system dir. - DTFWHome = null; - } else { - // one exists but not the other - //System.err.println("Error: Both files dbghelp.dll and dbgeng.dll " - // "must exist in directory " + DTFWHome); - throw new UnsatisfiedLinkError("Both files dbghelp.dll and " + - "dbgeng.dll must exist in " + - "directory " + DTFWHome); + // First place to search is co-located with sawindbg.dll in + // $JAVA_HOME/jre/bin (java.home property is set to $JAVA_HOME/jre): + searchList.add(System.getProperty("java.home") + File.separator + "bin"); + sawindbgPath = (String) searchList.get(0) + File.separator + + "sawindbg.dll"; + + // second place to search is specified by an environment variable: + String DTFWHome = System.getenv("DEBUGGINGTOOLSFORWINDOWS"); + if (DTFWHome != null) { + searchList.add(DTFWHome); } - } - if (DTFWHome == null) { - // The files better be in the system dir. - String sysDir = System.getenv("SYSTEMROOT") + - File.separator + "system32"; - File feng = new File(sysDir + File.separator + "dbgeng.dll"); - if (!feng.exists()) { - throw new UnsatisfiedLinkError("File dbgeng.dll does not exist in " + - sysDir + ". Please search microsoft.com " + - "for Debugging Tools For Windows, and " + - "either download it to the default " + - "location, or download it to a custom " + - "location and set environment variable " + - " DEBUGGINGTOOLSFORWINDOWS " + - "to the pathname of that location."); - } + // The third place to search is the install directory for the + // "Debugging Tools For Windows" package; so far there are three + // name variations that we know of: + String sysRoot = System.getenv("SYSTEMROOT"); + DTFWHome = sysRoot + File.separator + ".." + File.separator + + "Program Files" + File.separator + "Debugging Tools For Windows"; + searchList.add(DTFWHome); + searchList.add(DTFWHome + " (x86)"); + searchList.add(DTFWHome + " (x64)"); + + // The last place to search is the system directory: + searchList.add(sysRoot + File.separator + "system32"); } + for (int i = 0; i < searchList.size(); i++) { + File dir = new File((String) searchList.get(i)); + if (!dir.exists()) { + if (loadLibraryDEBUG) { + System.err.println("DEBUG: '" + searchList.get(i) + + "': directory does not exist."); + } + // this search directory doesn't exist so skip it + continue; + } + + dbgengPath = (String) searchList.get(i) + File.separator + "dbgeng.dll"; + dbghelpPath = (String) searchList.get(i) + File.separator + "dbghelp.dll"; + + File feng = new File(dbgengPath); + File fhelp = new File(dbghelpPath); + if (feng.exists() && fhelp.exists()) { + // both files exist so we have a match + break; + } + + // At least one of the files does not exist; no warning if both + // don't exist. If just one doesn't exist then we don't check + // loadLibraryDEBUG because we have a mis-configured system. + if (feng.exists()) { + System.err.println("WARNING: found '" + dbgengPath + + "' but did not find '" + dbghelpPath + "'; ignoring '" + + dbgengPath + "'."); + } else if (fhelp.exists()) { + System.err.println("WARNING: found '" + dbghelpPath + + "' but did not find '" + dbgengPath + "'; ignoring '" + + dbghelpPath + "'."); + } else if (loadLibraryDEBUG) { + System.err.println("DEBUG: searched '" + searchList.get(i) + + "': dbgeng.dll and dbghelp.dll were not found."); + } + dbgengPath = null; + dbghelpPath = null; + } + + if (dbgengPath == null || dbghelpPath == null) { + // at least one of the files wasn't found anywhere we searched + String mesg = null; + + if (dbgengPath == null && dbghelpPath == null) { + mesg = "dbgeng.dll and dbghelp.dll cannot be found. "; + } else if (dbgengPath == null) { + mesg = "dbgeng.dll cannot be found (dbghelp.dll was found). "; + } else { + mesg = "dbghelp.dll cannot be found (dbgeng.dll was found). "; + } + throw new UnsatisfiedLinkError(mesg + + "Please search microsoft.com for 'Debugging Tools For Windows', " + + "and either download it to the default location, or download it " + + "to a custom location and set environment variable " + + "'DEBUGGINGTOOLSFORWINDOWS' to the pathname of that location."); + } + + // NOTE: The order of loads is important! If we load dbgeng.dll + // first, then the dependency - dbghelp.dll - will be loaded + // from usual DLL search thereby defeating the purpose! + if (loadLibraryDEBUG) { + System.err.println("DEBUG: loading '" + dbghelpPath + "'."); + } + System.load(dbghelpPath); + if (loadLibraryDEBUG) { + System.err.println("DEBUG: loading '" + dbgengPath + "'."); + } + System.load(dbgengPath); + // Now, load sawindbg.dll - System.loadLibrary("sawindbg"); + if (loadLibraryDEBUG) { + System.err.println("DEBUG: loading '" + sawindbgPath + "'."); + } + System.load(sawindbgPath); + // where do I find '.exe', '.dll' files? imagePath = System.getProperty("sun.jvm.hotspot.debugger.windbg.imagePath"); if (imagePath == null) { diff -r 55f868e91c3b -r 0e52ef6e94d3 agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java --- a/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Thu Jan 06 16:03:20 2011 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Fri Jan 07 03:58:11 2011 -0800 @@ -30,6 +30,7 @@ import sun.jvm.hotspot.asm.sparc.*; import sun.jvm.hotspot.asm.x86.*; import sun.jvm.hotspot.asm.ia64.*; +import sun.jvm.hotspot.asm.amd64.*; import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.compiler.*; import sun.jvm.hotspot.debugger.*; @@ -198,6 +199,8 @@ cpuHelper = new SPARCHelper(); } else if (cpu.equals("x86")) { cpuHelper = new X86Helper(); + } else if (cpu.equals("amd64")) { + cpuHelper = new AMD64Helper(); } else if (cpu.equals("ia64")) { cpuHelper = new IA64Helper(); } else { diff -r 55f868e91c3b -r 0e52ef6e94d3 make/hotspot_version --- a/make/hotspot_version Thu Jan 06 16:03:20 2011 -0800 +++ b/make/hotspot_version Fri Jan 07 03:58:11 2011 -0800 @@ -35,7 +35,7 @@ HS_MAJOR_VER=20 HS_MINOR_VER=0 -HS_BUILD_NUMBER=04 +HS_BUILD_NUMBER=05 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 diff -r 55f868e91c3b -r 0e52ef6e94d3 make/linux/makefiles/build_vm_def.sh --- a/make/linux/makefiles/build_vm_def.sh Thu Jan 06 16:03:20 2011 -0800 +++ b/make/linux/makefiles/build_vm_def.sh Fri Jan 07 03:58:11 2011 -0800 @@ -1,7 +1,7 @@ #!/bin/sh # If we're cross compiling use that path for nm -if [ "$ALT_COMPILER_PATH" != "" ]; then +if [ "$CROSS_COMPILE_ARCH" != "" ]; then NM=$ALT_COMPILER_PATH/nm else NM=nm diff -r 55f868e91c3b -r 0e52ef6e94d3 make/linux/makefiles/buildtree.make --- a/make/linux/makefiles/buildtree.make Thu Jan 06 16:03:20 2011 -0800 +++ b/make/linux/makefiles/buildtree.make Fri Jan 07 03:58:11 2011 -0800 @@ -124,7 +124,7 @@ BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make \ - env.sh env.csh .dbxrc test_gamma + env.sh env.csh jdkpath.sh .dbxrc test_gamma BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \ ARCH=$(ARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT) @@ -318,6 +318,13 @@ sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=/setenv \1 /p' $?; \ ) > $@ +jdkpath.sh: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo "JDK=${JAVA_HOME}"; \ + ) > $@ + .dbxrc: $(BUILDTREE_MAKE) @echo Creating $@ ... $(QUIETLY) ( \ diff -r 55f868e91c3b -r 0e52ef6e94d3 make/linux/makefiles/gcc.make --- a/make/linux/makefiles/gcc.make Thu Jan 06 16:03:20 2011 -0800 +++ b/make/linux/makefiles/gcc.make Fri Jan 07 03:58:11 2011 -0800 @@ -25,7 +25,9 @@ #------------------------------------------------------------------------ # CC, CPP & AS -ifdef ALT_COMPILER_PATH +# When cross-compiling the ALT_COMPILER_PATH points +# to the cross-compilation toolset +ifdef CROSS_COMPILE_ARCH CPP = $(ALT_COMPILER_PATH)/g++ CC = $(ALT_COMPILER_PATH)/gcc else diff -r 55f868e91c3b -r 0e52ef6e94d3 make/linux/makefiles/vm.make --- a/make/linux/makefiles/vm.make Thu Jan 06 16:03:20 2011 -0800 +++ b/make/linux/makefiles/vm.make Fri Jan 07 03:58:11 2011 -0800 @@ -168,7 +168,9 @@ # Locate all source files in the given directory, excluding files in Src_Files_EXCLUDE. define findsrc - $(notdir $(shell find $(1) \( -name \*.c -o -name \*.cpp -o -name \*.s \) -a \! \( -name DUMMY $(addprefix -o -name ,$(Src_Files_EXCLUDE)) \) )) + $(notdir $(shell find $(1)/. ! -name . -prune \ + -a \( -name \*.c -o -name \*.cpp -o -name \*.s \) \ + -a ! \( -name DUMMY $(addprefix -o -name ,$(Src_Files_EXCLUDE)) \))) endef Src_Files := $(foreach e,$(Src_Dirs),$(call findsrc,$(e))) diff -r 55f868e91c3b -r 0e52ef6e94d3 make/solaris/makefiles/buildtree.make --- a/make/solaris/makefiles/buildtree.make Thu Jan 06 16:03:20 2011 -0800 +++ b/make/solaris/makefiles/buildtree.make Fri Jan 07 03:58:11 2011 -0800 @@ -117,7 +117,7 @@ BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make \ - env.ksh env.csh .dbxrc test_gamma + env.ksh env.csh jdkpath.sh .dbxrc test_gamma BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \ ARCH=$(ARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT) @@ -314,6 +314,13 @@ sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=/setenv \1 /p' $?; \ ) > $@ +jdkpath.sh: $(BUILDTREE_MAKE) + @echo Creating $@ ... + $(QUIETLY) ( \ + $(BUILDTREE_COMMENT); \ + echo "JDK=${JAVA_HOME}"; \ + ) > $@ + .dbxrc: $(BUILDTREE_MAKE) @echo Creating $@ ... $(QUIETLY) ( \ diff -r 55f868e91c3b -r 0e52ef6e94d3 make/solaris/makefiles/vm.make --- a/make/solaris/makefiles/vm.make Thu Jan 06 16:03:20 2011 -0800 +++ b/make/solaris/makefiles/vm.make Fri Jan 07 03:58:11 2011 -0800 @@ -106,17 +106,17 @@ # Not sure what the 'designed for' comment is referring too above. # The order may not be too significant anymore, but I have placed this # older libm before libCrun, just to make sure it's found and used first. -LIBS += -lsocket -lsched -ldl $(LIBM) -lCrun -lthread -ldoor -lc +LIBS += -lsocket -lsched -ldl $(LIBM) -lCrun -lthread -ldoor -lc -ldemangle else ifeq ($(COMPILER_REV_NUMERIC), 502) # SC6.1 has it's own libm.so: specifying anything else provokes a name conflict. -LIBS += -ldl -lthread -lsocket -lm -lsched -ldoor +LIBS += -ldl -lthread -lsocket -lm -lsched -ldoor -ldemangle else -LIBS += -ldl -lthread -lsocket $(LIBM) -lsched -ldoor +LIBS += -ldl -lthread -lsocket $(LIBM) -lsched -ldoor -ldemangle endif # 502 endif # 505 else -LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc +LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle endif # sparcWorks ifeq ("${Platform_arch}", "sparc") @@ -188,7 +188,9 @@ # Locate all source files in the given directory, excluding files in Src_Files_EXCLUDE. define findsrc - $(notdir $(shell find $(1) \( -name \*.c -o -name \*.cpp -o -name \*.s \) -a \! \( -name DUMMY $(addprefix -o -name ,$(Src_Files_EXCLUDE)) \) )) + $(notdir $(shell find $(1)/. ! -name . -prune \ + -a \( -name \*.c -o -name \*.cpp -o -name \*.s \) \ + -a ! \( -name DUMMY $(addprefix -o -name ,$(Src_Files_EXCLUDE)) \))) endef Src_Files := $(foreach e,$(Src_Dirs),$(call findsrc,$(e))) diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/build_vm_def.sh --- a/make/windows/build_vm_def.sh Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/build_vm_def.sh Fri Jan 07 03:58:11 2011 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2010, 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 @@ -45,6 +45,9 @@ echo "EXPORTS" > vm1.def AWK="$MKS_HOME/awk.exe" +if [ ! -e $AWK ]; then + AWK="$MKS_HOME/gawk.exe" +fi GREP="$MKS_HOME/grep.exe" SORT="$MKS_HOME/sort.exe" UNIQ="$MKS_HOME/uniq.exe" @@ -57,7 +60,7 @@ LINK_VER="$1" fi -if [ "x$LINK_VER" != "x800" -a "x$LINK_VER" != "x900" ]; then +if [ "x$LINK_VER" != "x800" -a "x$LINK_VER" != "x900" -a "x$LINK_VER" != "x1000" ]; then $DUMPBIN /symbols *.obj | "$GREP" "??_7.*@@6B@" | "$GREP" -v "type_info" | "$AWK" '{print $7}' | "$SORT" | "$UNIQ" > vm2.def else # Can't use pipes when calling cl.exe or link.exe from IDE. Using transit file vm3.def diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/create.bat --- a/make/windows/create.bat Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/create.bat Fri Jan 07 03:58:11 2011 -0800 @@ -36,6 +36,20 @@ REM Note: Running this batch file from the Windows command shell requires REM that "grep" be accessible on the PATH. An MKS install does this. REM + +cl 2>NUL >NUL +if %errorlevel% == 0 goto nexttest +echo Make sure cl.exe is in your PATH before running this script. +goto end + +:nexttest +grep -V 2>NUL >NUL +if %errorlevel% == 0 goto testit +echo Make sure grep.exe is in your PATH before running this script. Either cygwin or MKS should work. +goto end + + +:testit cl 2>&1 | grep "IA-64" >NUL if %errorlevel% == 0 goto isia64 cl 2>&1 | grep "AMD64" >NUL @@ -44,37 +58,40 @@ set BUILDARCH=i486 set Platform_arch=x86 set Platform_arch_model=x86_32 -goto end +goto done :amd64 set ARCH=x86 set BUILDARCH=amd64 set Platform_arch=x86 set Platform_arch_model=x86_64 -goto end +goto done :isia64 set ARCH=ia64 set BUILDARCH=ia64 set Platform_arch=ia64 set Platform_arch_model=ia64 -:end +:done setlocal if "%1" == "" goto usage -if not "%4" == "" goto usage +if not "%2" == "" goto usage -set HotSpotWorkSpace=%1 -set HotSpotBuildSpace=%2 -set HotSpotJDKDist=%3 +REM Set HotSpotWorkSpace to the directy two steps above this script +for %%i in ("%~dp0..") do ( set HotSpotWorkSpace=%%~dpi) +set HotSpotBuildRoot=%HotSpotWorkSpace%build +set HotSpotBuildSpace=%HotSpotBuildRoot%\vs +set HotSpotJDKDist=%1 + REM figure out MSC version for /F %%i in ('sh %HotSpotWorkSpace%/make/windows/get_msc_ver.sh') do set %%i echo ************************************************************** -set ProjectFile=vm.vcproj +set ProjectFile=jvm.vcproj if "%MSC_VER%" == "1200" ( -set ProjectFile=vm.dsp +set ProjectFile=jvm.dsp echo Will generate VC6 project {unsupported} ) else ( if "%MSC_VER%" == "1400" ( @@ -83,10 +100,16 @@ if "%MSC_VER%" == "1500" ( echo Will generate VC9 {Visual Studio 2008} ) else ( +if "%MSC_VER%" == "1600" ( +echo Detected Visual Studio 2010, but +echo will generate VC9 {Visual Studio 2008} +echo Use conversion wizard in VS 2010. +) else ( echo Will generate VC7 project {Visual Studio 2003 .NET} ) ) ) +) echo %ProjectFile% echo ************************************************************** @@ -118,6 +141,8 @@ :test3 if not "%HOTSPOTMKSHOME%" == "" goto makedir +if exist c:\cygwin\bin set HOTSPOTMKSHOME=c:\cygwin\bin +if not "%HOTSPOTMKSHOME%" == "" goto makedir echo Warning: please set variable HOTSPOTMKSHOME to place where echo your MKS/Cygwin installation is echo. @@ -133,21 +158,24 @@ REM This is now safe to do. :copyfiles for /D %%i in (compiler1, compiler2, tiered, core, kernel) do ( -if NOT EXIST %HotSpotBuildSpace%\%%i mkdir %HotSpotBuildSpace%\%%i -copy %HotSpotWorkSpace%\make\windows\projectfiles\%%i\* %HotSpotBuildSpace%\%%i\ > NUL +if NOT EXIST %HotSpotBuildSpace%\%%i\generated mkdir %HotSpotBuildSpace%\%%i\generated +copy %HotSpotWorkSpace%\make\windows\projectfiles\%%i\* %HotSpotBuildSpace%\%%i\generated > NUL ) REM force regneration of ProjectFile if exist %HotSpotBuildSpace%\%ProjectFile% del %HotSpotBuildSpace%\%ProjectFile% for /D %%i in (compiler1, compiler2, tiered, core, kernel) do ( - -echo # Generated file! > %HotSpotBuildSpace%\%%i\local.make +echo -- %%i -- +echo # Generated file! > %HotSpotBuildSpace%\%%i\local.make echo # Changing a variable below and then deleting %ProjectFile% will cause >> %HotSpotBuildSpace%\%%i\local.make echo # %ProjectFile% to be regenerated with the new values. Changing the >> %HotSpotBuildSpace%\%%i\local.make -echo # version requires rerunning create.bat. >> %HotSpotBuildSpace%\%%i\local.make +echo # version requires rerunning create.bat. >> %HotSpotBuildSpace%\%%i\local.make echo. >> %HotSpotBuildSpace%\%%i\local.make +echo Variant=%%i >> %HotSpotBuildSpace%\%%i\local.make +echo WorkSpace=%HotSpotWorkSpace% >> %HotSpotBuildSpace%\%%i\local.make echo HOTSPOTWORKSPACE=%HotSpotWorkSpace% >> %HotSpotBuildSpace%\%%i\local.make +echo HOTSPOTBUILDROOT=%HotSpotBuildRoot% >> %HotSpotBuildSpace%\%%i\local.make echo HOTSPOTBUILDSPACE=%HotSpotBuildSpace% >> %HotSpotBuildSpace%\%%i\local.make echo HOTSPOTJDKDIST=%HotSpotJDKDist% >> %HotSpotBuildSpace%\%%i\local.make echo ARCH=%ARCH% >> %HotSpotBuildSpace%\%%i\local.make @@ -155,42 +183,35 @@ echo Platform_arch=%Platform_arch% >> %HotSpotBuildSpace%\%%i\local.make echo Platform_arch_model=%Platform_arch_model% >> %HotSpotBuildSpace%\%%i\local.make -pushd %HotSpotBuildSpace%\%%i +for /D %%j in (debug, fastdebug, product) do ( +if NOT EXIST %HotSpotBuildSpace%\%%i\%%j mkdir %HotSpotBuildSpace%\%%i\%%j +) + +pushd %HotSpotBuildSpace%\%%i\generated nmake /nologo popd ) -pushd %HotSpotBuildSpace% +pushd %HotSpotBuildRoot% -echo # Generated file! > local.make -echo # Changing a variable below and then deleting %ProjectFile% will cause >> local.make -echo # %ProjectFile% to be regenerated with the new values. Changing the >> local.make -echo # version requires rerunning create.bat. >> local.make -echo. >> local.make -echo HOTSPOTWORKSPACE=%HotSpotWorkSpace% >> local.make -echo HOTSPOTBUILDSPACE=%HotSpotBuildSpace% >> local.make -echo HOTSPOTJDKDIST=%HotSpotJDKDist% >> local.make -echo ARCH=%ARCH% >> local.make -echo BUILDARCH=%BUILDARCH% >> local.make -echo Platform_arch=%Platform_arch% >> local.make -echo Platform_arch_model=%Platform_arch_model% >> local.make - -nmake /nologo /F %HotSpotWorkSpace%/make/windows/projectfiles/common/Makefile %HotSpotBuildSpace%/%ProjectFile% +REM It doesn't matter which variant we use here, "compiler1" is as good as any of the others - we need the common variables +nmake /nologo /F %HotSpotWorkSpace%/make/windows/projectfiles/common/Makefile LOCAL_MAKE=%HotSpotBuildSpace%\compiler1\local.make %HotSpotBuildRoot%/%ProjectFile% popd goto end :usage -echo Usage: create HotSpotWorkSpace HotSpotBuildSpace HotSpotJDKDist +echo Usage: create HotSpotJDKDist echo. -echo This is the interactive build setup script (as opposed to the batch -echo build execution script). It creates HotSpotBuildSpace if necessary, -echo copies the appropriate files out of HotSpotWorkSpace into it, and +echo This is the VS build setup script (as opposed to the batch +echo build execution script). It creates a build directory if necessary, +echo copies the appropriate files out of the workspace into it, and echo builds and runs ProjectCreator in it. This has the side-effect of creating echo the %ProjectFile% file in the build space, which is then used in Visual C++. -echo The HotSpotJDKDist defines place where JVM binaries should be placed. +echo. +echo The HotSpotJDKDist defines the JDK that should be used when running the JVM. echo Environment variable FORCE_MSC_VER allows to override MSVC version autodetection. echo. echo NOTE that it is now NOT safe to modify any of the files in the build diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/create_obj_files.sh --- a/make/windows/create_obj_files.sh Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/create_obj_files.sh Fri Jan 07 03:58:11 2011 -0800 @@ -107,8 +107,12 @@ "x86_64") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} *x86_32*" ;; esac +# Locate all source files in the given directory, excluding files in Src_Files_EXCLUDE. function findsrc { - $FIND ${1} \( -name \*.c -o -name \*.cpp -o -name \*.s \) -a \! \( -name ${Src_Files_EXCLUDE// / -o -name } \) | sed 's/.*\/\(.*\)/\1/'; + $FIND ${1}/. ! -name . -prune \ + -a \( -name \*.c -o -name \*.cpp -o -name \*.s \) \ + -a \! \( -name ${Src_Files_EXCLUDE// / -o -name } \) \ + | sed 's/.*\/\(.*\)/\1/'; } Src_Files= diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/makefiles/adlc.make --- a/make/windows/makefiles/adlc.make Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/makefiles/adlc.make Fri Jan 07 03:58:11 2011 -0800 @@ -22,7 +22,6 @@ # # -!include $(WorkSpace)/make/windows/makefiles/compile.make # Rules for building adlc.exe @@ -46,15 +45,7 @@ ADLCFLAGS=-q -T -U_LP64 !endif -CPP_FLAGS=$(CPP_FLAGS) \ - /D TARGET_OS_FAMILY_windows \ - /D TARGET_ARCH_$(Platform_arch) \ - /D TARGET_ARCH_MODEL_$(Platform_arch_model) \ - /D TARGET_OS_ARCH_windows_$(Platform_arch) \ - /D TARGET_OS_ARCH_MODEL_windows_$(Platform_arch_model) \ - /D TARGET_COMPILER_visCPP - -CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE +ADLC_CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE CPP_INCLUDE_DIRS=\ /I "..\generated" \ @@ -92,10 +83,10 @@ $(AdlcOutDir)\dfa_$(Platform_arch_model).cpp {$(WorkSpace)\src\share\vm\adlc}.cpp.obj:: - $(CPP) $(CPP_FLAGS) $(EXH_FLAGS) $(CPP_INCLUDE_DIRS) /c $< + $(CPP) $(ADLC_CPP_FLAGS) $(EXH_FLAGS) $(CPP_INCLUDE_DIRS) /c $< {$(WorkSpace)\src\share\vm\opto}.cpp.obj:: - $(CPP) $(CPP_FLAGS) $(EXH_FLAGS) $(CPP_INCLUDE_DIRS) /c $< + $(CPP) $(ADLC_CPP_FLAGS) $(EXH_FLAGS) $(CPP_INCLUDE_DIRS) /c $< adlc.exe: main.obj adlparse.obj archDesc.obj arena.obj dfa.obj dict2.obj filebuff.obj \ forms.obj formsopt.obj formssel.obj opcodes.obj output_c.obj output_h.obj diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/makefiles/compile.make --- a/make/windows/makefiles/compile.make Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/makefiles/compile.make Fri Jan 07 03:58:11 2011 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2010, 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 @@ -80,6 +80,20 @@ CPP=ARCH_ERROR !endif +CPP_FLAGS=$(CPP_FLAGS) /D "WIN32" /D "_WINDOWS" + +# Must specify this for sharedRuntimeTrig.cpp +CPP_FLAGS=$(CPP_FLAGS) /D "VM_LITTLE_ENDIAN" + +# Used for platform dispatching +CPP_FLAGS=$(CPP_FLAGS) /D TARGET_OS_FAMILY_windows +CPP_FLAGS=$(CPP_FLAGS) /D TARGET_ARCH_$(Platform_arch) +CPP_FLAGS=$(CPP_FLAGS) /D TARGET_ARCH_MODEL_$(Platform_arch_model) +CPP_FLAGS=$(CPP_FLAGS) /D TARGET_OS_ARCH_windows_$(Platform_arch) +CPP_FLAGS=$(CPP_FLAGS) /D TARGET_OS_ARCH_MODEL_windows_$(Platform_arch_model) +CPP_FLAGS=$(CPP_FLAGS) /D TARGET_COMPILER_visCPP + + # MSC_VER is a 4 digit number that tells us what compiler is being used # and is generated when the local.make file is created by build.make # via the script get_msc_ver.sh @@ -138,7 +152,7 @@ !endif # Always add the _STATIC_CPPLIB flag -STATIC_CPPLIB_OPTION = /D _STATIC_CPPLIB +STATIC_CPPLIB_OPTION = /D _STATIC_CPPLIB /D _DISABLE_DEPRECATE_STATIC_CPPLIB MS_RUNTIME_OPTION = $(MS_RUNTIME_OPTION) $(STATIC_CPPLIB_OPTION) CPP_FLAGS=$(CPP_FLAGS) $(MS_RUNTIME_OPTION) diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/makefiles/debug.make --- a/make/windows/makefiles/debug.make Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/makefiles/debug.make Fri Jan 07 03:58:11 2011 -0800 @@ -26,7 +26,6 @@ HS_FNAME=$(HS_INTERNAL_NAME).dll AOUT=$(HS_FNAME) SAWINDBG=sawindbg.dll -LAUNCHER_NAME=hotspot.exe GENERATED=../generated # Allow the user to turn off precompiled headers from the command line. @@ -34,7 +33,7 @@ BUILD_PCH_FILE=_build_pch_file.obj !endif -default:: $(BUILD_PCH_FILE) $(AOUT) $(LAUNCHER_NAME) checkAndBuildSA +default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA !include ../local.make !include compile.make @@ -49,8 +48,10 @@ # Force resources to be rebuilt every time $(Res_Files): FORCE -$(AOUT): $(Res_Files) $(Obj_Files) +vm.def: $(Obj_Files) sh $(WorkSpace)/make/windows/build_vm_def.sh + +$(AOUT): $(Res_Files) $(Obj_Files) vm.def $(LINK) @<< $(LINK_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) << diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/makefiles/fastdebug.make --- a/make/windows/makefiles/fastdebug.make Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/makefiles/fastdebug.make Fri Jan 07 03:58:11 2011 -0800 @@ -26,7 +26,6 @@ HS_FNAME=$(HS_INTERNAL_NAME).dll AOUT=$(HS_FNAME) SAWINDBG=sawindbg.dll -LAUNCHER_NAME=hotspot.exe GENERATED=../generated # Allow the user to turn off precompiled headers from the command line. @@ -34,7 +33,7 @@ BUILD_PCH_FILE=_build_pch_file.obj !endif -default:: $(BUILD_PCH_FILE) $(AOUT) $(LAUNCHER_NAME) checkAndBuildSA +default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA !include ../local.make !include compile.make @@ -49,8 +48,10 @@ # Force resources to be rebuilt every time $(Res_Files): FORCE -$(AOUT): $(Res_Files) $(Obj_Files) +vm.def: $(Obj_Files) sh $(WorkSpace)/make/windows/build_vm_def.sh + +$(AOUT): $(Res_Files) $(Obj_Files) vm.def $(LINK) @<< $(LINK_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) << diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/makefiles/generated.make --- a/make/windows/makefiles/generated.make Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/makefiles/generated.make Fri Jan 07 03:58:11 2011 -0800 @@ -51,6 +51,7 @@ !if ("$(Variant)" == "compiler2") || ("$(Variant)" == "tiered") +!include $(WorkSpace)/make/windows/makefiles/compile.make !include $(WorkSpace)/make/windows/makefiles/adlc.make !endif diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/makefiles/launcher.make --- a/make/windows/makefiles/launcher.make Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/makefiles/launcher.make Fri Jan 07 03:58:11 2011 -0800 @@ -22,7 +22,8 @@ # # -LAUNCHER_FLAGS=$(ARCHFLAG) \ + +LAUNCHER_FLAGS=$(CPP_FLAGS) $(ARCHFLAG) \ /D FULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \ /D JDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \ /D JDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \ @@ -32,9 +33,11 @@ /D _CRT_SECURE_NO_DEPRECATE \ /D LINK_INTO_LIBJVM \ /I $(WorkSpace)\src\os\windows\launcher \ - /I $(WorkSpace)\src\share\tools\launcher - -CPP_FLAGS=$(CPP_FLAGS) $(LAUNCHER_FLAGS) + /I $(WorkSpace)\src\share\tools\launcher \ + /I $(WorkSpace)\src\share\vm\prims \ + /I $(WorkSpace)\src\share\vm \ + /I $(WorkSpace)\src\cpu\$(Platform_arch)\vm \ + /I $(WorkSpace)\src\os\windows\vm LINK_FLAGS=/manifest $(HS_INTERNAL_NAME).lib kernel32.lib user32.lib /nologo /machine:$(MACHINE) /map /debug /subsystem:console @@ -46,22 +49,23 @@ LINK_FLAGS = $(LINK_FLAGS) $(BUFFEROVERFLOWLIB) !endif -LAUNCHERDIR = $(GAMMADIR)/src/os/windows/launcher -LAUNCHERDIR_SHARE = $(GAMMADIR)/src/share/tools/launcher +LAUNCHERDIR = $(WorkSpace)/src/os/windows/launcher +LAUNCHERDIR_SHARE = $(WorkSpace)/src/share/tools/launcher OUTDIR = launcher {$(LAUNCHERDIR)}.c{$(OUTDIR)}.obj: - -mkdir $(OUTDIR) - $(CPP) $(CPP_FLAGS) /c /Fo$@ $< + -mkdir $(OUTDIR) 2>NUL >NUL + $(CPP) $(LAUNCHER_FLAGS) /c /Fo$@ $< {$(LAUNCHERDIR_SHARE)}.c{$(OUTDIR)}.obj: - -mkdir $(OUTDIR) - $(CPP) $(CPP_FLAGS) /c /Fo$@ $< + -mkdir $(OUTDIR) 2>NUL >NUL + $(CPP) $(LAUNCHER_FLAGS) /c /Fo$@ $< $(OUTDIR)\*.obj: $(LAUNCHERDIR)\*.c $(LAUNCHERDIR)\*.h $(LAUNCHERDIR_SHARE)\*.c $(LAUNCHERDIR_SHARE)\*.h -$(LAUNCHER_NAME): $(OUTDIR)\java.obj $(OUTDIR)\java_md.obj $(OUTDIR)\jli_util.obj - $(LINK) $(LINK_FLAGS) /out:$@ $** +launcher: $(OUTDIR)\java.obj $(OUTDIR)\java_md.obj $(OUTDIR)\jli_util.obj + echo $(JAVA_HOME) > jdkpath.txt + $(LINK) $(LINK_FLAGS) /out:hotspot.exe $** diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/makefiles/product.make --- a/make/windows/makefiles/product.make Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/makefiles/product.make Fri Jan 07 03:58:11 2011 -0800 @@ -25,7 +25,6 @@ HS_INTERNAL_NAME=jvm HS_FNAME=$(HS_INTERNAL_NAME).dll AOUT=$(HS_FNAME) -LAUNCHER_NAME=hotspot.exe GENERATED=../generated # Allow the user to turn off precompiled headers from the command line. @@ -33,7 +32,7 @@ BUILD_PCH_FILE=_build_pch_file.obj !endif -default:: $(BUILD_PCH_FILE) $(AOUT) $(LAUNCHER_NAME) checkAndBuildSA +default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA !include ../local.make !include compile.make @@ -59,8 +58,10 @@ $(LINK_FLAGS) /out:$@ /implib:$*.lib $(Obj_Files) $(Res_Files) << !else -$(AOUT): $(Res_Files) $(Obj_Files) +vm.def: $(Obj_Files) sh $(WorkSpace)/make/windows/build_vm_def.sh + +$(AOUT): $(Res_Files) $(Obj_Files) vm.def $(LINK) @<< $(LINK_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) << diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/makefiles/projectcreator.make --- a/make/windows/makefiles/projectcreator.make Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/makefiles/projectcreator.make Fri Jan 07 03:58:11 2011 -0800 @@ -84,11 +84,12 @@ -buildBase $(HOTSPOTBUILDSPACE)\%f\%b \ -startAt src \ -compiler $(VcVersion) \ - -projectFileName $(HOTSPOTBUILDSPACE)\$(ProjectFile) \ + -projectFileName $(HOTSPOTBUILDROOT)\$(ProjectFile) \ -jdkTargetRoot $(HOTSPOTJDKDIST) \ -define ALIGN_STACK_FRAMES \ -define VM_LITTLE_ENDIAN \ -prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(LINK_VER)" \ + -postbuild "" "Building hotspot.exe..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) nmake -f $(HOTSPOTWORKSPACE)\make\windows\projectfiles\common\Makefile LOCAL_MAKE=$(HOTSPOTBUILDSPACE)\%f\local.make JAVA_HOME=$(HOTSPOTJDKDIST) launcher" \ -ignoreFile jsig.c \ -ignoreFile jvmtiEnvRecommended.cpp \ -ignoreFile jvmtiEnvStub.cpp \ diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/makefiles/rules.make --- a/make/windows/makefiles/rules.make Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/makefiles/rules.make Fri Jan 07 03:58:11 2011 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2010, 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 @@ -48,7 +48,7 @@ JAVAC_FLAGS=-g -encoding ascii BOOTSTRAP_JAVAC_FLAGS=$(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION) -ProjectFile=vm.vcproj +ProjectFile=jvm.vcproj !if "$(MSC_VER)" == "1200" @@ -63,6 +63,11 @@ VcVersion=VC9 +!elseif "$(MSC_VER)" == "1600" + +# for compatibility - we don't yet have a ProjectCreator for VC10 +VcVersion=VC9 + !else VcVersion=VC7 diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/makefiles/vm.make --- a/make/windows/makefiles/vm.make Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/makefiles/vm.make Fri Jan 07 03:58:11 2011 -0800 @@ -71,22 +71,11 @@ CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_BUILD_USER=\"$(BuildUser)\"" CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_VM_DISTRO=\"$(HOTSPOT_VM_DISTRO)\"" -CPP_FLAGS=$(CPP_FLAGS) /D "WIN32" /D "_WINDOWS" $(CPP_INCLUDE_DIRS) - -# Must specify this for sharedRuntimeTrig.cpp -CPP_FLAGS=$(CPP_FLAGS) /D "VM_LITTLE_ENDIAN" +CPP_FLAGS=$(CPP_FLAGS) $(CPP_INCLUDE_DIRS) # Define that so jni.h is on correct side CPP_FLAGS=$(CPP_FLAGS) /D "_JNI_IMPLEMENTATION_" -# Used for platform dispatching -CPP_FLAGS=$(CPP_FLAGS) /D TARGET_OS_FAMILY_windows -CPP_FLAGS=$(CPP_FLAGS) /D TARGET_ARCH_$(Platform_arch) -CPP_FLAGS=$(CPP_FLAGS) /D TARGET_ARCH_MODEL_$(Platform_arch_model) -CPP_FLAGS=$(CPP_FLAGS) /D TARGET_OS_ARCH_windows_$(Platform_arch) -CPP_FLAGS=$(CPP_FLAGS) /D TARGET_OS_ARCH_MODEL_windows_$(Platform_arch_model) -CPP_FLAGS=$(CPP_FLAGS) /D TARGET_COMPILER_visCPP - !if "$(BUILDARCH)" == "ia64" STACK_SIZE="/STACK:1048576,262144" !else @@ -104,6 +93,8 @@ !endif !endif +# If you modify exports below please do the corresponding changes in +# src/share/tools/ProjectCreator/WinGammaPlatformVC7.java LINK_FLAGS=$(LINK_FLAGS) $(STACK_SIZE) /subsystem:windows /dll /base:0x8000000 \ /export:JNI_GetDefaultJavaVMInitArgs \ /export:JNI_CreateJavaVM \ diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/projectfiles/common/Makefile --- a/make/windows/projectfiles/common/Makefile Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/projectfiles/common/Makefile Fri Jan 07 03:58:11 2011 -0800 @@ -22,7 +22,10 @@ # # -!include local.make +!ifdef LOCAL_MAKE +!include $(LOCAL_MAKE) +!endif + WorkSpace=$(HOTSPOTWORKSPACE) @@ -34,11 +37,18 @@ !else !ifdef JAVA_HOME BootStrapDir=$(JAVA_HOME) +!else +!ifdef HOTSPOTJDKDIST +BootStrapDir=$(HOTSPOTJDKDIST) +!endif !endif !endif !endif + + !include $(HOTSPOTWORKSPACE)/make/windows/makefiles/projectcreator.make +!include $(WorkSpace)/make/windows/makefiles/compile.make # Pick up rules for building JVMTI (JSR-163) JvmtiOutDir=$(HOTSPOTBUILDSPACE)\$(Variant)\generated\jvmtifiles @@ -56,6 +66,9 @@ !include $(HOTSPOTWORKSPACE)/make/windows/makefiles/adlc.make !endif +HS_INTERNAL_NAME=jvm +!include $(HOTSPOTWORKSPACE)/make/windows/makefiles/launcher.make + default:: $(AdditionalTargets) $(JvmtiGeneratedFiles) !include $(HOTSPOTWORKSPACE)/make/hotspot_version @@ -97,7 +110,7 @@ -define JRE_RELEASE_VERSION=\\\"$(JRE_RELEASE_VERSION)\\\" \ -define HOTSPOT_VM_DISTRO=\\\"$(HOTSPOT_VM_DISTRO)\\\" -$(HOTSPOTBUILDSPACE)/$(ProjectFile): local.make $(HOTSPOTBUILDSPACE)/classes/ProjectCreator.class +$(HOTSPOTBUILDROOT)/$(ProjectFile): $(HOTSPOTBUILDSPACE)/classes/ProjectCreator.class @$(RUN_JAVA) -Djava.class.path=$(HOTSPOTBUILDSPACE)/classes ProjectCreator WinGammaPlatform$(VcVersion) $(ProjectCreatorIDEOptions) clean: diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/projectfiles/compiler1/Makefile --- a/make/windows/projectfiles/compiler1/Makefile Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/projectfiles/compiler1/Makefile Fri Jan 07 03:58:11 2011 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2010, 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 @@ -22,7 +22,6 @@ # # -Variant=compiler1 -!include local.make +!include ../local.make !include $(HOTSPOTWORKSPACE)/make/windows/projectfiles/common/Makefile diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/projectfiles/compiler1/vm.def --- a/make/windows/projectfiles/compiler1/vm.def Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/projectfiles/compiler1/vm.def Fri Jan 07 03:58:11 2011 -0800 @@ -2,6 +2,6 @@ ; This .DEF file is a placeholder for one which is automatically ; generated during the build process. See ; make\windows\build_vm_def.sh and -; make\windows\makefiles\makedeps.make (esp. the "-prelink" +; make\windows\makefiles\projectcreator.make (esp. the "-prelink" ; options). ; diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/projectfiles/compiler2/Makefile --- a/make/windows/projectfiles/compiler2/Makefile Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/projectfiles/compiler2/Makefile Fri Jan 07 03:58:11 2011 -0800 @@ -22,8 +22,7 @@ # # -Variant=compiler2 -!include local.make +!include ../local.make AdlcOutDir=$(HOTSPOTBUILDSPACE)\$(Variant)\generated\adfiles AdditionalTargets=$(AdlcOutDir)\ad_$(Platform_arch_model).cpp $(AdlcOutDir)\dfa_$(Platform_arch_model).cpp diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/projectfiles/compiler2/vm.def --- a/make/windows/projectfiles/compiler2/vm.def Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/projectfiles/compiler2/vm.def Fri Jan 07 03:58:11 2011 -0800 @@ -2,6 +2,6 @@ ; This .DEF file is a placeholder for one which is automatically ; generated during the build process. See ; make\windows\build_vm_def.sh and -; make\windows\makefiles\makedeps.make (esp. the "-prelink" +; make\windows\makefiles\projectcreator.make (esp. the "-prelink" ; options). ; diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/projectfiles/core/Makefile --- a/make/windows/projectfiles/core/Makefile Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/projectfiles/core/Makefile Fri Jan 07 03:58:11 2011 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 2010, 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 @@ -22,7 +22,6 @@ # # -Variant=core -!include local.make +!include ../local.make !include $(HOTSPOTWORKSPACE)/make/windows/projectfiles/common/Makefile diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/projectfiles/core/vm.def --- a/make/windows/projectfiles/core/vm.def Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/projectfiles/core/vm.def Fri Jan 07 03:58:11 2011 -0800 @@ -2,6 +2,6 @@ ; This .DEF file is a placeholder for one which is automatically ; generated during the build process. See ; make\windows\build_vm_def.sh and -; make\windows\makefiles\makedeps.make (esp. the "-prelink" +; make\windows\makefiles\projectcreator.make (esp. the "-prelink" ; options). ; diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/projectfiles/kernel/Makefile --- a/make/windows/projectfiles/kernel/Makefile Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/projectfiles/kernel/Makefile Fri Jan 07 03:58:11 2011 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 2010 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 @@ -22,7 +22,6 @@ # # -Variant=kernel -!include local.make +!include ../local.make !include $(HOTSPOTWORKSPACE)/make/windows/projectfiles/common/Makefile diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/projectfiles/kernel/vm.def --- a/make/windows/projectfiles/kernel/vm.def Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/projectfiles/kernel/vm.def Fri Jan 07 03:58:11 2011 -0800 @@ -2,6 +2,6 @@ ; This .DEF file is a placeholder for one which is automatically ; generated during the build process. See ; make\windows\build_vm_def.sh and -; make\windows\makefiles\makedeps.make (esp. the "-prelink" +; make\windows\makefiles\projectcreator.make (esp. the "-prelink" ; options). ; diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/projectfiles/tiered/Makefile --- a/make/windows/projectfiles/tiered/Makefile Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/projectfiles/tiered/Makefile Fri Jan 07 03:58:11 2011 -0800 @@ -22,8 +22,7 @@ # # -Variant=tiered -!include local.make +!include ../local.make AdlcOutDir=$(HOTSPOTBUILDSPACE)\$(Variant)\generated\adfiles AdditionalTargets=$(AdlcOutDir)\ad_$(Platform_arch_model).cpp $(AdlcOutDir)\dfa_$(Platform_arch_model).cpp diff -r 55f868e91c3b -r 0e52ef6e94d3 make/windows/projectfiles/tiered/vm.def --- a/make/windows/projectfiles/tiered/vm.def Thu Jan 06 16:03:20 2011 -0800 +++ b/make/windows/projectfiles/tiered/vm.def Fri Jan 07 03:58:11 2011 -0800 @@ -2,6 +2,6 @@ ; This .DEF file is a placeholder for one which is automatically ; generated during the build process. See ; make\windows\build_vm_def.sh and -; make\windows\makefiles\makedeps.make (esp. the "-prelink" +; make\windows\makefiles\projectcreator.make (esp. the "-prelink" ; options). ; diff -r 55f868e91c3b -r 0e52ef6e94d3 src/os/linux/vm/decoder_linux.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/linux/vm/decoder_linux.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1997, 2010, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "prims/jvm.h" +#include "utilities/decoder.hpp" + +#include + +bool Decoder::demangle(const char* symbol, char *buf, int buflen) { + int status; + char* result; + size_t size = (size_t)buflen; + + // Don't pass buf to __cxa_demangle. In case of the 'buf' is too small, + // __cxa_demangle will call system "realloc" for additional memory, which + // may use different malloc/realloc mechanism that allocates 'buf'. + if ((result = abi::__cxa_demangle(symbol, NULL, NULL, &status)) != NULL) { + jio_snprintf(buf, buflen, "%s", result); + // call c library's free + ::free(result); + return true; + } + return false; +} diff -r 55f868e91c3b -r 0e52ef6e94d3 src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/os/linux/vm/os_linux.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -59,6 +59,7 @@ #include "services/attachListener.hpp" #include "services/runtimeService.hpp" #include "thread_linux.inline.hpp" +#include "utilities/decoder.hpp" #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/growableArray.hpp" @@ -114,6 +115,7 @@ # include # include # include +# include #define MAX_PATH (2 * K) @@ -1688,14 +1690,23 @@ Dl_info dlinfo; if (dladdr((void*)addr, &dlinfo) && dlinfo.dli_sname != NULL) { - if (buf) jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname); - if (offset) *offset = addr - (address)dlinfo.dli_saddr; + if (buf != NULL) { + if(!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) { + jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname); + } + } + if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr; return true; - } else { - if (buf) buf[0] = '\0'; - if (offset) *offset = -1; - return false; + } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { + if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), + dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) { + return true; + } } + + if (buf != NULL) buf[0] = '\0'; + if (offset != NULL) *offset = -1; + return false; } struct _address_to_library_name { @@ -4423,6 +4434,15 @@ return 1; } +int os::socket_available(int fd, jint *pbytes) { + // Linux doc says EINTR not returned, unlike Solaris + int ret = ::ioctl(fd, FIONREAD, pbytes); + + //%% note ioctl can return 0 when successful, JVM_SocketAvailable + // is expected to return 0 on failure and 1 on success to the jdk. + return (ret < 0) ? 0 : 1; +} + // Map a block of memory. char* os::map_memory(int fd, const char* file_name, size_t file_offset, char *addr, size_t bytes, bool read_only, diff -r 55f868e91c3b -r 0e52ef6e94d3 src/os/linux/vm/os_linux.inline.hpp --- a/src/os/linux/vm/os_linux.inline.hpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/os/linux/vm/os_linux.inline.hpp Fri Jan 07 03:58:11 2011 -0800 @@ -45,7 +45,6 @@ #include #include #include -#include #include inline void* os::thread_local_storage_at(int index) { @@ -268,16 +267,6 @@ RESTARTABLE_RETURN_INT(::sendto(fd, buf, len, (unsigned int) flags, to, tolen)); } -inline int os::socket_available(int fd, jint *pbytes) { - // Linux doc says EINTR not returned, unlike Solaris - int ret = ::ioctl(fd, FIONREAD, pbytes); - - //%% note ioctl can return 0 when successful, JVM_SocketAvailable - // is expected to return 0 on failure and 1 on success to the jdk. - return (ret < 0) ? 0 : 1; -} - - inline int os::socket_shutdown(int fd, int howto){ return ::shutdown(fd, howto); } diff -r 55f868e91c3b -r 0e52ef6e94d3 src/os/linux/vm/perfMemory_linux.cpp --- a/src/os/linux/vm/perfMemory_linux.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/os/linux/vm/perfMemory_linux.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -635,7 +635,29 @@ return -1; } - return fd; + // Verify that we have enough disk space for this file. + // We'll get random SIGBUS crashes on memory accesses if + // we don't. + + for (size_t seekpos = 0; seekpos < size; seekpos += os::vm_page_size()) { + int zero_int = 0; + result = (int)os::seek_to_file_offset(fd, (jlong)(seekpos)); + if (result == -1 ) break; + RESTARTABLE(::write(fd, &zero_int, 1), result); + if (result != 1) { + if (errno == ENOSPC) { + warning("Insufficient space for shared memory file:\n %s\nTry using the -Djava.io.tmpdir= option to select an alternate temp location.\n", filename); + } + break; + } + } + + if (result != -1) { + return fd; + } else { + RESTARTABLE(::close(fd), result); + return -1; + } } // open the shared memory file for the given user and vmid. returns diff -r 55f868e91c3b -r 0e52ef6e94d3 src/os/posix/launcher/java_md.c --- a/src/os/posix/launcher/java_md.c Thu Jan 06 16:03:20 2011 -0800 +++ b/src/os/posix/launcher/java_md.c Fri Jan 07 03:58:11 2011 -0800 @@ -812,13 +812,10 @@ #ifdef GAMMA { - /* gamma launcher uses JAVA_HOME or ALT_JAVA_HOME environment variable to find JDK/JRE */ - char* java_home_var = getenv("ALT_JAVA_HOME"); + /* gamma launcher uses JAVA_HOME environment variable to find JDK/JRE */ + char* java_home_var = getenv("JAVA_HOME"); if (java_home_var == NULL) { - java_home_var = getenv("JAVA_HOME"); - } - if (java_home_var == NULL) { - printf("JAVA_HOME or ALT_JAVA_HOME must point to a valid JDK/JRE to run gamma\n"); + printf("JAVA_HOME must point to a valid JDK/JRE to run gamma\n"); return JNI_FALSE; } snprintf(buf, bufsize, "%s", java_home_var); @@ -1837,7 +1834,7 @@ if (pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args) == 0) { void * tmp; pthread_join(tid, &tmp); - rslt = (int)tmp; + rslt = (int)(intptr_t)tmp; } else { /* * Continue execution in current thread if for some reason (e.g. out of @@ -1855,7 +1852,7 @@ if (thr_create(NULL, stack_size, (void *(*)(void *))continuation, args, flags, &tid) == 0) { void * tmp; thr_join(tid, NULL, &tmp); - rslt = (int)tmp; + rslt = (int)(intptr_t)tmp; } else { /* See above. Continue in current thread if thr_create() failed */ rslt = continuation(args); diff -r 55f868e91c3b -r 0e52ef6e94d3 src/os/posix/launcher/launcher.script --- a/src/os/posix/launcher/launcher.script Thu Jan 06 16:03:20 2011 -0800 +++ b/src/os/posix/launcher/launcher.script Fri Jan 07 03:58:11 2011 -0800 @@ -95,17 +95,21 @@ ;; esac +# Find out the absolute path to this script +MYDIR=$(cd $(dirname $SCRIPT) && pwd) + +JDK= if [ "${ALT_JAVA_HOME}" = "" ]; then - if [ "${JAVA_HOME}" = "" ]; then - echo "Neither ALT_JAVA_HOME nor JAVA_HOME is set. Aborting."; - exit 1; - else - JDK=${JAVA_HOME%%/jre}; - fi + source ${MYDIR}/jdkpath.sh else JDK=${ALT_JAVA_HOME%%/jre}; fi +if [ "${JDK}" = "" ]; then + echo Failed to find JDK. ALT_JAVA_HOME is not set or ./jdkpath.sh is empty or not found. + exit 1 +fi + # We will set the LD_LIBRARY_PATH as follows: # o $JVMPATH (directory portion only) # o $JRE/lib/$ARCH diff -r 55f868e91c3b -r 0e52ef6e94d3 src/os/solaris/vm/decoder_solaris.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/solaris/vm/decoder_solaris.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 1997, 2010, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "utilities/decoder.hpp" + +#include + +bool Decoder::demangle(const char* symbol, char *buf, int buflen) { + return !cplus_demangle(symbol, buf, (size_t)buflen); +} diff -r 55f868e91c3b -r 0e52ef6e94d3 src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/os/solaris/vm/os_solaris.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -57,6 +57,7 @@ #include "services/attachListener.hpp" #include "services/runtimeService.hpp" #include "thread_solaris.inline.hpp" +#include "utilities/decoder.hpp" #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/growableArray.hpp" @@ -79,6 +80,7 @@ // put OS-includes here # include # include +# include # include # include # include @@ -1474,6 +1476,13 @@ return &allowdebug_blocked_sigs; } + +void _handle_uncaught_cxx_exception() { + VMError err("An uncaught C++ exception"); + err.report_and_die(); +} + + // First crack at OS-specific initialization, from inside the new thread. void os::initialize_thread() { int r = thr_main() ; @@ -1563,6 +1572,7 @@ // use the dynamic check for T2 libthread. os::Solaris::init_thread_fpu_state(); + std::set_terminate(_handle_uncaught_cxx_exception); } @@ -1969,27 +1979,42 @@ Sym * info; if (dladdr1_func((void *)addr, &dlinfo, (void **)&info, RTLD_DL_SYMENT)) { - if (buf) jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname); - if (offset) *offset = addr - (address)dlinfo.dli_saddr; - - // check if the returned symbol really covers addr - return ((char *)dlinfo.dli_saddr + info->st_size > (char *)addr); - } else { - if (buf) buf[0] = '\0'; - if (offset) *offset = -1; - return false; + if ((char *)dlinfo.dli_saddr + info->st_size > (char *)addr) { + if (buf != NULL) { + if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) + jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname); + } + if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr; + return true; + } } + if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { + if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), + dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) { + return true; + } + } + if (buf != NULL) buf[0] = '\0'; + if (offset != NULL) *offset = -1; + return false; } else { // no, only dladdr is available - if(dladdr((void *)addr, &dlinfo)) { - if (buf) jio_snprintf(buf, buflen, dlinfo.dli_sname); - if (offset) *offset = addr - (address)dlinfo.dli_saddr; + if (dladdr((void *)addr, &dlinfo)) { + if (buf != NULL) { + if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) + jio_snprintf(buf, buflen, dlinfo.dli_sname); + } + if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr; + return true; + } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { + if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), + dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) { return true; - } else { - if (buf) buf[0] = '\0'; - if (offset) *offset = -1; - return false; + } } + if (buf != NULL) buf[0] = '\0'; + if (offset != NULL) *offset = -1; + return false; } } diff -r 55f868e91c3b -r 0e52ef6e94d3 src/os/windows/launcher/java_md.c --- a/src/os/windows/launcher/java_md.c Thu Jan 06 16:03:20 2011 -0800 +++ b/src/os/windows/launcher/java_md.c Fri Jan 07 03:58:11 2011 -0800 @@ -22,6 +22,7 @@ * */ +#include #include #include #include @@ -486,16 +487,62 @@ #else /* ifndef GAMMA */ - /* gamma launcher uses JAVA_HOME or ALT_JAVA_HOME environment variable to find JDK/JRE */ - char* java_home_var = getenv("ALT_JAVA_HOME"); - if (java_home_var == NULL) { - java_home_var = getenv("JAVA_HOME"); + char env[MAXPATHLEN + 1]; + + /* gamma launcher uses ALT_JAVA_HOME environment variable or jdkpath.txt file to find JDK/JRE */ + + if (getenv("ALT_JAVA_HOME") != NULL) { + snprintf(buf, bufsize, "%s", getenv("ALT_JAVA_HOME")); } - if (java_home_var == NULL) { - printf("JAVA_HOME or ALT_JAVA_HOME must point to a valid JDK/JRE to run gamma\n"); - return JNI_FALSE; + else { + char path[MAXPATHLEN + 1]; + char* p; + int len; + FILE* fp; + + // find the path to the currect executable + len = GetModuleFileName(NULL, path, MAXPATHLEN + 1); + if (len == 0 || len > MAXPATHLEN) { + printf("Could not get directory of current executable."); + return JNI_FALSE; + } + // remove last path component ("hotspot.exe") + p = strrchr(path, '\\'); + if (p == NULL) { + printf("Could not parse directory of current executable.\n"); + return JNI_FALSE; + } + *p = '\0'; + + // open jdkpath.txt and read JAVA_HOME from it + if (strlen(path) + strlen("\\jdkpath.txt") + 1 >= MAXPATHLEN) { + printf("Path too long: %s\n", path); + return JNI_FALSE; + } + strcat(path, "\\jdkpath.txt"); + fp = fopen(path, "r"); + if (fp == NULL) { + printf("Could not open file %s to get path to JDK.\n", path); + return JNI_FALSE; + } + + if (fgets(buf, bufsize, fp) == NULL) { + printf("Could not read from file %s to get path to JDK.\n", path); + fclose(fp); + return JNI_FALSE; + } + // trim the buffer + p = buf + strlen(buf) - 1; + while(isspace(*p)) { + *p = '\0'; + p--; + } + fclose(fp); } - snprintf(buf, bufsize, "%s", java_home_var); + + _snprintf(env, MAXPATHLEN, "JAVA_HOME=%s", buf); + _putenv(env); + return JNI_TRUE; #endif /* ifndef GAMMA */ } diff -r 55f868e91c3b -r 0e52ef6e94d3 src/os/windows/vm/decoder_windows.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/windows/vm/decoder_windows.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1997, 2010, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "prims/jvm.h" +#include "utilities/decoder.hpp" + +HMODULE Decoder::_dbghelp_handle = NULL; +bool Decoder::_can_decode_in_vm = false; +pfn_SymGetSymFromAddr64 Decoder::_pfnSymGetSymFromAddr64 = NULL; +pfn_UndecorateSymbolName Decoder::_pfnUndecorateSymbolName = NULL; + +void Decoder::initialize() { + if (!_initialized) { + _initialized = true; + + HMODULE handle = ::LoadLibrary("dbghelp.dll"); + if (!handle) { + _decoder_status = helper_not_found; + return; + } + + _dbghelp_handle = handle; + + pfn_SymSetOptions _pfnSymSetOptions = (pfn_SymSetOptions)::GetProcAddress(handle, "SymSetOptions"); + pfn_SymInitialize _pfnSymInitialize = (pfn_SymInitialize)::GetProcAddress(handle, "SymInitialize"); + _pfnSymGetSymFromAddr64 = (pfn_SymGetSymFromAddr64)::GetProcAddress(handle, "SymGetSymFromAddr64"); + _pfnUndecorateSymbolName = (pfn_UndecorateSymbolName)GetProcAddress(handle, "UnDecorateSymbolName"); + + if (_pfnSymSetOptions == NULL || _pfnSymInitialize == NULL || _pfnSymGetSymFromAddr64 == NULL) { + _pfnSymGetSymFromAddr64 = NULL; + _pfnUndecorateSymbolName = NULL; + ::FreeLibrary(handle); + _dbghelp_handle = NULL; + _decoder_status = helper_func_error; + return; + } + + _pfnSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); + if (!_pfnSymInitialize(GetCurrentProcess(), NULL, TRUE)) { + _pfnSymGetSymFromAddr64 = NULL; + _pfnUndecorateSymbolName = NULL; + ::FreeLibrary(handle); + _dbghelp_handle = NULL; + _decoder_status = helper_init_error; + return; + } + + // find out if jvm.dll contains private symbols, by decoding + // current function and comparing the result + address addr = (address)Decoder::initialize; + char buf[MAX_PATH]; + if (decode(addr, buf, sizeof(buf), NULL) == no_error) { + _can_decode_in_vm = !strcmp(buf, "Decoder::initialize"); + } + } +} + +void Decoder::uninitialize() { + assert(_initialized, "Decoder not yet initialized"); + _pfnSymGetSymFromAddr64 = NULL; + _pfnUndecorateSymbolName = NULL; + if (_dbghelp_handle != NULL) { + ::FreeLibrary(_dbghelp_handle); + } + _initialized = false; +} + +bool Decoder::can_decode_C_frame_in_vm() { + initialize(); + return _can_decode_in_vm; +} + + +Decoder::decoder_status Decoder::decode(address addr, char *buf, int buflen, int *offset) { + assert(_initialized, "Decoder not yet initialized"); + if (_pfnSymGetSymFromAddr64 != NULL) { + PIMAGEHLP_SYMBOL64 pSymbol; + char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)]; + pSymbol = (PIMAGEHLP_SYMBOL64)symbolInfo; + pSymbol->MaxNameLength = MAX_PATH; + pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + DWORD64 displacement; + if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) { + if (buf != NULL) { + if (!demangle(pSymbol->Name, buf, buflen)) { + jio_snprintf(buf, buflen, "%s", pSymbol->Name); + } + } + if (offset != NULL) *offset = (int)displacement; + return no_error; + } + } + return helper_not_found; +} + +bool Decoder::demangle(const char* symbol, char *buf, int buflen) { + assert(_initialized, "Decoder not yet initialized"); + return _pfnUndecorateSymbolName != NULL && + _pfnUndecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE); +} + diff -r 55f868e91c3b -r 0e52ef6e94d3 src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/os/windows/vm/os_windows.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * CopyrighT (c) 1997, 2010, 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 @@ -62,6 +62,7 @@ #include "services/attachListener.hpp" #include "services/runtimeService.hpp" #include "thread_windows.inline.hpp" +#include "utilities/decoder.hpp" #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/growableArray.hpp" @@ -1365,12 +1366,11 @@ bool os::dll_address_to_function_name(address addr, char *buf, int buflen, int *offset) { - // Unimplemented on Windows - in order to use SymGetSymFromAddr(), - // we need to initialize imagehlp/dbghelp, then load symbol table - // for every module. That's too much work to do after a fatal error. - // For an example on how to implement this function, see 1.4.2. - if (offset) *offset = -1; - if (buf) buf[0] = '\0'; + if (Decoder::decode(addr, buf, buflen, offset) == Decoder::no_error) { + return true; + } + if (offset != NULL) *offset = -1; + if (buf != NULL) buf[0] = '\0'; return false; } @@ -1711,14 +1711,11 @@ buf[0] = '\0'; if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) { // Support for the gamma launcher. Check for an - // ALT_JAVA_HOME or JAVA_HOME environment variable + // JAVA_HOME environment variable // and fix up the path so it looks like // libjvm.so is installed there (append a fake suffix // hotspot/libjvm.so). - char* java_home_var = ::getenv("ALT_JAVA_HOME"); - if (java_home_var == NULL) { - java_home_var = ::getenv("JAVA_HOME"); - } + char* java_home_var = ::getenv("JAVA_HOME"); if (java_home_var != NULL && java_home_var[0] != 0) { strncpy(buf, java_home_var, buflen); @@ -2007,6 +2004,16 @@ int number; }; +// All Visual C++ exceptions thrown from code generated by the Microsoft Visual +// C++ compiler contain this error code. Because this is a compiler-generated +// error, the code is not listed in the Win32 API header files. +// The code is actually a cryptic mnemonic device, with the initial "E" +// standing for "exception" and the final 3 bytes (0x6D7363) representing the +// ASCII values of "msc". + +#define EXCEPTION_UNCAUGHT_CXX_EXCEPTION 0xE06D7363 + + struct siglabel exceptlabels[] = { def_excpt(EXCEPTION_ACCESS_VIOLATION), def_excpt(EXCEPTION_DATATYPE_MISALIGNMENT), @@ -2031,6 +2038,7 @@ def_excpt(EXCEPTION_INVALID_DISPOSITION), def_excpt(EXCEPTION_GUARD_PAGE), def_excpt(EXCEPTION_INVALID_HANDLE), + def_excpt(EXCEPTION_UNCAUGHT_CXX_EXCEPTION), NULL, 0 }; @@ -2264,7 +2272,6 @@ } } - if (t != NULL && t->is_Java_thread()) { JavaThread* thread = (JavaThread*) t; bool in_java = thread->thread_state() == _thread_in_Java; @@ -2468,8 +2475,9 @@ } // switch } #ifndef _WIN64 - if ((thread->thread_state() == _thread_in_Java) || - (thread->thread_state() == _thread_in_native) ) + if (((thread->thread_state() == _thread_in_Java) || + (thread->thread_state() == _thread_in_native)) && + exception_code != EXCEPTION_UNCAUGHT_CXX_EXCEPTION) { LONG result=Handle_FLT_Exception(exceptionInfo); if (result==EXCEPTION_CONTINUE_EXECUTION) return result; @@ -2493,6 +2501,7 @@ case EXCEPTION_ILLEGAL_INSTRUCTION_2: case EXCEPTION_INT_OVERFLOW: case EXCEPTION_INT_DIVIDE_BY_ZERO: + case EXCEPTION_UNCAUGHT_CXX_EXCEPTION: { report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord, exceptionInfo->ContextRecord); } diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/tools/ProjectCreator/BuildConfig.java --- a/src/share/tools/ProjectCreator/BuildConfig.java Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/tools/ProjectCreator/BuildConfig.java Fri Jan 07 03:58:11 2011 -0800 @@ -22,8 +22,11 @@ * */ -import java.util.*; import java.io.File; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Vector; class BuildConfig { Hashtable vars; @@ -57,7 +60,6 @@ // ones mentioned above were needed to expand format String buildBase = expandFormat(getFieldString(null, "BuildBase")); - String jdkDir = getFieldString(null, "JdkTargetRoot"); String sourceBase = getFieldString(null, "SourceBase"); String outDir = buildBase; @@ -65,7 +67,7 @@ put("OutputDir", outDir); put("SourceBase", sourceBase); put("BuildBase", buildBase); - put("OutputDll", jdkDir + Util.sep + outDll); + put("OutputDll", outDir + Util.sep + outDll); context = new String [] {flavourBuild, flavour, build, null}; } @@ -537,68 +539,75 @@ } } -class C1DebugConfig extends GenericDebugConfig { +abstract class GenericDebugNonKernelConfig extends GenericDebugConfig { + protected void init(Vector includes, Vector defines) { + super.init(includes, defines); + getCI().getAdditionalNonKernelLinkerFlags(getV("LinkerFlags")); + } +} + +class C1DebugConfig extends GenericDebugNonKernelConfig { String getOptFlag() { return getCI().getNoOptFlag(); } C1DebugConfig() { - initNames("compiler1", "debug", "fastdebug\\jre\\bin\\client\\jvm.dll"); + initNames("compiler1", "debug", "jvm.dll"); init(getIncludes(), getDefines()); } } -class C1FastDebugConfig extends GenericDebugConfig { +class C1FastDebugConfig extends GenericDebugNonKernelConfig { String getOptFlag() { return getCI().getOptFlag(); } C1FastDebugConfig() { - initNames("compiler1", "fastdebug", "fastdebug\\jre\\bin\\client\\jvm.dll"); + initNames("compiler1", "fastdebug", "jvm.dll"); init(getIncludes(), getDefines()); } } -class C2DebugConfig extends GenericDebugConfig { +class C2DebugConfig extends GenericDebugNonKernelConfig { String getOptFlag() { return getCI().getNoOptFlag(); } C2DebugConfig() { - initNames("compiler2", "debug", "fastdebug\\jre\\bin\\server\\jvm.dll"); + initNames("compiler2", "debug", "jvm.dll"); init(getIncludes(), getDefines()); } } -class C2FastDebugConfig extends GenericDebugConfig { +class C2FastDebugConfig extends GenericDebugNonKernelConfig { String getOptFlag() { return getCI().getOptFlag(); } C2FastDebugConfig() { - initNames("compiler2", "fastdebug", "fastdebug\\jre\\bin\\server\\jvm.dll"); + initNames("compiler2", "fastdebug", "jvm.dll"); init(getIncludes(), getDefines()); } } -class TieredDebugConfig extends GenericDebugConfig { +class TieredDebugConfig extends GenericDebugNonKernelConfig { String getOptFlag() { return getCI().getNoOptFlag(); } TieredDebugConfig() { - initNames("tiered", "debug", "fastdebug\\jre\\bin\\server\\jvm.dll"); + initNames("tiered", "debug", "jvm.dll"); init(getIncludes(), getDefines()); } } -class TieredFastDebugConfig extends GenericDebugConfig { +class TieredFastDebugConfig extends GenericDebugNonKernelConfig { String getOptFlag() { return getCI().getOptFlag(); } TieredFastDebugConfig() { - initNames("tiered", "fastdebug", "fastdebug\\jre\\bin\\server\\jvm.dll"); + initNames("tiered", "fastdebug", "jvm.dll"); init(getIncludes(), getDefines()); } } @@ -618,45 +627,45 @@ class C1ProductConfig extends ProductConfig { C1ProductConfig() { - initNames("compiler1", "product", "jre\\bin\\client\\jvm.dll"); + initNames("compiler1", "product", "jvm.dll"); init(getIncludes(), getDefines()); } } class C2ProductConfig extends ProductConfig { C2ProductConfig() { - initNames("compiler2", "product", "jre\\bin\\server\\jvm.dll"); + initNames("compiler2", "product", "jvm.dll"); init(getIncludes(), getDefines()); } } class TieredProductConfig extends ProductConfig { TieredProductConfig() { - initNames("tiered", "product", "jre\\bin\\server\\jvm.dll"); + initNames("tiered", "product", "jvm.dll"); init(getIncludes(), getDefines()); } } -class CoreDebugConfig extends GenericDebugConfig { +class CoreDebugConfig extends GenericDebugNonKernelConfig { String getOptFlag() { return getCI().getNoOptFlag(); } CoreDebugConfig() { - initNames("core", "debug", "fastdebug\\jre\\bin\\core\\jvm.dll"); + initNames("core", "debug", "jvm.dll"); init(getIncludes(), getDefines()); } } -class CoreFastDebugConfig extends GenericDebugConfig { +class CoreFastDebugConfig extends GenericDebugNonKernelConfig { String getOptFlag() { return getCI().getOptFlag(); } CoreFastDebugConfig() { - initNames("core", "fastdebug", "fastdebug\\jre\\bin\\core\\jvm.dll"); + initNames("core", "fastdebug", "jvm.dll"); init(getIncludes(), getDefines()); } } @@ -664,7 +673,7 @@ class CoreProductConfig extends ProductConfig { CoreProductConfig() { - initNames("core", "product", "jre\\bin\\core\\jvm.dll"); + initNames("core", "product", "jvm.dll"); init(getIncludes(), getDefines()); } } @@ -675,7 +684,7 @@ } KernelDebugConfig() { - initNames("kernel", "debug", "fastdebug\\jre\\bin\\kernel\\jvm.dll"); + initNames("kernel", "debug", "jvm.dll"); init(getIncludes(), getDefines()); } } @@ -687,7 +696,7 @@ } KernelFastDebugConfig() { - initNames("kernel", "fastdebug", "fastdebug\\jre\\bin\\kernel\\jvm.dll"); + initNames("kernel", "fastdebug", "jvm.dll"); init(getIncludes(), getDefines()); } } @@ -695,7 +704,7 @@ class KernelProductConfig extends ProductConfig { KernelProductConfig() { - initNames("kernel", "product", "jre\\bin\\kernel\\jvm.dll"); + initNames("kernel", "product", "jvm.dll"); init(getIncludes(), getDefines()); } } @@ -704,6 +713,7 @@ abstract Vector getBaseLinkerFlags(String outDir, String outDll); abstract Vector getDebugCompilerFlags(String opt); abstract Vector getDebugLinkerFlags(); + abstract void getAdditionalNonKernelLinkerFlags(Vector rv); abstract Vector getProductCompilerFlags(); abstract Vector getProductLinkerFlags(); abstract String getOptFlag(); @@ -713,4 +723,14 @@ void addAttr(Vector receiver, String attr, String value) { receiver.add(attr); receiver.add(value); } + void extAttr(Vector receiver, String attr, String value) { + int attr_pos=receiver.indexOf(attr) ; + if ( attr_pos == -1) { + // If attr IS NOT present in the Vector - add it + receiver.add(attr); receiver.add(value); + } else { + // If attr IS present in the Vector - append value to it + receiver.set(attr_pos+1,receiver.get(attr_pos+1)+value); + } + } } diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/tools/ProjectCreator/WinGammaPlatform.java --- a/src/share/tools/ProjectCreator/WinGammaPlatform.java Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/tools/ProjectCreator/WinGammaPlatform.java Fri Jan 07 03:58:11 2011 -0800 @@ -22,8 +22,15 @@ * */ -import java.io.*; -import java.util.*; +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.TreeSet; +import java.util.Vector; abstract class HsArgHandler extends ArgHandler { static final int STRING = 1; @@ -345,11 +352,23 @@ new ArgsParser(args, new ArgRule[] { - new HsArgRule("-sourceBase", - "SourceBase", - " (Did you set the HotSpotWorkSpace environment variable?)", - HsArgHandler.STRING - ), + new ArgRule("-sourceBase", + new HsArgHandler() { + public void handle(ArgIterator it) { + String cfg = getCfg(it.get()); + if (nextNotKey(it)) { + String sb = (String) it.get(); + if (sb.endsWith(Util.sep)) { + sb = sb.substring(0, sb.length() - 1); + } + BuildConfig.putField(cfg, "SourceBase", sb); + it.next(); + } else { + empty("-sourceBase", null); + } + } + } + ), new HsArgRule("-buildBase", "BuildBase", @@ -512,7 +531,6 @@ new HsArgHandler() { public void handle(ArgIterator it) { if (nextNotKey(it)) { - String build = it.get(); if (nextNotKey(it)) { String description = it.get(); if (nextNotKey(it)) { @@ -528,7 +546,28 @@ empty(null, "** Error: wrong number of args to -prelink"); } } - ) + ), + + new ArgRule("-postbuild", + new HsArgHandler() { + public void handle(ArgIterator it) { + if (nextNotKey(it)) { + if (nextNotKey(it)) { + String description = it.get(); + if (nextNotKey(it)) { + String command = it.get(); + BuildConfig.putField(null, "PostbuildDescription", description); + BuildConfig.putField(null, "PostbuildCommand", command); + it.next(); + return; + } + } + } + + empty(null, "** Error: wrong number of args to -postbuild"); + } + } + ), }, new ArgHandler() { public void handle(ArgIterator it) { @@ -618,10 +657,6 @@ public int compareTo(Object o) { FileInfo oo = (FileInfo)o; - // Don't squelch identical short file names where the full - // paths are different - if (!attr.shortName.equals(oo.attr.shortName)) - return attr.shortName.compareTo(oo.attr.shortName); return full.compareTo(oo.full); } diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/tools/ProjectCreator/WinGammaPlatformVC6.java --- a/src/share/tools/ProjectCreator/WinGammaPlatformVC6.java Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/tools/ProjectCreator/WinGammaPlatformVC6.java Fri Jan 07 03:58:11 2011 -0800 @@ -260,6 +260,8 @@ return rv; } + void getAdditionalNonKernelLinkerFlags(Vector rv) {} + Vector getProductCompilerFlags() { Vector rv = new Vector(); diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/tools/ProjectCreator/WinGammaPlatformVC7.java --- a/src/share/tools/ProjectCreator/WinGammaPlatformVC7.java Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/tools/ProjectCreator/WinGammaPlatformVC7.java Fri Jan 07 03:58:11 2011 -0800 @@ -22,8 +22,13 @@ * */ -import java.io.*; -import java.util.*; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.TreeSet; +import java.util.Vector; public class WinGammaPlatformVC7 extends WinGammaPlatform { @@ -104,7 +109,9 @@ boolean match(FileInfo fi) { - return fi.full.regionMatches(true, baseLen, dir, 0, dirLen); + int lastSlashIndex = fi.full.lastIndexOf('/'); + String fullDir = fi.full.substring(0, lastSlashIndex); + return fullDir.endsWith(dir); } } @@ -217,65 +224,41 @@ // - container filter just provides a container to group together real filters // - real filter can select elements from the set according to some rule, put it into XML // and remove from the list - Vector makeFilters(TreeSet files) { + Vector makeFilters(TreeSet files) { Vector rv = new Vector(); String sbase = Util.normalize(BuildConfig.getFieldString(null, "SourceBase")+"/src/"); - ContainerFilter rt = new ContainerFilter("Runtime"); - rt.add(new DirectoryFilter("share/vm/prims", sbase)); - rt.add(new DirectoryFilter("share/vm/runtime", sbase)); - rt.add(new DirectoryFilter("share/vm/oops", sbase)); - rv.add(rt); - - ContainerFilter gc = new ContainerFilter("GC"); - gc.add(new DirectoryFilter("share/vm/memory", sbase)); - gc.add(new DirectoryFilter("share/vm/gc_interface", sbase)); + String currentDir = ""; + DirectoryFilter container = null; + for(FileInfo fileInfo : files) { - ContainerFilter gc_impl = new ContainerFilter("Implementations"); - gc_impl.add(new DirectoryFilter("CMS", - "share/vm/gc_implementation/concurrentMarkSweep", - sbase)); - gc_impl.add(new DirectoryFilter("Parallel Scavenge", - "share/vm/gc_implementation/parallelScavenge", - sbase)); - gc_impl.add(new DirectoryFilter("Shared", - "share/vm/gc_implementation/shared", - sbase)); - // for all leftovers - gc_impl.add(new DirectoryFilter("Misc", - "share/vm/gc_implementation", - sbase)); - - gc.add(gc_impl); - rv.add(gc); + if (!fileInfo.full.startsWith(sbase)) { + continue; + } - rv.add(new DirectoryFilter("C1", "share/vm/c1", sbase)); - - rv.add(new DirectoryFilter("C2", "share/vm/opto", sbase)); - - ContainerFilter comp = new ContainerFilter("Compiler Common"); - comp.add(new DirectoryFilter("share/vm/asm", sbase)); - comp.add(new DirectoryFilter("share/vm/ci", sbase)); - comp.add(new DirectoryFilter("share/vm/code", sbase)); - comp.add(new DirectoryFilter("share/vm/compiler", sbase)); - rv.add(comp); + int lastSlash = fileInfo.full.lastIndexOf('/'); + String dir = fileInfo.full.substring(sbase.length(), lastSlash); + if(dir.equals("share/vm")) { + // skip files directly in share/vm - should only be precompiled.hpp which is handled below + continue; + } + if (!dir.equals(currentDir)) { + currentDir = dir; + if (container != null) { + rv.add(container); + } - rv.add(new DirectoryFilter("Interpreter", - "share/vm/interpreter", - sbase)); - - ContainerFilter misc = new ContainerFilter("Misc"); - misc.add(new DirectoryFilter("share/vm/libadt", sbase)); - misc.add(new DirectoryFilter("share/vm/services", sbase)); - misc.add(new DirectoryFilter("share/vm/utilities", sbase)); - misc.add(new DirectoryFilter("share/vm/classfile", sbase)); - rv.add(misc); - - rv.add(new DirectoryFilter("os_cpu", sbase)); - - rv.add(new DirectoryFilter("cpu", sbase)); - - rv.add(new DirectoryFilter("os", sbase)); + // remove "share/vm/" from names + String name = dir; + if (dir.startsWith("share/vm/")) { + name = dir.substring("share/vm/".length(), dir.length()); + } + container = new DirectoryFilter(name, dir, sbase); + } + } + if (container != null) { + rv.add(container); + } ContainerFilter generated = new ContainerFilter("Generated"); ContainerFilter c1Generated = new ContainerFilter("C1"); @@ -397,7 +380,6 @@ "Name", cfg, "ExcludedFromBuild", "TRUE" }); - tag("Tool", new String[] {"Name", "VCCLCompilerTool"}); endTag("FileConfiguration"); } @@ -441,7 +423,11 @@ tag("Tool", new String[] { - "Name", "VCPostBuildEventTool" + "Name", "VCPostBuildEventTool", + "Description", BuildConfig.getFieldString(null, "PostbuildDescription"), + //Caution: String.replace(String,String) is available from JDK5 onwards only + "CommandLine", cfg.expandFormat(BuildConfig.getFieldString(null, "PostbuildCommand").replace + ("\t", " ")) } ); @@ -469,33 +455,6 @@ "Culture", "1033" } ); - tag("Tool", - new String[] { - "Name", "VCWebServiceProxyGeneratorTool" - } - ); - - tag ("Tool", - new String[] { - "Name", "VCXMLDataGeneratorTool" - } - ); - - tag("Tool", - new String[] { - "Name", "VCWebDeploymentTool" - } - ); - tag("Tool", - new String[] { - "Name", "VCManagedWrapperGeneratorTool" - } - ); - tag("Tool", - new String[] { - "Name", "VCAuxiliaryManagedWrapperGeneratorTool" - } - ); tag("Tool", new String[] { @@ -597,7 +556,7 @@ addAttr(rv, "PrecompiledHeaderFile", outDir+Util.sep+"vm.pch"); addAttr(rv, "AssemblerListingLocation", outDir); addAttr(rv, "ObjectFile", outDir+Util.sep); - addAttr(rv, "ProgramDataBaseFileName", outDir+Util.sep+"vm.pdb"); + addAttr(rv, "ProgramDataBaseFileName", outDir+Util.sep+"jvm.pdb"); // Set /nologo optin addAttr(rv, "SuppressStartupBanner", "TRUE"); // Surpass the default /Tc or /Tp. 0 is compileAsDefault @@ -631,17 +590,22 @@ addAttr(rv, "AdditionalOptions", "/export:JNI_GetDefaultJavaVMInitArgs " + "/export:JNI_CreateJavaVM " + + "/export:JVM_FindClassFromBootLoader "+ "/export:JNI_GetCreatedJavaVMs "+ "/export:jio_snprintf /export:jio_printf "+ "/export:jio_fprintf /export:jio_vfprintf "+ - "/export:jio_vsnprintf "); + "/export:jio_vsnprintf "+ + "/export:JVM_GetVersionInfo "+ + "/export:JVM_GetThreadStateNames "+ + "/export:JVM_GetThreadStateValues "+ + "/export:JVM_InitAgentProperties "); addAttr(rv, "AdditionalDependencies", "Wsock32.lib winmm.lib"); addAttr(rv, "OutputFile", outDll); // Set /INCREMENTAL option. 1 is linkIncrementalNo addAttr(rv, "LinkIncremental", "1"); addAttr(rv, "SuppressStartupBanner", "TRUE"); addAttr(rv, "ModuleDefinitionFile", outDir+Util.sep+"vm.def"); - addAttr(rv, "ProgramDatabaseFile", outDir+Util.sep+"vm.pdb"); + addAttr(rv, "ProgramDatabaseFile", outDir+Util.sep+"jvm.pdb"); // Set /SUBSYSTEM option. 2 is subSystemWindows addAttr(rv, "SubSystem", "2"); addAttr(rv, "BaseAddress", "0x8000000"); @@ -682,6 +646,11 @@ return rv; } + void getAdditionalNonKernelLinkerFlags(Vector rv) { + extAttr(rv, "AdditionalOptions", + "/export:AsyncGetCallTrace "); + } + void getProductCompilerFlags_common(Vector rv) { // Set /O2 option. 2 is optimizeMaxSpeed addAttr(rv, "Optimization", "2"); diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/tools/ProjectCreator/WinGammaPlatformVC8.java --- a/src/share/tools/ProjectCreator/WinGammaPlatformVC8.java Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/tools/ProjectCreator/WinGammaPlatformVC8.java Fri Jan 07 03:58:11 2011 -0800 @@ -22,7 +22,7 @@ * */ -import java.util.*; +import java.util.Vector; public class WinGammaPlatformVC8 extends WinGammaPlatformVC7 { @@ -41,6 +41,9 @@ // Set /EHsc- option. 0 is cppExceptionHandlingNo addAttr(rv, "ExceptionHandling", "0"); + // enable multi process builds + extAttr(rv, "AdditionalOptions", "/MP"); + return rv; } diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/tools/launcher/java.c --- a/src/share/tools/launcher/java.c Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/tools/launcher/java.c Fri Jan 07 03:58:11 2011 -0800 @@ -275,6 +275,8 @@ jvmpath, sizeof(jvmpath), original_argv); + printf("Using java runtime at: %s\n", jrepath); + ifn.CreateJavaVM = 0; ifn.GetDefaultJavaVMInitArgs = 0; diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/tools/launcher/jli_util.c --- a/src/share/tools/launcher/jli_util.c Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/tools/launcher/jli_util.c Fri Jan 07 03:58:11 2011 -0800 @@ -1,3 +1,4 @@ + /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -27,7 +28,7 @@ #include "jli_util.h" #ifdef GAMMA -#ifdef _WINDOWS +#ifdef TARGET_OS_FAMILY_windows #define strdup _strdup #endif #endif diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/code/nmethod.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -619,8 +619,8 @@ OopMapSet* oop_maps ) : CodeBlob("native nmethod", code_buffer, sizeof(nmethod), nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps), - _compiled_synchronized_native_basic_lock_owner_sp_offset(basic_lock_owner_sp_offset), - _compiled_synchronized_native_basic_lock_sp_offset(basic_lock_sp_offset) + _native_receiver_sp_offset(basic_lock_owner_sp_offset), + _native_basic_lock_sp_offset(basic_lock_sp_offset) { { debug_only(No_Safepoint_Verifier nsv;) @@ -696,8 +696,8 @@ int frame_size) : CodeBlob("dtrace nmethod", code_buffer, sizeof(nmethod), nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, NULL), - _compiled_synchronized_native_basic_lock_owner_sp_offset(in_ByteSize(-1)), - _compiled_synchronized_native_basic_lock_sp_offset(in_ByteSize(-1)) + _native_receiver_sp_offset(in_ByteSize(-1)), + _native_basic_lock_sp_offset(in_ByteSize(-1)) { { debug_only(No_Safepoint_Verifier nsv;) @@ -790,8 +790,8 @@ ) : CodeBlob("nmethod", code_buffer, sizeof(nmethod), nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps), - _compiled_synchronized_native_basic_lock_owner_sp_offset(in_ByteSize(-1)), - _compiled_synchronized_native_basic_lock_sp_offset(in_ByteSize(-1)) + _native_receiver_sp_offset(in_ByteSize(-1)), + _native_basic_lock_sp_offset(in_ByteSize(-1)) { assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR"); { diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/code/nmethod.hpp --- a/src/share/vm/code/nmethod.hpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/code/nmethod.hpp Fri Jan 07 03:58:11 2011 -0800 @@ -210,7 +210,7 @@ ExceptionCache *_exception_cache; PcDescCache _pc_desc_cache; - // These are only used for compiled synchronized native methods to + // These are used for compiled synchronized native methods to // locate the owner and stack slot for the BasicLock so that we can // properly revoke the bias of the owner if necessary. They are // needed because there is no debug information for compiled native @@ -220,8 +220,10 @@ // sharing between platforms. Note that currently biased locking // will never cause Class instances to be biased but this code // handles the static synchronized case as well. - ByteSize _compiled_synchronized_native_basic_lock_owner_sp_offset; - ByteSize _compiled_synchronized_native_basic_lock_sp_offset; + // JVMTI's GetLocalInstance() also uses these offsets to find the receiver + // for non-static native wrapper frames. + ByteSize _native_receiver_sp_offset; + ByteSize _native_basic_lock_sp_offset; friend class nmethodLocker; @@ -676,11 +678,11 @@ bool is_patchable_at(address instr_address); // UseBiasedLocking support - ByteSize compiled_synchronized_native_basic_lock_owner_sp_offset() { - return _compiled_synchronized_native_basic_lock_owner_sp_offset; + ByteSize native_receiver_sp_offset() { + return _native_receiver_sp_offset; } - ByteSize compiled_synchronized_native_basic_lock_sp_offset() { - return _compiled_synchronized_native_basic_lock_sp_offset; + ByteSize native_basic_lock_sp_offset() { + return _native_basic_lock_sp_offset; } // support for code generation diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -1825,23 +1825,11 @@ } } - -class G1CMIsAliveClosure: public BoolObjectClosure { - G1CollectedHeap* _g1; - public: - G1CMIsAliveClosure(G1CollectedHeap* g1) : - _g1(g1) - {} - - void do_object(oop obj) { - assert(false, "not to be invoked"); - } - bool do_object_b(oop obj) { - HeapWord* addr = (HeapWord*)obj; - return addr != NULL && - (!_g1->is_in_g1_reserved(addr) || !_g1->is_obj_ill(obj)); - } -}; +bool G1CMIsAliveClosure::do_object_b(oop obj) { + HeapWord* addr = (HeapWord*)obj; + return addr != NULL && + (!_g1->is_in_g1_reserved(addr) || !_g1->is_obj_ill(obj)); +} class G1CMKeepAliveClosure: public OopClosure { G1CollectedHeap* _g1; @@ -1896,16 +1884,15 @@ rp->setup_policy(clear_all_soft_refs); assert(_markStack.isEmpty(), "mark stack should be empty"); - G1CMIsAliveClosure g1IsAliveClosure (g1h); - G1CMKeepAliveClosure g1KeepAliveClosure(g1h, this, nextMarkBitMap()); + G1CMIsAliveClosure g1_is_alive(g1h); + G1CMKeepAliveClosure g1_keep_alive(g1h, this, nextMarkBitMap()); G1CMDrainMarkingStackClosure - g1DrainMarkingStackClosure(nextMarkBitMap(), &_markStack, - &g1KeepAliveClosure); + g1_drain_mark_stack(nextMarkBitMap(), &_markStack, &g1_keep_alive); // XXXYYY Also: copy the parallel ref processing code from CMS. - rp->process_discovered_references(&g1IsAliveClosure, - &g1KeepAliveClosure, - &g1DrainMarkingStackClosure, + rp->process_discovered_references(&g1_is_alive, + &g1_keep_alive, + &g1_drain_mark_stack, NULL); assert(_markStack.overflow() || _markStack.isEmpty(), "mark stack should be empty (unless it overflowed)"); @@ -1918,8 +1905,8 @@ assert(!rp->discovery_enabled(), "should have been disabled"); // Now clean up stale oops in SymbolTable and StringTable - SymbolTable::unlink(&g1IsAliveClosure); - StringTable::unlink(&g1IsAliveClosure); + SymbolTable::unlink(&g1_is_alive); + StringTable::unlink(&g1_is_alive); } void ConcurrentMark::swapMarkBitMaps() { diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/gc_implementation/g1/concurrentMark.hpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp Fri Jan 07 03:58:11 2011 -0800 @@ -33,6 +33,25 @@ typedef GenericTaskQueue CMTaskQueue; typedef GenericTaskQueueSet CMTaskQueueSet; +// Closure used by CM during concurrent reference discovery +// and reference processing (during remarking) to determine +// if a particular object is alive. It is primarily used +// to determine if referents of discovered reference objects +// are alive. An instance is also embedded into the +// reference processor as the _is_alive_non_header field +class G1CMIsAliveClosure: public BoolObjectClosure { + G1CollectedHeap* _g1; + public: + G1CMIsAliveClosure(G1CollectedHeap* g1) : + _g1(g1) + {} + + void do_object(oop obj) { + ShouldNotCallThis(); + } + bool do_object_b(oop obj); +}; + // A generic CM bit map. This is essentially a wrapper around the BitMap // class, with one bit per (1<<_shifter) HeapWords. diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp --- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -277,7 +277,9 @@ // completed. This will also notify the FullGCCount_lock in case a // Java thread is waiting for a full GC to happen (e.g., it // called System.gc() with +ExplicitGCInvokesConcurrent). - g1->increment_full_collections_completed(true /* outer */); + _sts.join(); + g1->increment_full_collections_completed(true /* concurrent */); + _sts.leave(); } assert(_should_terminate, "just checking"); diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -1192,6 +1192,7 @@ return false; } + DTraceGCProbeMarker gc_probe_marker(true /* full */); ResourceMark rm; if (PrintHeapAtGC) { @@ -1389,7 +1390,7 @@ } // Update the number of full collections that have been completed. - increment_full_collections_completed(false /* outer */); + increment_full_collections_completed(false /* concurrent */); if (PrintHeapAtGC) { Universe::print_heap_after_gc(); @@ -1768,6 +1769,7 @@ _g1_policy(policy_), _dirty_card_queue_set(false), _into_cset_dirty_card_queue_set(false), + _is_alive_closure(this), _ref_processor(NULL), _process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)), _bot_shared(NULL), @@ -2061,7 +2063,8 @@ mr, // span false, // Reference discovery is not atomic true, // mt_discovery - NULL, // is alive closure: need to fill this in for efficiency + &_is_alive_closure, // is alive closure + // for efficiency ParallelGCThreads, ParallelRefProcEnabled, true); // Setting next fields of discovered @@ -2176,9 +2179,14 @@ (cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)); } -void G1CollectedHeap::increment_full_collections_completed(bool outer) { +void G1CollectedHeap::increment_full_collections_completed(bool concurrent) { MonitorLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag); + // We assume that if concurrent == true, then the caller is a + // concurrent thread that was joined the Suspendible Thread + // Set. If there's ever a cheap way to check this, we should add an + // assert here. + // We have already incremented _total_full_collections at the start // of the GC, so total_full_collections() represents how many full // collections have been started. @@ -2192,17 +2200,18 @@ // behind the number of full collections started. // This is the case for the inner caller, i.e. a Full GC. - assert(outer || + assert(concurrent || (full_collections_started == _full_collections_completed + 1) || (full_collections_started == _full_collections_completed + 2), - err_msg("for inner caller: full_collections_started = %u " + err_msg("for inner caller (Full GC): full_collections_started = %u " "is inconsistent with _full_collections_completed = %u", full_collections_started, _full_collections_completed)); // This is the case for the outer caller, i.e. the concurrent cycle. - assert(!outer || + assert(!concurrent || (full_collections_started == _full_collections_completed + 1), - err_msg("for outer caller: full_collections_started = %u " + err_msg("for outer caller (concurrent cycle): " + "full_collections_started = %u " "is inconsistent with _full_collections_completed = %u", full_collections_started, _full_collections_completed)); @@ -2212,7 +2221,7 @@ // we wake up any waiters (especially when ExplicitInvokesConcurrent // is set) so that if a waiter requests another System.gc() it doesn't // incorrectly see that a marking cyle is still in progress. - if (outer) { + if (concurrent) { _cmThread->clear_in_progress(); } @@ -3205,13 +3214,14 @@ return false; } + DTraceGCProbeMarker gc_probe_marker(false /* full */); + ResourceMark rm; + if (PrintHeapAtGC) { Universe::print_heap_before_gc(); } { - ResourceMark rm; - // This call will decide whether this pause is an initial-mark // pause. If it is, during_initial_mark_pause() will return true // for the duration of this pause. @@ -3950,8 +3960,6 @@ // Now restore saved marks, if any. if (_objs_with_preserved_marks != NULL) { assert(_preserved_marks_of_objs != NULL, "Both or none."); - assert(_objs_with_preserved_marks->length() == - _preserved_marks_of_objs->length(), "Both or none."); guarantee(_objs_with_preserved_marks->length() == _preserved_marks_of_objs->length(), "Both or none."); for (int i = 0; i < _objs_with_preserved_marks->length(); i++) { @@ -4046,7 +4054,10 @@ } void G1CollectedHeap::preserve_mark_if_necessary(oop obj, markOop m) { - if (m != markOopDesc::prototype()) { + assert(evacuation_failed(), "Oversaving!"); + // We want to call the "for_promotion_failure" version only in the + // case of a promotion failure. + if (m->must_be_preserved_for_promotion_failure(obj)) { if (_objs_with_preserved_marks == NULL) { assert(_preserved_marks_of_objs == NULL, "Both or none."); _objs_with_preserved_marks = diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Jan 07 03:58:11 2011 -0800 @@ -643,16 +643,16 @@ // can happen in a nested fashion, i.e., we start a concurrent // cycle, a Full GC happens half-way through it which ends first, // and then the cycle notices that a Full GC happened and ends - // too. The outer parameter is a boolean to help us do a bit tighter - // consistency checking in the method. If outer is false, the caller - // is the inner caller in the nesting (i.e., the Full GC). If outer - // is true, the caller is the outer caller in this nesting (i.e., - // the concurrent cycle). Further nesting is not currently - // supported. The end of the this call also notifies the - // FullGCCount_lock in case a Java thread is waiting for a full GC - // to happen (e.g., it called System.gc() with + // too. The concurrent parameter is a boolean to help us do a bit + // tighter consistency checking in the method. If concurrent is + // false, the caller is the inner caller in the nesting (i.e., the + // Full GC). If concurrent is true, the caller is the outer caller + // in this nesting (i.e., the concurrent cycle). Further nesting is + // not currently supported. The end of the this call also notifies + // the FullGCCount_lock in case a Java thread is waiting for a full + // GC to happen (e.g., it called System.gc() with // +ExplicitGCInvokesConcurrent). - void increment_full_collections_completed(bool outer); + void increment_full_collections_completed(bool concurrent); unsigned int full_collections_completed() { return _full_collections_completed; @@ -849,6 +849,12 @@ void print_gc_alloc_regions(); #endif // !PRODUCT + // Instance of the concurrent mark is_alive closure for embedding + // into the reference processor as the is_alive_non_header. This + // prevents unnecessary additions to the discovered lists during + // concurrent discovery. + G1CMIsAliveClosure _is_alive_closure; + // ("Weak") Reference processing support ReferenceProcessor* _ref_processor; @@ -893,7 +899,7 @@ // specified by the policy object. jint initialize(); - void ref_processing_init(); + virtual void ref_processing_init(); void set_par_threads(int t) { SharedHeap::set_par_threads(t); diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/gc_implementation/parNew/parNewGeneration.cpp --- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -1058,10 +1058,11 @@ #endif void ParNewGeneration::preserve_mark_if_necessary(oop obj, markOop m) { - if ((m != markOopDesc::prototype()) && - (!UseBiasedLocking || (m != markOopDesc::biased_locking_prototype()))) { + if (m->must_be_preserved_for_promotion_failure(obj)) { + // We should really have separate per-worker stacks, rather + // than use locking of a common pair of stacks. MutexLocker ml(ParGCRareEvent_lock); - DefNewGeneration::preserve_mark_if_necessary(obj, m); + preserve_mark(obj, m); } } diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -694,6 +694,8 @@ void PSScavenge::oop_promotion_failed(oop obj, markOop obj_mark) { _promotion_failed = true; if (obj_mark->must_be_preserved_for_promotion_failure(obj)) { + // Should use per-worker private stakcs hetre rather than + // locking a common pair of stacks. ThreadCritical tc; _preserved_oop_stack.push(obj); _preserved_mark_stack.push(obj_mark); diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/gc_implementation/shared/vmGCOperations.hpp --- a/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Fri Jan 07 03:58:11 2011 -0800 @@ -209,4 +209,15 @@ HeapWord* result() const { return _res; } }; +class DTraceGCProbeMarker : public StackObj { +public: + DTraceGCProbeMarker(bool full) { + VM_GC_Operation::notify_gc_begin(full); + } + + ~DTraceGCProbeMarker() { + VM_GC_Operation::notify_gc_end(); + } +}; + #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_VMGCOPERATIONS_HPP diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/memory/defNewGeneration.cpp --- a/src/share/vm/memory/defNewGeneration.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/memory/defNewGeneration.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -684,23 +684,28 @@ _preserved_marks_of_objs.clear(true); } +void DefNewGeneration::preserve_mark(oop obj, markOop m) { + assert(promotion_failed() && m->must_be_preserved_for_promotion_failure(obj), + "Oversaving!"); + _objs_with_preserved_marks.push(obj); + _preserved_marks_of_objs.push(m); +} + void DefNewGeneration::preserve_mark_if_necessary(oop obj, markOop m) { if (m->must_be_preserved_for_promotion_failure(obj)) { - _objs_with_preserved_marks.push(obj); - _preserved_marks_of_objs.push(m); + preserve_mark(obj, m); } } void DefNewGeneration::handle_promotion_failure(oop old) { - preserve_mark_if_necessary(old, old->mark()); - if (!_promotion_failed && PrintPromotionFailure) { + if (PrintPromotionFailure && !_promotion_failed) { gclog_or_tty->print(" (promotion failure size = " SIZE_FORMAT ") ", old->size()); } - + _promotion_failed = true; + preserve_mark_if_necessary(old, old->mark()); // forward to self old->forward_to(old); - _promotion_failed = true; _promo_failure_scan_stack.push(old); diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/memory/defNewGeneration.hpp --- a/src/share/vm/memory/defNewGeneration.hpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/memory/defNewGeneration.hpp Fri Jan 07 03:58:11 2011 -0800 @@ -85,6 +85,7 @@ // Preserve the mark of "obj", if necessary, in preparation for its mark // word being overwritten with a self-forwarding-pointer. void preserve_mark_if_necessary(oop obj, markOop m); + void preserve_mark(oop obj, markOop m); // work routine used by the above // Together, these keep pairs. // They should always contain the same number of elements. diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/oops/instanceRefKlass.cpp --- a/src/share/vm/oops/instanceRefKlass.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/oops/instanceRefKlass.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -457,6 +457,12 @@ } } +bool instanceRefKlass::owns_pending_list_lock(JavaThread* thread) { + if (java_lang_ref_Reference::pending_list_lock() == NULL) return false; + Handle h_lock(thread, java_lang_ref_Reference::pending_list_lock()); + return ObjectSynchronizer::current_thread_holds_lock(thread, h_lock); +} + void instanceRefKlass::acquire_pending_list_lock(BasicLock *pending_list_basic_lock) { // we may enter this with pending exception set PRESERVE_EXCEPTION_MARK; // exceptions are never thrown, needed for TRAPS argument diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/oops/instanceRefKlass.hpp --- a/src/share/vm/oops/instanceRefKlass.hpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/oops/instanceRefKlass.hpp Fri Jan 07 03:58:11 2011 -0800 @@ -89,6 +89,7 @@ static void release_and_notify_pending_list_lock(BasicLock *pending_list_basic_lock); static void acquire_pending_list_lock(BasicLock *pending_list_basic_lock); + static bool owns_pending_list_lock(JavaThread* thread); // Update non-static oop maps so 'referent', 'nextPending' and // 'discovered' will look like non-oops diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/oops/klassVtable.cpp --- a/src/share/vm/oops/klassVtable.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/oops/klassVtable.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -518,18 +518,21 @@ bool klassVtable::is_miranda(methodOop m, objArrayOop class_methods, klassOop super) { symbolOop name = m->name(); symbolOop signature = m->signature(); + if (instanceKlass::find_method(class_methods, name, signature) == NULL) { - // did not find it in the method table of the current class + // did not find it in the method table of the current class if (super == NULL) { // super doesn't exist return true; - } else { - if (instanceKlass::cast(super)->lookup_method(name, signature) == NULL) { - // super class hierarchy does not implement it - return true; - } + } + + methodOop mo = instanceKlass::cast(super)->lookup_method(name, signature); + if (mo == NULL || mo->access_flags().is_private() ) { + // super class hierarchy does not implement it or protection is different + return true; } } + return false; } diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/oops/markOop.inline.hpp --- a/src/share/vm/oops/markOop.inline.hpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/oops/markOop.inline.hpp Fri Jan 07 03:58:11 2011 -0800 @@ -30,7 +30,7 @@ #include "oops/markOop.hpp" #include "runtime/globals.hpp" -// Should this header be preserved during GC? +// Should this header be preserved during GC (when biased locking is enabled)? inline bool markOopDesc::must_be_preserved_with_bias(oop obj_containing_mark) const { assert(UseBiasedLocking, "unexpected"); if (has_bias_pattern()) { @@ -47,14 +47,15 @@ return (!is_unlocked() || !has_no_hash()); } +// Should this header be preserved during GC? inline bool markOopDesc::must_be_preserved(oop obj_containing_mark) const { if (!UseBiasedLocking) return (!is_unlocked() || !has_no_hash()); return must_be_preserved_with_bias(obj_containing_mark); } -// Should this header (including its age bits) be preserved in the -// case of a promotion failure during scavenge? +// Should this header be preserved in the case of a promotion failure +// during scavenge (when biased locking is enabled)? inline bool markOopDesc::must_be_preserved_with_bias_for_promotion_failure(oop obj_containing_mark) const { assert(UseBiasedLocking, "unexpected"); // We don't explicitly save off the mark words of biased and @@ -70,18 +71,20 @@ prototype_for_object(obj_containing_mark)->has_bias_pattern()) { return true; } - return (this != prototype()); + return (!is_unlocked() || !has_no_hash()); } +// Should this header be preserved in the case of a promotion failure +// during scavenge? inline bool markOopDesc::must_be_preserved_for_promotion_failure(oop obj_containing_mark) const { if (!UseBiasedLocking) - return (this != prototype()); + return (!is_unlocked() || !has_no_hash()); return must_be_preserved_with_bias_for_promotion_failure(obj_containing_mark); } -// Should this header (including its age bits) be preserved in the -// case of a scavenge in which CMS is the old generation? +// Same as must_be_preserved_with_bias_for_promotion_failure() except that +// it takes a klassOop argument, instead of the object of which this is the mark word. inline bool markOopDesc::must_be_preserved_with_bias_for_cms_scavenge(klassOop klass_of_obj_containing_mark) const { assert(UseBiasedLocking, "unexpected"); // CMS scavenges preserve mark words in similar fashion to promotion failures; see above @@ -89,11 +92,14 @@ klass_of_obj_containing_mark->klass_part()->prototype_header()->has_bias_pattern()) { return true; } - return (this != prototype()); + return (!is_unlocked() || !has_no_hash()); } + +// Same as must_be_preserved_for_promotion_failure() except that +// it takes a klassOop argument, instead of the object of which this is the mark word. inline bool markOopDesc::must_be_preserved_for_cms_scavenge(klassOop klass_of_obj_containing_mark) const { if (!UseBiasedLocking) - return (this != prototype()); + return (!is_unlocked() || !has_no_hash()); return must_be_preserved_with_bias_for_cms_scavenge(klass_of_obj_containing_mark); } diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/oops/methodOop.cpp --- a/src/share/vm/oops/methodOop.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/oops/methodOop.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -309,6 +309,12 @@ // Build a methodDataOop object to hold information about this method // collected in the interpreter. void methodOopDesc::build_interpreter_method_data(methodHandle method, TRAPS) { + // Do not profile method if current thread holds the pending list lock, + // which avoids deadlock for acquiring the MethodData_lock. + if (instanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) { + return; + } + // Grab a lock here to prevent multiple // methodDataOops from being created. MutexLocker ml(MethodData_lock, THREAD); diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/prims/jvmti.xml --- a/src/share/vm/prims/jvmti.xml Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/prims/jvmti.xml Fri Jan 07 03:58:11 2011 -0800 @@ -5649,6 +5649,45 @@ + + Get Local Instance + + This function can be used to retrieve the value of the local object + variable at slot 0 (the "this" object) from non-static + frames. This function can retrieve the "this" object from + native method frames, whereas GetLocalObject() would + return JVMTI_ERROR_OPAQUE_FRAME in those cases. + + new + + + + + + + + The thread of the frame containing the variable's value. + + + + + + The depth of the frame containing the variable's value. + + + + + + On return, points to the variable's value. + + + + + + If the specified frame is a static method frame. + + + Get Local Variable - Int diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/prims/jvmtiEnv.cpp --- a/src/share/vm/prims/jvmtiEnv.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/prims/jvmtiEnv.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -1796,6 +1796,29 @@ } } /* end GetLocalObject */ +// Threads_lock NOT held, java_thread not protected by lock +// java_thread - pre-checked +// java_thread - unchecked +// depth - pre-checked as non-negative +// value - pre-checked for NULL +jvmtiError +JvmtiEnv::GetLocalInstance(JavaThread* java_thread, jint depth, jobject* value){ + JavaThread* current_thread = JavaThread::current(); + // rm object is created to clean up the javaVFrame created in + // doit_prologue(), but after doit() is finished with it. + ResourceMark rm(current_thread); + + VM_GetReceiver op(java_thread, current_thread, depth); + VMThread::execute(&op); + jvmtiError err = op.result(); + if (err != JVMTI_ERROR_NONE) { + return err; + } else { + *value = op.value().l; + return JVMTI_ERROR_NONE; + } +} /* end GetLocalInstance */ + // Threads_lock NOT held, java_thread not protected by lock // java_thread - pre-checked diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/prims/jvmtiImpl.cpp --- a/src/share/vm/prims/jvmtiImpl.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/prims/jvmtiImpl.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -586,7 +586,6 @@ { } - vframe *VM_GetOrSetLocal::get_vframe() { if (!_thread->has_last_Java_frame()) { return NULL; @@ -609,7 +608,7 @@ } javaVFrame *jvf = (javaVFrame*)vf; - if (!vf->is_java_frame() || jvf->method()->is_native()) { + if (!vf->is_java_frame()) { _result = JVMTI_ERROR_OPAQUE_FRAME; return NULL; } @@ -740,6 +739,15 @@ _jvf = get_java_vframe(); NULL_CHECK(_jvf, false); + if (_jvf->method()->is_native()) { + if (getting_receiver() && !_jvf->method()->is_static()) { + return true; + } else { + _result = JVMTI_ERROR_OPAQUE_FRAME; + return false; + } + } + if (!check_slot_type(_jvf)) { return false; } @@ -781,40 +789,46 @@ HandleMark hm; switch (_type) { - case T_INT: locals->set_int_at (_index, _value.i); break; - case T_LONG: locals->set_long_at (_index, _value.j); break; - case T_FLOAT: locals->set_float_at (_index, _value.f); break; - case T_DOUBLE: locals->set_double_at(_index, _value.d); break; - case T_OBJECT: { - Handle ob_h(JNIHandles::resolve_external_guard(_value.l)); - locals->set_obj_at (_index, ob_h); - break; - } - default: ShouldNotReachHere(); + case T_INT: locals->set_int_at (_index, _value.i); break; + case T_LONG: locals->set_long_at (_index, _value.j); break; + case T_FLOAT: locals->set_float_at (_index, _value.f); break; + case T_DOUBLE: locals->set_double_at(_index, _value.d); break; + case T_OBJECT: { + Handle ob_h(JNIHandles::resolve_external_guard(_value.l)); + locals->set_obj_at (_index, ob_h); + break; + } + default: ShouldNotReachHere(); } _jvf->set_locals(locals); } else { - StackValueCollection *locals = _jvf->locals(); + if (_jvf->method()->is_native() && _jvf->is_compiled_frame()) { + assert(getting_receiver(), "Can only get here when getting receiver"); + oop receiver = _jvf->fr().get_native_receiver(); + _value.l = JNIHandles::make_local(_calling_thread, receiver); + } else { + StackValueCollection *locals = _jvf->locals(); - if (locals->at(_index)->type() == T_CONFLICT) { - memset(&_value, 0, sizeof(_value)); - _value.l = NULL; - return; - } + if (locals->at(_index)->type() == T_CONFLICT) { + memset(&_value, 0, sizeof(_value)); + _value.l = NULL; + return; + } - switch (_type) { - case T_INT: _value.i = locals->int_at (_index); break; - case T_LONG: _value.j = locals->long_at (_index); break; - case T_FLOAT: _value.f = locals->float_at (_index); break; - case T_DOUBLE: _value.d = locals->double_at(_index); break; - case T_OBJECT: { - // Wrap the oop to be returned in a local JNI handle since - // oops_do() no longer applies after doit() is finished. - oop obj = locals->obj_at(_index)(); - _value.l = JNIHandles::make_local(_calling_thread, obj); - break; - } - default: ShouldNotReachHere(); + switch (_type) { + case T_INT: _value.i = locals->int_at (_index); break; + case T_LONG: _value.j = locals->long_at (_index); break; + case T_FLOAT: _value.f = locals->float_at (_index); break; + case T_DOUBLE: _value.d = locals->double_at(_index); break; + case T_OBJECT: { + // Wrap the oop to be returned in a local JNI handle since + // oops_do() no longer applies after doit() is finished. + oop obj = locals->obj_at(_index)(); + _value.l = JNIHandles::make_local(_calling_thread, obj); + break; + } + default: ShouldNotReachHere(); + } } } } @@ -825,6 +839,10 @@ } +VM_GetReceiver::VM_GetReceiver( + JavaThread* thread, JavaThread* caller_thread, jint depth) + : VM_GetOrSetLocal(thread, caller_thread, depth, 0) {} + ///////////////////////////////////////////////////////////////////////////////////////// // diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/prims/jvmtiImpl.hpp --- a/src/share/vm/prims/jvmtiImpl.hpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/prims/jvmtiImpl.hpp Fri Jan 07 03:58:11 2011 -0800 @@ -355,7 +355,7 @@ // to the thread simultaneously. // class VM_GetOrSetLocal : public VM_Operation { -private: + protected: JavaThread* _thread; JavaThread* _calling_thread; jint _depth; @@ -365,6 +365,10 @@ javaVFrame* _jvf; bool _set; + // It is possible to get the receiver out of a non-static native wrapper + // frame. Use VM_GetReceiver to do this. + virtual bool getting_receiver() const { return false; } + jvmtiError _result; vframe* get_vframe(); @@ -395,6 +399,15 @@ static bool is_assignable(const char* ty_sign, Klass* klass, Thread* thread); }; +class VM_GetReceiver : public VM_GetOrSetLocal { + protected: + virtual bool getting_receiver() const { return true; } + + public: + VM_GetReceiver(JavaThread* thread, JavaThread* calling_thread, jint depth); + const char* name() const { return "get receiver"; } +}; + /////////////////////////////////////////////////////////////// // diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/runtime/frame.cpp --- a/src/share/vm/runtime/frame.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/runtime/frame.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -41,6 +41,8 @@ #include "runtime/signature.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" +#include "utilities/decoder.hpp" + #ifdef TARGET_ARCH_x86 # include "nativeInst_x86.hpp" #endif @@ -652,7 +654,7 @@ // names if pc is within jvm.dll or libjvm.so, because JVM only has // JVM_xxxx and a few other symbols in the dynamic symbol table. Do this // only for native libraries. - if (!in_vm) { + if (!in_vm || Decoder::can_decode_C_frame_in_vm()) { found = os::dll_address_to_function_name(pc, buf, buflen, &offset); if (found) { @@ -1071,28 +1073,20 @@ } } -BasicLock* frame::compiled_synchronized_native_monitor(nmethod* nm) { - if (nm == NULL) { - assert(_cb != NULL && _cb->is_nmethod() && - nm->method()->is_native() && - nm->method()->is_synchronized(), - "should not call this otherwise"); - nm = (nmethod*) _cb; - } - int byte_offset = in_bytes(nm->compiled_synchronized_native_basic_lock_sp_offset()); +BasicLock* frame::get_native_monitor() { + nmethod* nm = (nmethod*)_cb; + assert(_cb != NULL && _cb->is_nmethod() && nm->method()->is_native(), + "Should not call this unless it's a native nmethod"); + int byte_offset = in_bytes(nm->native_basic_lock_sp_offset()); assert(byte_offset >= 0, "should not see invalid offset"); return (BasicLock*) &sp()[byte_offset / wordSize]; } -oop frame::compiled_synchronized_native_monitor_owner(nmethod* nm) { - if (nm == NULL) { - assert(_cb != NULL && _cb->is_nmethod() && - nm->method()->is_native() && - nm->method()->is_synchronized(), - "should not call this otherwise"); - nm = (nmethod*) _cb; - } - int byte_offset = in_bytes(nm->compiled_synchronized_native_basic_lock_owner_sp_offset()); +oop frame::get_native_receiver() { + nmethod* nm = (nmethod*)_cb; + assert(_cb != NULL && _cb->is_nmethod() && nm->method()->is_native(), + "Should not call this unless it's a native nmethod"); + int byte_offset = in_bytes(nm->native_receiver_sp_offset()); assert(byte_offset >= 0, "should not see invalid offset"); oop owner = ((oop*) sp())[byte_offset / wordSize]; assert( Universe::heap()->is_in(owner), "bad receiver" ); diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/runtime/frame.hpp --- a/src/share/vm/runtime/frame.hpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/runtime/frame.hpp Fri Jan 07 03:58:11 2011 -0800 @@ -254,10 +254,10 @@ // Return the monitor owner and BasicLock for compiled synchronized // native methods so that biased locking can revoke the receiver's - // bias if necessary. Takes optional nmethod for this frame as - // argument to avoid performing repeated lookups in code cache. - BasicLock* compiled_synchronized_native_monitor (nmethod* nm = NULL); - oop compiled_synchronized_native_monitor_owner(nmethod* nm = NULL); + // bias if necessary. This is also used by JVMTI's GetLocalInstance method + // (via VM_GetReceiver) to retrieve the receiver from a native wrapper frame. + BasicLock* get_native_monitor(); + oop get_native_receiver(); // Find receiver for an invoke when arguments are just pushed on stack (i.e., callee stack-frame is // not setup) diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/runtime/vframe_hp.cpp --- a/src/share/vm/runtime/vframe_hp.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/runtime/vframe_hp.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -207,8 +207,8 @@ GrowableArray *monitors = new GrowableArray(1); // Casting away const frame& fr = (frame&) _fr; - MonitorInfo* info = new MonitorInfo(fr.compiled_synchronized_native_monitor_owner(nm), - fr.compiled_synchronized_native_monitor(nm), false, false); + MonitorInfo* info = new MonitorInfo( + fr.get_native_receiver(), fr.get_native_monitor(), false, false); monitors->push(info); return monitors; } diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/utilities/decoder.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/utilities/decoder.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 1997, 2010, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "prims/jvm.h" +#include "utilities/decoder.hpp" + +Decoder::decoder_status Decoder::_decoder_status = Decoder::no_error; +bool Decoder::_initialized = false; + +#ifndef _WINDOWS + +// Implementation of common functionalities among Solaris and Linux +#include "utilities/elfFile.hpp" + +ElfFile* Decoder::_opened_elf_files = NULL; + +bool Decoder::can_decode_C_frame_in_vm() { + return true; +} + +void Decoder::initialize() { + _initialized = true; +} + +void Decoder::uninitialize() { + if (_opened_elf_files != NULL) { + delete _opened_elf_files; + _opened_elf_files = NULL; + } + _initialized = false; +} + +Decoder::decoder_status Decoder::decode(address addr, const char* filepath, char *buf, int buflen, int *offset) { + if (_decoder_status != no_error) { + return _decoder_status; + } + + ElfFile* file = get_elf_file(filepath); + if (_decoder_status != no_error) { + return _decoder_status; + } + + const char* symbol = file->decode(addr, offset); + if (file->get_status() == out_of_memory) { + _decoder_status = out_of_memory; + return _decoder_status; + } else if (symbol != NULL) { + if (!demangle(symbol, buf, buflen)) { + jio_snprintf(buf, buflen, "%s", symbol); + } + return no_error; + } else { + return symbol_not_found; + } +} + +ElfFile* Decoder::get_elf_file(const char* filepath) { + if (_decoder_status != no_error) { + return NULL; + } + ElfFile* file = _opened_elf_files; + while (file != NULL) { + if (file->same_elf_file(filepath)) { + return file; + } + file = file->m_next; + } + + file = new ElfFile(filepath); + if (file == NULL) { + _decoder_status = out_of_memory; + } + if (_opened_elf_files != NULL) { + file->m_next = _opened_elf_files; + } + + _opened_elf_files = file; + return file; +} + +#endif + diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/utilities/decoder.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/utilities/decoder.hpp Fri Jan 07 03:58:11 2011 -0800 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1997, 2010, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + + +#ifndef __DECODER_HPP +#define __DECODER_HPP + +#include "memory/allocation.hpp" + +#ifdef _WINDOWS +#include +#include + +// functions needed for decoding symbols +typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD); +typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL); +typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64); +typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD); + +#else + +class ElfFile; + +#endif // _WINDOWS + + +class Decoder: public StackObj { + + public: + // status code for decoding native C frame + enum decoder_status { + no_error, // successfully decoded frames + out_of_memory, // out of memory + file_invalid, // invalid elf file + file_not_found, // could not found symbol file (on windows), such as jvm.pdb or jvm.map + helper_not_found, // could not load dbghelp.dll (Windows only) + helper_func_error, // decoding functions not found (Windows only) + helper_init_error, // SymInitialize failed (Windows only) + symbol_not_found // could not find the symbol + }; + + public: + Decoder() { initialize(); }; + ~Decoder() { uninitialize(); }; + + static bool can_decode_C_frame_in_vm(); + + static void initialize(); + static void uninitialize(); + +#ifdef _WINDOWS + static decoder_status decode(address addr, char *buf, int buflen, int *offset); +#else + static decoder_status decode(address addr, const char* filepath, char *buf, int buflen, int *offset); +#endif + + static bool demangle(const char* symbol, char *buf, int buflen); + + static decoder_status get_status() { return _decoder_status; }; + +#ifndef _WINDOWS + private: + static ElfFile* get_elf_file(const char* filepath); +#endif // _WINDOWS + + + private: + static decoder_status _decoder_status; + static bool _initialized; + +#ifdef _WINDOWS + static HMODULE _dbghelp_handle; + static bool _can_decode_in_vm; + static pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64; + static pfn_UndecorateSymbolName _pfnUndecorateSymbolName; +#else + static ElfFile* _opened_elf_files; +#endif // _WINDOWS +}; + +#endif // __DECODER_HPP diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/utilities/elfFile.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/utilities/elfFile.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -0,0 +1,198 @@ +/* + * Copyright (c) 1997, 2010, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" + +#ifndef _WINDOWS + +#include +#include +#include + +#include "memory/allocation.inline.hpp" +#include "utilities/decoder.hpp" +#include "utilities/elfFile.hpp" +#include "utilities/elfStringTable.hpp" +#include "utilities/elfSymbolTable.hpp" + + +ElfFile::ElfFile(const char* filepath) { + assert(filepath, "null file path"); + memset(&m_elfHdr, 0, sizeof(m_elfHdr)); + m_string_tables = NULL; + m_symbol_tables = NULL; + m_next = NULL; + m_status = Decoder::no_error; + + int len = strlen(filepath) + 1; + m_filepath = NEW_C_HEAP_ARRAY(char, len); + if (m_filepath != NULL) { + strcpy((char*)m_filepath, filepath); + m_file = fopen(filepath, "r"); + if (m_file != NULL) { + load_tables(); + } else { + m_status = Decoder::file_not_found; + } + } else { + m_status = Decoder::out_of_memory; + } +} + +ElfFile::~ElfFile() { + if (m_string_tables != NULL) { + delete m_string_tables; + } + + if (m_symbol_tables != NULL) { + delete m_symbol_tables; + } + + if (m_file != NULL) { + fclose(m_file); + } + + if (m_filepath != NULL) { + FREE_C_HEAP_ARRAY(char, m_filepath); + } + + if (m_next != NULL) { + delete m_next; + } +}; + + +//Check elf header to ensure the file is valid. +bool ElfFile::is_elf_file(Elf_Ehdr& hdr) { + return (ELFMAG0 == hdr.e_ident[EI_MAG0] && + ELFMAG1 == hdr.e_ident[EI_MAG1] && + ELFMAG2 == hdr.e_ident[EI_MAG2] && + ELFMAG3 == hdr.e_ident[EI_MAG3] && + ELFCLASSNONE != hdr.e_ident[EI_CLASS] && + ELFDATANONE != hdr.e_ident[EI_DATA]); +} + +bool ElfFile::load_tables() { + assert(m_file, "file not open"); + assert(m_status == Decoder::no_error, "already in error"); + + // read elf file header + if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) { + m_status = Decoder::file_invalid; + return false; + } + + if (!is_elf_file(m_elfHdr)) { + m_status = Decoder::file_invalid; + return false; + } + + // walk elf file's section headers, and load string tables + Elf_Shdr shdr; + if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) { + if (m_status != Decoder::no_error) return false; + + for (int index = 0; index < m_elfHdr.e_shnum; index ++) { + if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) { + m_status = Decoder::file_invalid; + return false; + } + // string table + if (shdr.sh_type == SHT_STRTAB) { + ElfStringTable* table = new ElfStringTable(m_file, shdr, index); + if (table == NULL) { + m_status = Decoder::out_of_memory; + return false; + } + add_string_table(table); + } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { + ElfSymbolTable* table = new ElfSymbolTable(m_file, shdr); + if (table == NULL) { + m_status = Decoder::out_of_memory; + return false; + } + add_symbol_table(table); + } + } + } + return true; +} + +const char* ElfFile::decode(address addr, int* offset) { + // something already went wrong, just give up + if (m_status != Decoder::no_error) { + return NULL; + } + + ElfSymbolTable* symbol_table = m_symbol_tables; + int string_table_index; + int pos_in_string_table; + int off = INT_MAX; + bool found_symbol = false; + while (symbol_table != NULL) { + if (Decoder::no_error == symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) { + found_symbol = true; + } + symbol_table = symbol_table->m_next; + } + if (!found_symbol) return NULL; + + ElfStringTable* string_table = get_string_table(string_table_index); + if (string_table == NULL) { + m_status = Decoder::file_invalid; + return NULL; + } + if (offset) *offset = off; + return string_table->string_at(pos_in_string_table); +} + + +void ElfFile::add_symbol_table(ElfSymbolTable* table) { + if (m_symbol_tables == NULL) { + m_symbol_tables = table; + } else { + table->m_next = m_symbol_tables; + m_symbol_tables = table; + } +} + +void ElfFile::add_string_table(ElfStringTable* table) { + if (m_string_tables == NULL) { + m_string_tables = table; + } else { + table->m_next = m_string_tables; + m_string_tables = table; + } +} + +ElfStringTable* ElfFile::get_string_table(int index) { + ElfStringTable* p = m_string_tables; + while (p != NULL) { + if (p->index() == index) return p; + p = p->m_next; + } + return NULL; +} + +#endif // _WINDOWS diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/utilities/elfFile.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/utilities/elfFile.hpp Fri Jan 07 03:58:11 2011 -0800 @@ -0,0 +1,140 @@ +/* + * Copyright (c) 1997, 2010, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef __ELF_FILE_HPP +#define __ELF_FILE_HPP + +#ifndef _WINDOWS + +#include +#include + +#ifdef _LP64 + +typedef Elf64_Half Elf_Half; +typedef Elf64_Word Elf_Word; +typedef Elf64_Off Elf_Off; +typedef Elf64_Addr Elf_Addr; + +typedef Elf64_Ehdr Elf_Ehdr; +typedef Elf64_Shdr Elf_Shdr; +typedef Elf64_Sym Elf_Sym; + +#define ELF_ST_TYPE ELF64_ST_TYPE + +#else + +typedef Elf32_Half Elf_Half; +typedef Elf32_Word Elf_Word; +typedef Elf32_Off Elf_Off; +typedef Elf32_Addr Elf_Addr; + + +typedef Elf32_Ehdr Elf_Ehdr; +typedef Elf32_Shdr Elf_Shdr; +typedef Elf32_Sym Elf_Sym; + +#define ELF_ST_TYPE ELF32_ST_TYPE +#endif + +#include "globalDefinitions.hpp" +#include "memory/allocation.hpp" +#include "utilities/decoder.hpp" + + +class ElfStringTable; +class ElfSymbolTable; + + +// On Solaris/Linux platforms, libjvm.so does contain all private symbols. +// ElfFile is basically an elf file parser, which can lookup the symbol +// that is the nearest to the given address. +// Beware, this code is called from vm error reporting code, when vm is already +// in "error" state, so there are scenarios, lookup will fail. We want this +// part of code to be very defensive, and bait out if anything went wrong. + +class ElfFile: public CHeapObj { + friend class Decoder; + public: + ElfFile(const char* filepath); + ~ElfFile(); + + const char* decode(address addr, int* offset); + const char* filepath() { + return m_filepath; + } + + bool same_elf_file(const char* filepath) { + assert(filepath, "null file path"); + assert(m_filepath, "already out of memory"); + return (m_filepath && !strcmp(filepath, m_filepath)); + } + + Decoder::decoder_status get_status() { + return m_status; + } + + private: + // sanity check, if the file is a real elf file + bool is_elf_file(Elf_Ehdr&); + + // load string tables from the elf file + bool load_tables(); + + // string tables are stored in a linked list + void add_string_table(ElfStringTable* table); + + // symbol tables are stored in a linked list + void add_symbol_table(ElfSymbolTable* table); + + // return a string table at specified section index + ElfStringTable* get_string_table(int index); + + // look up an address and return the nearest symbol + const char* look_up(Elf_Shdr shdr, address addr, int* offset); + + protected: + ElfFile* m_next; + + private: + // file + const char* m_filepath; + FILE* m_file; + + // Elf header + Elf_Ehdr m_elfHdr; + + // symbol tables + ElfSymbolTable* m_symbol_tables; + + // string tables + ElfStringTable* m_string_tables; + + Decoder::decoder_status m_status; +}; + +#endif // _WINDOWS + +#endif // __ELF_FILE_HPP + diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/utilities/elfStringTable.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/utilities/elfStringTable.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1997, 2010, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" + +#ifndef _WINDOWS + +#include "memory/allocation.inline.hpp" +#include "utilities/elfStringTable.hpp" + +// We will try to load whole string table into memory if we can. +// Otherwise, fallback to more expensive file operation. +ElfStringTable::ElfStringTable(FILE* file, Elf_Shdr shdr, int index) { + assert(file, "null file handle"); + m_table = NULL; + m_index = index; + m_next = NULL; + m_file = file; + m_status = Decoder::no_error; + + // try to load the string table + long cur_offset = ftell(file); + m_table = (char*)NEW_C_HEAP_ARRAY(char, shdr.sh_size); + if (m_table != NULL) { + // if there is an error, mark the error + if (fseek(file, shdr.sh_offset, SEEK_SET) || + fread((void*)m_table, shdr.sh_size, 1, file) != 1 || + fseek(file, cur_offset, SEEK_SET)) { + m_status = Decoder::file_invalid; + FREE_C_HEAP_ARRAY(char, m_table); + m_table = NULL; + } + } else { + memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr)); + } +} + +ElfStringTable::~ElfStringTable() { + if (m_table != NULL) { + FREE_C_HEAP_ARRAY(char, m_table); + } + + if (m_next != NULL) { + delete m_next; + } +} + +const char* ElfStringTable::string_at(int pos) { + if (m_status != Decoder::no_error) { + return NULL; + } + if (m_table != NULL) { + return (const char*)(m_table + pos); + } else { + long cur_pos = ftell(m_file); + if (cur_pos == -1 || + fseek(m_file, m_shdr.sh_offset + pos, SEEK_SET) || + fread(m_symbol, 1, MAX_SYMBOL_LEN, m_file) <= 0 || + fseek(m_file, cur_pos, SEEK_SET)) { + m_status = Decoder::file_invalid; + return NULL; + } + return (const char*)m_symbol; + } +} + +#endif // _WINDOWS + diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/utilities/elfStringTable.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/utilities/elfStringTable.hpp Fri Jan 07 03:58:11 2011 -0800 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1997, 2010, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef __ELF_STRING_TABLE_HPP +#define __ELF_STRING_TABLE_HPP + +#ifndef _WINDOWS + +#include "memory/allocation.hpp" +#include "utilities/decoder.hpp" +#include "utilities/elfFile.hpp" + + +// The string table represents a string table section in an elf file. +// Whenever there is enough memory, it will load whole string table as +// one blob. Otherwise, it will load string from file when requested. + +#define MAX_SYMBOL_LEN 256 + +class ElfStringTable: CHeapObj { + friend class ElfFile; + public: + ElfStringTable(FILE* file, Elf_Shdr shdr, int index); + ~ElfStringTable(); + + // section index + int index() { return m_index; }; + + // get string at specified offset + const char* string_at(int offset); + + // get status code + Decoder::decoder_status get_status() { return m_status; }; + + protected: + ElfStringTable* m_next; + + // section index + int m_index; + + // holds complete string table if can + // allocate enough memory + const char* m_table; + + // file contains string table + FILE* m_file; + + // section header + Elf_Shdr m_shdr; + + // buffer for reading individual string + char m_symbol[MAX_SYMBOL_LEN]; + + // error code + Decoder::decoder_status m_status; +}; + +#endif // _WINDOWS + +#endif // __ELF_STRING_TABLE_HPP + diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/utilities/elfSymbolTable.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/utilities/elfSymbolTable.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -0,0 +1,125 @@ +/* + * Copyright (c) 1997, 2010, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" + +#ifndef _WINDOWS + +#include "memory/allocation.inline.hpp" +#include "utilities/elfSymbolTable.hpp" + +ElfSymbolTable::ElfSymbolTable(FILE* file, Elf_Shdr shdr) { + assert(file, "null file handle"); + m_symbols = NULL; + m_next = NULL; + m_file = file; + m_status = Decoder::no_error; + + // try to load the string table + long cur_offset = ftell(file); + if (cur_offset != -1) { + m_symbols = (Elf_Sym*)NEW_C_HEAP_ARRAY(char, shdr.sh_size); + if (m_symbols) { + if (fseek(file, shdr.sh_offset, SEEK_SET) || + fread((void*)m_symbols, shdr.sh_size, 1, file) != 1 || + fseek(file, cur_offset, SEEK_SET)) { + m_status = Decoder::file_invalid; + FREE_C_HEAP_ARRAY(char, m_symbols); + m_symbols = NULL; + } + } + if (m_status == Decoder::no_error) { + memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr)); + } + } else { + m_status = Decoder::file_invalid; + } +} + +ElfSymbolTable::~ElfSymbolTable() { + if (m_symbols != NULL) { + FREE_C_HEAP_ARRAY(char, m_symbols); + } + + if (m_next != NULL) { + delete m_next; + } +} + +Decoder::decoder_status ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset) { + assert(stringtableIndex, "null string table index pointer"); + assert(posIndex, "null string table offset pointer"); + assert(offset, "null offset pointer"); + + if (m_status != Decoder::no_error) { + return m_status; + } + + address pc = 0; + size_t sym_size = sizeof(Elf_Sym); + assert((m_shdr.sh_size % sym_size) == 0, "check size"); + int count = m_shdr.sh_size / sym_size; + if (m_symbols != NULL) { + for (int index = 0; index < count; index ++) { + if (STT_FUNC == ELF_ST_TYPE(m_symbols[index].st_info)) { + address sym_addr = (address)m_symbols[index].st_value; + if (sym_addr < addr && (addr - sym_addr) < *offset) { + pc = (address)m_symbols[index].st_value; + *offset = (int)(addr - pc); + *posIndex = m_symbols[index].st_name; + *stringtableIndex = m_shdr.sh_link; + } + } + } + } else { + long cur_pos; + if ((cur_pos = ftell(m_file)) == -1 || + fseek(m_file, m_shdr.sh_offset, SEEK_SET)) { + m_status = Decoder::file_invalid; + return m_status; + } + + Elf_Sym sym; + for (int index = 0; index < count; index ++) { + if (fread(&sym, sym_size, 1, m_file) == 1) { + if (STT_FUNC == ELF_ST_TYPE(sym.st_info)) { + address sym_addr = (address)sym.st_value; + if (sym_addr < addr && (addr - sym_addr) < *offset) { + pc = (address)sym.st_value; + *offset = (int)(addr - pc); + *posIndex = sym.st_name; + *stringtableIndex = m_shdr.sh_link; + } + } + } else { + m_status = Decoder::file_invalid; + return m_status; + } + } + fseek(m_file, cur_pos, SEEK_SET); + } + return m_status; +} + +#endif // _WINDOWS diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/utilities/elfSymbolTable.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/utilities/elfSymbolTable.hpp Fri Jan 07 03:58:11 2011 -0800 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1997, 2010, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef __ELF_SYMBOL_TABLE_HPP +#define __ELF_SYMBOL_TABLE_HPP + +#ifndef _WINDOWS + + +#include "memory/allocation.hpp" +#include "utilities/decoder.hpp" +#include "utilities/elfFile.hpp" + +/* + * symbol table object represents a symbol section in an elf file. + * Whenever possible, it will load all symbols from the corresponding section + * of the elf file into memory. Otherwise, it will walk the section in file + * to look up the symbol that nearest the given address. + */ +class ElfSymbolTable: public CHeapObj { + friend class ElfFile; + public: + ElfSymbolTable(FILE* file, Elf_Shdr shdr); + ~ElfSymbolTable(); + + // search the symbol that is nearest to the specified address. + Decoder::decoder_status lookup(address addr, int* stringtableIndex, int* posIndex, int* offset); + + Decoder::decoder_status get_status() { return m_status; }; + + protected: + ElfSymbolTable* m_next; + + // holds a complete symbol table section if + // can allocate enough memory + Elf_Sym* m_symbols; + + // file contains string table + FILE* m_file; + + // section header + Elf_Shdr m_shdr; + + Decoder::decoder_status m_status; +}; + +#endif // _WINDOWS + +#endif // __ELF_SYMBOL_TABLE_HPP + + + diff -r 55f868e91c3b -r 0e52ef6e94d3 src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Thu Jan 06 16:03:20 2011 -0800 +++ b/src/share/vm/utilities/vmError.cpp Fri Jan 07 03:58:11 2011 -0800 @@ -33,6 +33,7 @@ #include "runtime/vmThread.hpp" #include "runtime/vm_operations.hpp" #include "utilities/debug.hpp" +#include "utilities/decoder.hpp" #include "utilities/defaultStream.hpp" #include "utilities/top.hpp" #include "utilities/vmError.hpp" @@ -516,8 +517,10 @@ if (fr.pc()) { st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)"); + // initialize decoder to decode C frames + Decoder decoder; + int count = 0; - while (count++ < StackPrintLimit) { fr.print_on_error(st, buf, sizeof(buf)); st->cr();