This commit is contained in:
J. Duke 2017-07-05 17:31:39 +02:00
commit 690982fea8
92 changed files with 1511 additions and 620 deletions

View File

@ -98,3 +98,4 @@ a12a9e78df8a9d534da0b4a244ed68f0de0bd58e jdk7-b118
2c2d4f88637b488014c37e1a2eb401f68bca8838 jdk7-b121 2c2d4f88637b488014c37e1a2eb401f68bca8838 jdk7-b121
f1591eed71f64f6eba79fb7426f5616cc4dfea73 jdk7-b122 f1591eed71f64f6eba79fb7426f5616cc4dfea73 jdk7-b122
ed6950da30cf1e8904b4bdb034d471647942271f jdk7-b123 ed6950da30cf1e8904b4bdb034d471647942271f jdk7-b123
024a6755895bf91b5a3c98984c89ee018efbf538 jdk7-b124

View File

@ -98,3 +98,4 @@ cff5a173ec1e89013359e804a3e31736ef6fb462 jdk7-b120
2cc9f32992101732b23730b737740e64ebc5fa89 jdk7-b121 2cc9f32992101732b23730b737740e64ebc5fa89 jdk7-b121
1523a060032c8a5b7840198da8911abeff88118f jdk7-b122 1523a060032c8a5b7840198da8911abeff88118f jdk7-b122
a230c142628cea22475ab9dc5cd544266ddf2466 jdk7-b123 a230c142628cea22475ab9dc5cd544266ddf2466 jdk7-b123
f90b3e014e831eb4f32ef035a1dad2b8ba87949f jdk7-b124

View File

@ -138,3 +138,5 @@ f5603a6e50422046ebc0d2f1671d55cb8f1bf1e9 jdk7-b120
5484e7c53fa7da5e869902437ee08a9ae10c1c69 hs20-b03 5484e7c53fa7da5e869902437ee08a9ae10c1c69 hs20-b03
9669f9b284108a9ee0a0ccbe215c37a130c9dcf5 jdk7-b123 9669f9b284108a9ee0a0ccbe215c37a130c9dcf5 jdk7-b123
9669f9b284108a9ee0a0ccbe215c37a130c9dcf5 hs20-b04 9669f9b284108a9ee0a0ccbe215c37a130c9dcf5 hs20-b04
0a8e0d4345b37b71ec49dda08ee03b68c4f1b592 jdk7-b124
0a8e0d4345b37b71ec49dda08ee03b68c4f1b592 hs20-b05

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -99,15 +99,8 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
long typeEntrySizeOffset; long typeEntrySizeOffset;
long typeEntryArrayStride; long typeEntryArrayStride;
typeEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset"); // Fetch the address of the VMTypeEntry*. We get this symbol first
typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset"); // and try to use it to make sure that symbol lookup is working.
typeEntryIsOopTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset");
typeEntryIsIntegerTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset");
typeEntryIsUnsignedOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset");
typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset");
typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride");
// Fetch the address of the VMTypeEntry*
Address entryAddr = lookupInProcess("gHotSpotVMTypes"); Address entryAddr = lookupInProcess("gHotSpotVMTypes");
// System.err.println("gHotSpotVMTypes address = " + entryAddr); // System.err.println("gHotSpotVMTypes address = " + entryAddr);
// Dereference this once to get the pointer to the first VMTypeEntry // Dereference this once to get the pointer to the first VMTypeEntry
@ -118,6 +111,14 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
throw new RuntimeException("gHotSpotVMTypes was not initialized properly in the remote process; can not continue"); 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 // Start iterating down it until we find an entry with no name
Address typeNameAddr = null; Address typeNameAddr = null;
do { do {

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -122,10 +122,14 @@ public class COFFFileParser {
private MemoizedObject[] sectionHeaders; private MemoizedObject[] sectionHeaders;
private MemoizedObject[] symbols; 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() { private MemoizedObject stringTable = new MemoizedObject() {
public Object computeValue() { public Object computeValue() {
// the String Table follows the Symbol Table
int ptr = getPointerToSymbolTable(); int ptr = getPointerToSymbolTable();
if (ptr == 0) { if (ptr == 0) {
// no Symbol Table so no String Table
return new StringTable(0); return new StringTable(0);
} else { } else {
return new StringTable(ptr + SYMBOL_SIZE * getNumberOfSymbols()); return new StringTable(ptr + SYMBOL_SIZE * getNumberOfSymbols());
@ -140,6 +144,8 @@ public class COFFFileParser {
timeDateStamp = readInt(); timeDateStamp = readInt();
pointerToSymbolTable = readInt(); pointerToSymbolTable = readInt();
numberOfSymbols = readInt(); numberOfSymbols = readInt();
// String Table can be accessed at this point because
// pointerToSymbolTable and numberOfSymbols fields are set.
sizeOfOptionalHeader = readShort(); sizeOfOptionalHeader = readShort();
characteristics = readShort(); characteristics = readShort();
@ -222,6 +228,8 @@ public class COFFFileParser {
private MemoizedObject windowsSpecificFields; private MemoizedObject windowsSpecificFields;
private MemoizedObject dataDirectories; 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 STANDARD_FIELDS_OFFSET = 2;
private static final int PE32_WINDOWS_SPECIFIC_FIELDS_OFFSET = 28; private static final int PE32_WINDOWS_SPECIFIC_FIELDS_OFFSET = 28;
private static final int PE32_DATA_DIRECTORIES_OFFSET = 96; private static final int PE32_DATA_DIRECTORIES_OFFSET = 96;
@ -288,7 +296,7 @@ public class COFFFileParser {
private int sizeOfUninitializedData; private int sizeOfUninitializedData;
private int addressOfEntryPoint; private int addressOfEntryPoint;
private int baseOfCode; private int baseOfCode;
private int baseOfData; private int baseOfData; // only set in PE32
OptionalHeaderStandardFieldsImpl(int offset, OptionalHeaderStandardFieldsImpl(int offset,
boolean isPE32Plus) { boolean isPE32Plus) {
@ -301,7 +309,8 @@ public class COFFFileParser {
sizeOfUninitializedData = readInt(); sizeOfUninitializedData = readInt();
addressOfEntryPoint = readInt(); addressOfEntryPoint = readInt();
baseOfCode = readInt(); baseOfCode = readInt();
if (isPE32Plus) { if (!isPE32Plus) {
// only available in PE32
baseOfData = readInt(); baseOfData = readInt();
} }
} }
@ -433,7 +442,10 @@ public class COFFFileParser {
if (dir.getRVA() == 0 || dir.getSize() == 0) { if (dir.getRVA() == 0 || dir.getSize() == 0) {
return null; 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 @@ public class COFFFileParser {
} }
class ExportDirectoryTableImpl implements ExportDirectoryTable { class ExportDirectoryTableImpl implements ExportDirectoryTable {
private int exportDataDirRVA;
private int offset; private int offset;
private int size; private int size;
@ -548,8 +561,9 @@ public class COFFFileParser {
private MemoizedObject exportOrdinalTable; private MemoizedObject exportOrdinalTable;
private MemoizedObject exportAddressTable; private MemoizedObject exportAddressTable;
ExportDirectoryTableImpl(int offset, int size) { ExportDirectoryTableImpl(int exportDataDirRVA, int size) {
this.offset = offset; this.exportDataDirRVA = exportDataDirRVA;
offset = rvaToFileOffset(exportDataDirRVA);
this.size = size; this.size = size;
seek(offset); seek(offset);
exportFlags = readInt(); exportFlags = readInt();
@ -595,6 +609,7 @@ public class COFFFileParser {
exportOrdinalTable = new MemoizedObject() { exportOrdinalTable = new MemoizedObject() {
public Object computeValue() { public Object computeValue() {
// number of ordinals is same as the number of name pointers
short[] ordinals = new short[getNumberOfNamePointers()]; short[] ordinals = new short[getNumberOfNamePointers()];
seek(rvaToFileOffset(getOrdinalTableRVA())); seek(rvaToFileOffset(getOrdinalTableRVA()));
for (int i = 0; i < ordinals.length; i++) { for (int i = 0; i < ordinals.length; i++) {
@ -608,14 +623,18 @@ public class COFFFileParser {
public Object computeValue() { public Object computeValue() {
int[] addresses = new int[getNumberOfAddressTableEntries()]; int[] addresses = new int[getNumberOfAddressTableEntries()];
seek(rvaToFileOffset(getExportAddressTableRVA())); seek(rvaToFileOffset(getExportAddressTableRVA()));
// Must make two passes to avoid rvaToFileOffset // The Export Address Table values are a union of two
// destroying seek() position // 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++) { for (int i = 0; i < addresses.length; i++) {
addresses[i] = readInt(); addresses[i] = readInt();
} }
for (int i = 0; i < addresses.length; i++) {
addresses[i] = rvaToFileOffset(addresses[i]);
}
return addresses; return addresses;
} }
}; };
@ -648,11 +667,12 @@ public class COFFFileParser {
public boolean isExportAddressForwarder(short ordinal) { public boolean isExportAddressForwarder(short ordinal) {
int addr = getExportAddress(ordinal); int addr = getExportAddress(ordinal);
return ((offset <= addr) && (addr < (offset + size))); return ((exportDataDirRVA <= addr) &&
(addr < (exportDataDirRVA + size)));
} }
public String getExportAddressForwarder(short ordinal) { public String getExportAddressForwarder(short ordinal) {
seek(getExportAddress(ordinal)); seek(rvaToFileOffset(getExportAddress(ordinal)));
return readCString(); return readCString();
} }
@ -3371,10 +3391,17 @@ public class COFFFileParser {
throw new COFFException(e); throw new COFFException(e);
} }
// Look up in string table // Look up in string table
// FIXME: this index value is assumed to be in the valid range
name = getStringTable().get(index); name = getStringTable().get(index);
} else { } else {
try { 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) { } catch (UnsupportedEncodingException e) {
throw new COFFException(e); throw new COFFException(e);
} }
@ -3487,6 +3514,7 @@ public class COFFFileParser {
tmpName[5] << 16 | tmpName[5] << 16 |
tmpName[6] << 8 | tmpName[6] << 8 |
tmpName[7]); tmpName[7]);
// FIXME: stringOffset is assumed to be in the valid range
name = getStringTable().getAtOffset(stringOffset); name = getStringTable().getAtOffset(stringOffset);
} }
@ -3698,12 +3726,13 @@ public class COFFFileParser {
StringTable(int offset) { StringTable(int offset) {
if (offset == 0) { if (offset == 0) {
// no String Table
strings = new COFFString[0]; strings = new COFFString[0];
return; return;
} }
seek(offset); seek(offset);
int length = readInt(); int length = readInt(); // length includes itself
byte[] data = new byte[length - 4]; byte[] data = new byte[length - 4];
int numBytesRead = readBytes(data); int numBytesRead = readBytes(data);
if (numBytesRead != data.length) { if (numBytesRead != data.length) {

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -37,35 +37,48 @@ public class DumpExports {
String filename = args[0]; String filename = args[0];
COFFFile file = COFFFileParser.getParser().parse(filename); COFFFile file = COFFFileParser.getParser().parse(filename);
ExportDirectoryTable exports =
file.getHeader(). // get common point for both things we want to dump
getOptionalHeader(). OptionalHeaderDataDirectories dataDirs = file.getHeader().getOptionalHeader().
getDataDirectories(). getDataDirectories();
getExportDirectoryTable();
// 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) { if (exports == null) {
System.out.println("No exports found."); System.out.println("No exports found.");
} else { } 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("DLL name: " + exports.getDLLName());
System.out.println("Time/date stamp 0x" + Integer.toHexString(exports.getTimeDateStamp())); 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("Major version 0x" + Integer.toHexString(exports.getMajorVersion() & 0xFFFF));
System.out.println("Minor version 0x" + Integer.toHexString(exports.getMinorVersion() & 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++) { for (int i = 0; i < exports.getNumberOfNamePointers(); i++) {
System.out.println(" 0x" + short ordinal = exports.getExportOrdinal(i);
Integer.toHexString(exports.getExportAddress(exports.getExportOrdinal(i))) + System.out.print("[" + i + "] '" + exports.getExportName(i) + "': [" +
" " + ordinal + "] = 0x" + Integer.toHexString(exports.getExportAddress(ordinal)));
(exports.isExportAddressForwarder(exports.getExportOrdinal(i)) ? System.out.println(exports.isExportAddressForwarder(ordinal)
("Forwarded to " + exports.getExportAddressForwarder(exports.getExportOrdinal(i))) : ? " Forwarded to '" + exports.getExportAddressForwarder(ordinal) + "'"
exports.getExportName(i))); : "");
} }
} }
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -42,8 +42,8 @@ public class TestParser {
COFFHeader header = file.getHeader(); COFFHeader header = file.getHeader();
int numSections = header.getNumberOfSections(); int numSections = header.getNumberOfSections();
System.out.println(numSections + " sections detected."); System.out.println(numSections + " sections detected.");
for (int i = 0; i < numSections; i++) { for (int i = 1; i <= numSections; i++) {
SectionHeader secHeader = header.getSectionHeader(1 + i); SectionHeader secHeader = header.getSectionHeader(i);
System.out.println(secHeader.getName()); System.out.println(secHeader.getName());
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -506,7 +506,6 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger
throw new DebuggerException("Unimplemented"); throw new DebuggerException("Unimplemented");
} }
private static String DTFWHome;
private static String imagePath; private static String imagePath;
private static String symbolPath; private static String symbolPath;
private static boolean useNativeLookup; private static boolean useNativeLookup;
@ -514,81 +513,143 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger
static { static {
/* /*
* sawindbg.dll depends on dbgeng.dll which * sawindbg.dll depends on dbgeng.dll which itself depends on
* itself depends on dbghelp.dll. dbgeng.dll and dbghelp.dll. * dbghelp.dll. We have to make sure that the dbgeng.dll and
* On systems newer than Windows 2000, these two .dlls are * dbghelp.dll that we load are compatible with each other. We
* in the standard system directory so we will find them there. * load both of those libraries from the same directory based
* On Windows 2000 and earlier, these files do not exist. * on the theory that co-located libraries are compatible.
* The user must download Debugging Tools For Windows (DTFW)
* and install it in order to use SA.
* *
* We have to make sure we use the two files from the same directory * On Windows 2000 and earlier, dbgeng.dll and dbghelp.dll were
* in case there are more than one copy on the system because * not included as part of the standard system directory. On
* one version of dbgeng.dll might not be compatible with a * systems newer than Windows 2000, dbgeng.dll and dbghelp.dll
* different version of dbghelp.dll. * are included in the standard system directory. However, the
* We first look for them in the directory pointed at by * versions included in the standard system directory may not
* env. var. DEBUGGINGTOOLSFORWINDOWS, next in the default * be able to handle symbol information for the newer compilers.
* installation dir for DTFW, and lastly in the standard *
* system directory. We expect that that we will find * We search for and explicitly load the libraries using the
* them in the standard system directory on all systems * following directory search order:
* 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) { String dbgengPath = null;
// See if we have the files in the default location. String dbghelpPath = null;
String sysRoot = System.getenv("SYSTEMROOT"); String sawindbgPath = null;
DTFWHome = sysRoot + File.separator + List searchList = new ArrayList();
".." + File.separator + "Program Files" +
File.separator + "Debugging Tools For Windows"; boolean loadLibraryDEBUG =
} System.getProperty("sun.jvm.hotspot.loadLibrary.DEBUG") != null;
{ {
String dbghelp = DTFWHome + File.separator + "dbghelp.dll"; // First place to search is co-located with sawindbg.dll in
String dbgeng = DTFWHome + File.separator + "dbgeng.dll"; // $JAVA_HOME/jre/bin (java.home property is set to $JAVA_HOME/jre):
File fhelp = new File(dbghelp); searchList.add(System.getProperty("java.home") + File.separator + "bin");
File feng = new File(dbgeng); sawindbgPath = (String) searchList.get(0) + File.separator +
if (fhelp.exists() && feng.exists()) { "sawindbg.dll";
// found both, we are happy.
// second place to search is specified by an environment variable:
String DTFWHome = System.getenv("DEBUGGINGTOOLSFORWINDOWS");
if (DTFWHome != null) {
searchList.add(DTFWHome);
}
// 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 // NOTE: The order of loads is important! If we load dbgeng.dll
// first, then the dependency - dbghelp.dll - will be loaded // first, then the dependency - dbghelp.dll - will be loaded
// from usual DLL search thereby defeating the purpose! // from usual DLL search thereby defeating the purpose!
System.load(dbghelp); if (loadLibraryDEBUG) {
System.load(dbgeng); System.err.println("DEBUG: loading '" + dbghelpPath + "'.");
} 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);
}
}
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.");
} }
System.load(dbghelpPath);
if (loadLibraryDEBUG) {
System.err.println("DEBUG: loading '" + dbgengPath + "'.");
} }
System.load(dbgengPath);
// Now, load sawindbg.dll // 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? // where do I find '.exe', '.dll' files?
imagePath = System.getProperty("sun.jvm.hotspot.debugger.windbg.imagePath"); imagePath = System.getProperty("sun.jvm.hotspot.debugger.windbg.imagePath");
if (imagePath == null) { if (imagePath == null) {

View File

@ -30,6 +30,7 @@ import sun.jvm.hotspot.asm.*;
import sun.jvm.hotspot.asm.sparc.*; import sun.jvm.hotspot.asm.sparc.*;
import sun.jvm.hotspot.asm.x86.*; import sun.jvm.hotspot.asm.x86.*;
import sun.jvm.hotspot.asm.ia64.*; import sun.jvm.hotspot.asm.ia64.*;
import sun.jvm.hotspot.asm.amd64.*;
import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.compiler.*; import sun.jvm.hotspot.compiler.*;
import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.*;
@ -198,6 +199,8 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
cpuHelper = new SPARCHelper(); cpuHelper = new SPARCHelper();
} else if (cpu.equals("x86")) { } else if (cpu.equals("x86")) {
cpuHelper = new X86Helper(); cpuHelper = new X86Helper();
} else if (cpu.equals("amd64")) {
cpuHelper = new AMD64Helper();
} else if (cpu.equals("ia64")) { } else if (cpu.equals("ia64")) {
cpuHelper = new IA64Helper(); cpuHelper = new IA64Helper();
} else { } else {

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -31,11 +31,11 @@
# #
# Don't put quotes (fail windows build). # Don't put quotes (fail windows build).
HOTSPOT_VM_COPYRIGHT=Copyright 2010 HOTSPOT_VM_COPYRIGHT=Copyright 2011
HS_MAJOR_VER=20 HS_MAJOR_VER=20
HS_MINOR_VER=0 HS_MINOR_VER=0
HS_BUILD_NUMBER=05 HS_BUILD_NUMBER=06
JDK_MAJOR_VER=1 JDK_MAJOR_VER=1
JDK_MINOR_VER=7 JDK_MINOR_VER=7

View File

@ -150,6 +150,7 @@ jprt.build.targets= \
jprt.my.solaris.sparc.test.targets= \ jprt.my.solaris.sparc.test.targets= \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jvm98, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jvm98, \
${jprt.my.solaris.sparc}-{product|fastdebug}-c2-jvm98_tiered, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-scimark, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-scimark, \
${jprt.my.solaris.sparc}-product-{c1|c2}-runThese, \ ${jprt.my.solaris.sparc}-product-{c1|c2}-runThese, \
${jprt.my.solaris.sparc}-fastdebug-c1-runThese_Xshare, \ ${jprt.my.solaris.sparc}-fastdebug-c1-runThese_Xshare, \
@ -168,6 +169,7 @@ jprt.my.solaris.sparc.test.targets= \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_G1, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_G1, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_ParOldGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_ParOldGC, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_default, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_default, \
${jprt.my.solaris.sparc}-{product|fastdebug}-c2-jbb_default_tiered, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_SerialGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_SerialGC, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_ParallelGC, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_ParallelGC, \
${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_CMS, \ ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_CMS, \
@ -176,6 +178,7 @@ jprt.my.solaris.sparc.test.targets= \
jprt.my.solaris.sparcv9.test.targets= \ jprt.my.solaris.sparcv9.test.targets= \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jvm98, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jvm98, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jvm98_tiered, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-scimark, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-scimark, \
${jprt.my.solaris.sparcv9}-product-c2-runThese, \ ${jprt.my.solaris.sparcv9}-product-c2-runThese, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_default, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCBasher_default, \
@ -193,6 +196,7 @@ jprt.my.solaris.sparcv9.test.targets= \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_G1, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_G1, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_ParOldGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GCOld_ParOldGC, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_default, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_default, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_default_tiered, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_SerialGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_SerialGC, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_ParallelGC, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_ParallelGC, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_CMS, \ ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jbb_CMS, \
@ -201,6 +205,7 @@ jprt.my.solaris.sparcv9.test.targets= \
jprt.my.solaris.x64.test.targets= \ jprt.my.solaris.x64.test.targets= \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-jvm98, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jvm98, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-jvm98_tiered, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-scimark, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-scimark, \
${jprt.my.solaris.x64}-product-c2-runThese, \ ${jprt.my.solaris.x64}-product-c2-runThese, \
${jprt.my.solaris.x64}-product-c2-runThese_Xcomp, \ ${jprt.my.solaris.x64}-product-c2-runThese_Xcomp, \
@ -219,6 +224,7 @@ jprt.my.solaris.x64.test.targets= \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_G1, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_G1, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_ParOldGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_ParOldGC, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_default, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_default, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_default_tiered, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_SerialGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_SerialGC, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_CMS, \ ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_CMS, \
@ -227,6 +233,7 @@ jprt.my.solaris.x64.test.targets= \
jprt.my.solaris.i586.test.targets= \ jprt.my.solaris.i586.test.targets= \
${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-jvm98, \ ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-jvm98, \
${jprt.my.solaris.i586}-{product|fastdebug}-c2-jvm98_tiered, \
${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-scimark, \ ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-scimark, \
${jprt.my.solaris.i586}-product-{c1|c2}-runThese_Xcomp, \ ${jprt.my.solaris.i586}-product-{c1|c2}-runThese_Xcomp, \
${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xcomp, \ ${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xcomp, \
@ -253,6 +260,7 @@ jprt.my.solaris.i586.test.targets= \
${jprt.my.solaris.i586}-product-c1-GCOld_G1, \ ${jprt.my.solaris.i586}-product-c1-GCOld_G1, \
${jprt.my.solaris.i586}-product-c1-GCOld_ParOldGC, \ ${jprt.my.solaris.i586}-product-c1-GCOld_ParOldGC, \
${jprt.my.solaris.i586}-fastdebug-c2-jbb_default, \ ${jprt.my.solaris.i586}-fastdebug-c2-jbb_default, \
${jprt.my.solaris.i586}-fastdebug-c2-jbb_default_tiered, \
${jprt.my.solaris.i586}-fastdebug-c2-jbb_ParallelGC, \ ${jprt.my.solaris.i586}-fastdebug-c2-jbb_ParallelGC, \
${jprt.my.solaris.i586}-fastdebug-c2-jbb_CMS, \ ${jprt.my.solaris.i586}-fastdebug-c2-jbb_CMS, \
${jprt.my.solaris.i586}-fastdebug-c2-jbb_G1, \ ${jprt.my.solaris.i586}-fastdebug-c2-jbb_G1, \
@ -260,6 +268,7 @@ jprt.my.solaris.i586.test.targets= \
jprt.my.linux.i586.test.targets = \ jprt.my.linux.i586.test.targets = \
${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-jvm98, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-jvm98, \
${jprt.my.linux.i586}-{product|fastdebug}-c2-jvm98_tiered, \
${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-scimark, \ ${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-scimark, \
${jprt.my.linux.i586}-product-c1-runThese_Xcomp, \ ${jprt.my.linux.i586}-product-c1-runThese_Xcomp, \
${jprt.my.linux.i586}-fastdebug-c1-runThese_Xshare, \ ${jprt.my.linux.i586}-fastdebug-c1-runThese_Xshare, \
@ -279,6 +288,7 @@ jprt.my.linux.i586.test.targets = \
${jprt.my.linux.i586}-product-{c1|c2}-GCOld_G1, \ ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_G1, \
${jprt.my.linux.i586}-product-{c1|c2}-GCOld_ParOldGC, \ ${jprt.my.linux.i586}-product-{c1|c2}-GCOld_ParOldGC, \
${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_default, \ ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_default, \
${jprt.my.linux.i586}-{product|fastdebug}-c2-jbb_default_tiered, \
${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_ParallelGC, \ ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_ParallelGC, \
${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_CMS, \ ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_CMS, \
${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_G1, \ ${jprt.my.linux.i586}-{product|fastdebug}-c1-jbb_G1, \
@ -286,6 +296,7 @@ jprt.my.linux.i586.test.targets = \
jprt.my.linux.x64.test.targets = \ jprt.my.linux.x64.test.targets = \
${jprt.my.linux.x64}-{product|fastdebug}-c2-jvm98, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jvm98, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-jvm98_tiered, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-scimark, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-scimark, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_default, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_default, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_SerialGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCBasher_SerialGC, \
@ -302,12 +313,14 @@ jprt.my.linux.x64.test.targets = \
${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_G1, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_G1, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_ParOldGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-GCOld_ParOldGC, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_default, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_default, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_default_tiered, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_G1, \ ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_G1, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_ParOldGC ${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_ParOldGC
jprt.my.windows.i586.test.targets = \ jprt.my.windows.i586.test.targets = \
${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-jvm98, \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-jvm98, \
${jprt.my.windows.i586}-{product|fastdebug}-c2-jvm98_tiered, \
${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-scimark, \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-scimark, \
${jprt.my.windows.i586}-product-{c1|c2}-runThese, \ ${jprt.my.windows.i586}-product-{c1|c2}-runThese, \
${jprt.my.windows.i586}-product-{c1|c2}-runThese_Xcomp, \ ${jprt.my.windows.i586}-product-{c1|c2}-runThese_Xcomp, \
@ -327,6 +340,7 @@ jprt.my.windows.i586.test.targets = \
${jprt.my.windows.i586}-product-{c1|c2}-GCOld_G1, \ ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_G1, \
${jprt.my.windows.i586}-product-{c1|c2}-GCOld_ParOldGC, \ ${jprt.my.windows.i586}-product-{c1|c2}-GCOld_ParOldGC, \
${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-jbb_default, \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-jbb_default, \
${jprt.my.windows.i586}-{product|fastdebug}-c2-jbb_default_tiered, \
${jprt.my.windows.i586}-product-{c1|c2}-jbb_ParallelGC, \ ${jprt.my.windows.i586}-product-{c1|c2}-jbb_ParallelGC, \
${jprt.my.windows.i586}-product-{c1|c2}-jbb_CMS, \ ${jprt.my.windows.i586}-product-{c1|c2}-jbb_CMS, \
${jprt.my.windows.i586}-product-{c1|c2}-jbb_G1, \ ${jprt.my.windows.i586}-product-{c1|c2}-jbb_G1, \
@ -334,6 +348,7 @@ jprt.my.windows.i586.test.targets = \
jprt.my.windows.x64.test.targets = \ jprt.my.windows.x64.test.targets = \
${jprt.my.windows.x64}-{product|fastdebug}-c2-jvm98, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-jvm98, \
${jprt.my.windows.x64}-{product|fastdebug}-c2-jvm98_tiered, \
${jprt.my.windows.x64}-{product|fastdebug}-c2-scimark, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-scimark, \
${jprt.my.windows.x64}-product-c2-runThese, \ ${jprt.my.windows.x64}-product-c2-runThese, \
${jprt.my.windows.x64}-product-c2-runThese_Xcomp, \ ${jprt.my.windows.x64}-product-c2-runThese_Xcomp, \
@ -351,6 +366,7 @@ jprt.my.windows.x64.test.targets = \
${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_G1, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_G1, \
${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_ParOldGC, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-GCOld_ParOldGC, \
${jprt.my.windows.x64}-{product|fastdebug}-c2-jbb_default, \ ${jprt.my.windows.x64}-{product|fastdebug}-c2-jbb_default, \
${jprt.my.windows.x64}-{product|fastdebug}-c2-jbb_default_tiered, \
${jprt.my.windows.x64}-product-c2-jbb_CMS, \ ${jprt.my.windows.x64}-product-c2-jbb_CMS, \
${jprt.my.windows.x64}-product-c2-jbb_ParallelGC, \ ${jprt.my.windows.x64}-product-c2-jbb_ParallelGC, \
${jprt.my.windows.x64}-product-c2-jbb_G1, \ ${jprt.my.windows.x64}-product-c2-jbb_G1, \

View File

@ -61,7 +61,7 @@ include $(GAMMADIR)/make/scm.make
QUIETLY$(MAKE_VERBOSE) = @ QUIETLY$(MAKE_VERBOSE) = @
# For now, until the compiler is less wobbly: # For now, until the compiler is less wobbly:
TESTFLAGS = -Xbatch -showversion TESTFLAGS = -Xbatch -Xmx32m -showversion
### maye ARCH_XXX instead? ### maye ARCH_XXX instead?
ifdef USE_GCC ifdef USE_GCC

View File

@ -119,6 +119,10 @@ else
LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle
endif # sparcWorks endif # sparcWorks
ifeq ("${Platform_arch}", "sparc")
LIBS += -lkstat
endif
# By default, link the *.o into the library, not the executable. # By default, link the *.o into the library, not the executable.
LINK_INTO$(LINK_INTO) = LIBJVM LINK_INTO$(LINK_INTO) = LIBJVM

View File

@ -152,7 +152,7 @@ MS_RUNTIME_OPTION = /MTd /D "_DEBUG"
!endif !endif
# Always add the _STATIC_CPPLIB flag # 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) MS_RUNTIME_OPTION = $(MS_RUNTIME_OPTION) $(STATIC_CPPLIB_OPTION)
CPP_FLAGS=$(CPP_FLAGS) $(MS_RUNTIME_OPTION) CPP_FLAGS=$(CPP_FLAGS) $(MS_RUNTIME_OPTION)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,6 +23,7 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "assembler_sparc.inline.hpp" #include "assembler_sparc.inline.hpp"
#include "gc_interface/collectedHeap.inline.hpp" #include "gc_interface/collectedHeap.inline.hpp"
#include "interpreter/interpreter.hpp" #include "interpreter/interpreter.hpp"
@ -1327,37 +1328,38 @@ void MacroAssembler::patchable_sethi(const AddressLiteral& addrlit, Register d)
} }
int MacroAssembler::size_of_sethi(address a, bool worst_case) { int MacroAssembler::insts_for_sethi(address a, bool worst_case) {
#ifdef _LP64 #ifdef _LP64
if (worst_case) return 7; if (worst_case) return 7;
intptr_t iaddr = (intptr_t)a; intptr_t iaddr = (intptr_t) a;
int hi32 = (int)(iaddr >> 32); int msb32 = (int) (iaddr >> 32);
int lo32 = (int)(iaddr); int lsb32 = (int) (iaddr);
int inst_count; int count;
if (hi32 == 0 && lo32 >= 0) if (msb32 == 0 && lsb32 >= 0)
inst_count = 1; count = 1;
else if (hi32 == -1) else if (msb32 == -1)
inst_count = 2; count = 2;
else { else {
inst_count = 2; count = 2;
if ( hi32 & 0x3ff ) if (msb32 & 0x3ff)
inst_count++; count++;
if ( lo32 & 0xFFFFFC00 ) { if (lsb32 & 0xFFFFFC00 ) {
if( (lo32 >> 20) & 0xfff ) inst_count += 2; if ((lsb32 >> 20) & 0xfff) count += 2;
if( (lo32 >> 10) & 0x3ff ) inst_count += 2; if ((lsb32 >> 10) & 0x3ff) count += 2;
} }
} }
return BytesPerInstWord * inst_count; return count;
#else #else
return BytesPerInstWord; return 1;
#endif #endif
} }
int MacroAssembler::worst_case_size_of_set() { int MacroAssembler::worst_case_insts_for_set() {
return size_of_sethi(NULL, true) + 1; return insts_for_sethi(NULL, true) + 1;
} }
// Keep in sync with MacroAssembler::insts_for_internal_set
void MacroAssembler::internal_set(const AddressLiteral& addrlit, Register d, bool ForceRelocatable) { void MacroAssembler::internal_set(const AddressLiteral& addrlit, Register d, bool ForceRelocatable) {
intptr_t value = addrlit.value(); intptr_t value = addrlit.value();
@ -1379,6 +1381,23 @@ void MacroAssembler::internal_set(const AddressLiteral& addrlit, Register d, boo
} }
} }
// Keep in sync with MacroAssembler::internal_set
int MacroAssembler::insts_for_internal_set(intptr_t value) {
// can optimize
if (-4096 <= value && value <= 4095) {
return 1;
}
if (inv_hi22(hi22(value)) == value) {
return insts_for_sethi((address) value);
}
int count = insts_for_sethi((address) value);
AddressLiteral al(value);
if (al.low10() != 0) {
count++;
}
return count;
}
void MacroAssembler::set(const AddressLiteral& al, Register d) { void MacroAssembler::set(const AddressLiteral& al, Register d) {
internal_set(al, d, false); internal_set(al, d, false);
} }
@ -1443,11 +1462,11 @@ void MacroAssembler::set64(jlong value, Register d, Register tmp) {
} }
} }
int MacroAssembler::size_of_set64(jlong value) { int MacroAssembler::insts_for_set64(jlong value) {
v9_dep(); v9_dep();
int hi = (int)(value >> 32); int hi = (int) (value >> 32);
int lo = (int)(value & ~0); int lo = (int) (value & ~0);
int count = 0; int count = 0;
// (Matcher::isSimpleConstant64 knows about the following optimizations.) // (Matcher::isSimpleConstant64 knows about the following optimizations.)
@ -4083,11 +4102,15 @@ void MacroAssembler::tlab_refill(Label& retry, Label& try_eden, Label& slow_case
store_klass(t2, top); store_klass(t2, top);
verify_oop(top); verify_oop(top);
ld_ptr(G2_thread, in_bytes(JavaThread::tlab_start_offset()), t1);
sub(top, t1, t1); // size of tlab's allocated portion
incr_allocated_bytes(t1, 0, t2);
// refill the tlab with an eden allocation // refill the tlab with an eden allocation
bind(do_refill); bind(do_refill);
ld_ptr(G2_thread, in_bytes(JavaThread::tlab_size_offset()), t1); ld_ptr(G2_thread, in_bytes(JavaThread::tlab_size_offset()), t1);
sll_ptr(t1, LogHeapWordSize, t1); sll_ptr(t1, LogHeapWordSize, t1);
// add object_size ?? // allocate new tlab, address returned in top
eden_allocate(top, t1, 0, t2, t3, slow_case); eden_allocate(top, t1, 0, t2, t3, slow_case);
st_ptr(top, G2_thread, in_bytes(JavaThread::tlab_start_offset())); st_ptr(top, G2_thread, in_bytes(JavaThread::tlab_start_offset()));
@ -4115,6 +4138,22 @@ void MacroAssembler::tlab_refill(Label& retry, Label& try_eden, Label& slow_case
delayed()->nop(); delayed()->nop();
} }
void MacroAssembler::incr_allocated_bytes(Register var_size_in_bytes,
int con_size_in_bytes,
Register t1) {
// Bump total bytes allocated by this thread
assert(t1->is_global(), "must be global reg"); // so all 64 bits are saved on a context switch
assert_different_registers(var_size_in_bytes, t1);
// v8 support has gone the way of the dodo
ldx(G2_thread, in_bytes(JavaThread::allocated_bytes_offset()), t1);
if (var_size_in_bytes->is_valid()) {
add(t1, var_size_in_bytes, t1);
} else {
add(t1, con_size_in_bytes, t1);
}
stx(t1, G2_thread, in_bytes(JavaThread::allocated_bytes_offset()));
}
Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) {
switch (cond) { switch (cond) {
// Note some conditions are synonyms for others // Note some conditions are synonyms for others

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1884,23 +1884,24 @@ public:
void sethi(const AddressLiteral& addrlit, Register d); void sethi(const AddressLiteral& addrlit, Register d);
void patchable_sethi(const AddressLiteral& addrlit, Register d); void patchable_sethi(const AddressLiteral& addrlit, Register d);
// compute the size of a sethi/set // compute the number of instructions for a sethi/set
static int size_of_sethi( address a, bool worst_case = false ); static int insts_for_sethi( address a, bool worst_case = false );
static int worst_case_size_of_set(); static int worst_case_insts_for_set();
// set may be either setsw or setuw (high 32 bits may be zero or sign) // set may be either setsw or setuw (high 32 bits may be zero or sign)
private: private:
void internal_set(const AddressLiteral& al, Register d, bool ForceRelocatable); void internal_set(const AddressLiteral& al, Register d, bool ForceRelocatable);
static int insts_for_internal_set(intptr_t value);
public: public:
void set(const AddressLiteral& addrlit, Register d); void set(const AddressLiteral& addrlit, Register d);
void set(intptr_t value, Register d); void set(intptr_t value, Register d);
void set(address addr, Register d, RelocationHolder const& rspec); void set(address addr, Register d, RelocationHolder const& rspec);
static int insts_for_set(intptr_t value) { return insts_for_internal_set(value); }
void patchable_set(const AddressLiteral& addrlit, Register d); void patchable_set(const AddressLiteral& addrlit, Register d);
void patchable_set(intptr_t value, Register d); void patchable_set(intptr_t value, Register d);
void set64(jlong value, Register d, Register tmp); void set64(jlong value, Register d, Register tmp);
static int insts_for_set64(jlong value);
// Compute size of set64.
static int size_of_set64(jlong value);
// sign-extend 32 to 64 // sign-extend 32 to 64
inline void signx( Register s, Register d ) { sra( s, G0, d); } inline void signx( Register s, Register d ) { sra( s, G0, d); }
@ -2388,6 +2389,7 @@ public:
Label& slow_case // continuation point if fast allocation fails Label& slow_case // continuation point if fast allocation fails
); );
void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case);
void incr_allocated_bytes(Register var_size_in_bytes, int con_size_in_bytes, Register t1);
// interface method calling // interface method calling
void lookup_interface_method(Register recv_klass, void lookup_interface_method(Register recv_klass,

View File

@ -1705,8 +1705,7 @@ void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Op
} }
void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result) { void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) {
Assembler::Condition acond; Assembler::Condition acond;
switch (condition) { switch (condition) {
case lir_cond_equal: acond = Assembler::equal; break; case lir_cond_equal: acond = Assembler::equal; break;
@ -1737,7 +1736,12 @@ void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, L
ShouldNotReachHere(); ShouldNotReachHere();
} }
Label skip; Label skip;
#ifdef _LP64
if (type == T_INT) {
__ br(acond, false, Assembler::pt, skip); __ br(acond, false, Assembler::pt, skip);
} else
#endif
__ brx(acond, false, Assembler::pt, skip); // checks icc on 32bit and xcc on 64bit
if (opr1->is_constant() && opr1->type() == T_INT) { if (opr1->is_constant() && opr1->type() == T_INT) {
Register dest = result->as_register(); Register dest = result->as_register();
if (Assembler::is_simm13(opr1->as_jint())) { if (Assembler::is_simm13(opr1->as_jint())) {
@ -2688,6 +2692,11 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) {
#ifdef _LP64 #ifdef _LP64
__ mov(cmp_value_lo, t1); __ mov(cmp_value_lo, t1);
__ mov(new_value_lo, t2); __ mov(new_value_lo, t2);
// perform the compare and swap operation
__ casx(addr, t1, t2);
// generate condition code - if the swap succeeded, t2 ("new value" reg) was
// overwritten with the original value in "addr" and will be equal to t1.
__ cmp(t1, t2);
#else #else
// move high and low halves of long values into single registers // move high and low halves of long values into single registers
__ sllx(cmp_value_hi, 32, t1); // shift high half into temp reg __ sllx(cmp_value_hi, 32, t1); // shift high half into temp reg
@ -2696,13 +2705,15 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) {
__ sllx(new_value_hi, 32, t2); __ sllx(new_value_hi, 32, t2);
__ srl(new_value_lo, 0, new_value_lo); __ srl(new_value_lo, 0, new_value_lo);
__ or3(t2, new_value_lo, t2); // t2 holds 64-bit value to swap __ or3(t2, new_value_lo, t2); // t2 holds 64-bit value to swap
#endif
// perform the compare and swap operation // perform the compare and swap operation
__ casx(addr, t1, t2); __ casx(addr, t1, t2);
// generate condition code - if the swap succeeded, t2 ("new value" reg) was // generate condition code - if the swap succeeded, t2 ("new value" reg) was
// overwritten with the original value in "addr" and will be equal to t1. // overwritten with the original value in "addr" and will be equal to t1.
__ cmp(t1, t2); // Produce icc flag for 32bit.
__ sub(t1, t2, t2);
__ srlx(t2, 32, t1);
__ orcc(t2, t1, G0);
#endif
} else if (op->code() == lir_cas_int || op->code() == lir_cas_obj) { } else if (op->code() == lir_cas_int || op->code() == lir_cas_obj) {
Register addr = op->addr()->as_pointer_register(); Register addr = op->addr()->as_pointer_register();
Register cmp_value = op->cmp_value()->as_register(); Register cmp_value = op->cmp_value()->as_register();

View File

@ -662,7 +662,7 @@ void LIRGenerator::do_AttemptUpdate(Intrinsic* x) {
// generate conditional move of boolean result // generate conditional move of boolean result
LIR_Opr result = rlock_result(x); LIR_Opr result = rlock_result(x);
__ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result, T_LONG);
} }
@ -699,10 +699,10 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
else { else {
ShouldNotReachHere(); ShouldNotReachHere();
} }
// generate conditional move of boolean result // generate conditional move of boolean result
LIR_Opr result = rlock_result(x); LIR_Opr result = rlock_result(x);
__ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0),
result, as_BasicType(type));
if (type == objectType) { // Write-barrier needed for Object fields. if (type == objectType) { // Write-barrier needed for Object fields.
// Precise card mark since could either be object or array // Precise card mark since could either be object or array
post_barrier(addr, val.result()); post_barrier(addr, val.result());

View File

@ -166,7 +166,7 @@ void C1_MacroAssembler::try_allocate(
Register obj, // result: pointer to object after successful allocation Register obj, // result: pointer to object after successful allocation
Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise
int con_size_in_bytes, // object size in bytes if known at compile time int con_size_in_bytes, // object size in bytes if known at compile time
Register t1, // temp register Register t1, // temp register, must be global register for incr_allocated_bytes
Register t2, // temp register Register t2, // temp register
Label& slow_case // continuation point if fast allocation fails Label& slow_case // continuation point if fast allocation fails
) { ) {
@ -174,6 +174,7 @@ void C1_MacroAssembler::try_allocate(
tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case); tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
} else { } else {
eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case); eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
incr_allocated_bytes(var_size_in_bytes, con_size_in_bytes, t1);
} }
} }
@ -214,7 +215,7 @@ void C1_MacroAssembler::initialize_body(Register base, Register index) {
void C1_MacroAssembler::allocate_object( void C1_MacroAssembler::allocate_object(
Register obj, // result: pointer to object after successful allocation Register obj, // result: pointer to object after successful allocation
Register t1, // temp register Register t1, // temp register
Register t2, // temp register Register t2, // temp register, must be a global register for try_allocate
Register t3, // temp register Register t3, // temp register
int hdr_size, // object header size in words int hdr_size, // object header size in words
int obj_size, // object size in words int obj_size, // object size in words

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -448,7 +448,9 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
// get the instance size // get the instance size
__ ld(G5_klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), G1_obj_size); __ ld(G5_klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), G1_obj_size);
__ tlab_allocate(O0_obj, G1_obj_size, 0, G3_t1, slow_path); __ tlab_allocate(O0_obj, G1_obj_size, 0, G3_t1, slow_path);
__ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2); __ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2);
__ verify_oop(O0_obj); __ verify_oop(O0_obj);
__ mov(O0, I0); __ mov(O0, I0);
@ -459,6 +461,8 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
// get the instance size // get the instance size
__ ld(G5_klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), G1_obj_size); __ ld(G5_klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), G1_obj_size);
__ eden_allocate(O0_obj, G1_obj_size, 0, G3_t1, G4_t2, slow_path); __ eden_allocate(O0_obj, G1_obj_size, 0, G3_t1, G4_t2, slow_path);
__ incr_allocated_bytes(G1_obj_size, 0, G3_t1);
__ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2); __ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2);
__ verify_oop(O0_obj); __ verify_oop(O0_obj);
__ mov(O0, I0); __ mov(O0, I0);
@ -573,6 +577,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ and3(G1_arr_size, ~MinObjAlignmentInBytesMask, G1_arr_size); __ and3(G1_arr_size, ~MinObjAlignmentInBytesMask, G1_arr_size);
__ eden_allocate(O0_obj, G1_arr_size, 0, G3_t1, O1_t2, slow_path); // preserves G1_arr_size __ eden_allocate(O0_obj, G1_arr_size, 0, G3_t1, O1_t2, slow_path); // preserves G1_arr_size
__ incr_allocated_bytes(G1_arr_size, 0, G3_t1);
__ initialize_header(O0_obj, G5_klass, G4_length, G3_t1, O1_t2); __ initialize_header(O0_obj, G5_klass, G4_length, G3_t1, O1_t2);
__ ldub(klass_lh, G3_t1, klass_lh_header_size_offset); __ ldub(klass_lh, G3_t1, klass_lh_header_size_offset);

View File

@ -395,18 +395,23 @@ int MethodHandles::adapter_conversion_ops_supported_mask() {
// //
// Generate an "entry" field for a method handle. // Generate an "entry" field for a method handle.
// This determines how the method handle will respond to calls. // This determines how the method handle will respond to calls.
void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) { void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek, TRAPS) {
// Here is the register state during an interpreted call, // Here is the register state during an interpreted call,
// as set up by generate_method_handle_interpreter_entry(): // as set up by generate_method_handle_interpreter_entry():
// - G5: garbage temp (was MethodHandle.invoke methodOop, unused) // - G5: garbage temp (was MethodHandle.invoke methodOop, unused)
// - G3: receiver method handle // - G3: receiver method handle
// - O5_savedSP: sender SP (must preserve) // - O5_savedSP: sender SP (must preserve)
Register O0_argslot = O0; const Register O0_argslot = O0;
Register O1_scratch = O1; const Register O1_scratch = O1;
Register O2_scratch = O2; const Register O2_scratch = O2;
Register O3_scratch = O3; const Register O3_scratch = O3;
Register G5_index = G5; const Register G5_index = G5;
// Argument registers for _raise_exception.
const Register O0_code = O0;
const Register O1_actual = O1;
const Register O2_required = O2;
guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets");
@ -439,48 +444,36 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
case _raise_exception: case _raise_exception:
{ {
// Not a real MH entry, but rather shared code for raising an // Not a real MH entry, but rather shared code for raising an
// exception. Extra local arguments are passed in scratch // exception. Since we use a C2I adapter to set up the
// registers, as required type in O3, failing object (or NULL) // interpreter state, arguments are expected in compiler
// in O2, failing bytecode type in O1. // argument registers.
methodHandle mh(raise_exception_method());
address c2i_entry = methodOopDesc::make_adapters(mh, CATCH);
__ mov(O5_savedSP, SP); // Cut the stack back to where the caller started. __ mov(O5_savedSP, SP); // Cut the stack back to where the caller started.
// Push arguments as if coming from the interpreter. Label L_no_method;
Register O0_scratch = O0_argslot;
int stackElementSize = Interpreter::stackElementSize;
// Make space on the stack for the arguments and set Gargs
// correctly.
__ sub(SP, 4*stackElementSize, SP); // Keep stack aligned.
__ add(SP, (frame::varargs_offset)*wordSize - 1*Interpreter::stackElementSize + STACK_BIAS + BytesPerWord, Gargs);
// void raiseException(int code, Object actual, Object required)
__ st( O1_scratch, Address(Gargs, 2*stackElementSize)); // code
__ st_ptr(O2_scratch, Address(Gargs, 1*stackElementSize)); // actual
__ st_ptr(O3_scratch, Address(Gargs, 0*stackElementSize)); // required
Label no_method;
// FIXME: fill in _raise_exception_method with a suitable sun.dyn method // FIXME: fill in _raise_exception_method with a suitable sun.dyn method
__ set(AddressLiteral((address) &_raise_exception_method), G5_method); __ set(AddressLiteral((address) &_raise_exception_method), G5_method);
__ ld_ptr(Address(G5_method, 0), G5_method); __ ld_ptr(Address(G5_method, 0), G5_method);
__ tst(G5_method); __ tst(G5_method);
__ brx(Assembler::zero, false, Assembler::pn, no_method); __ brx(Assembler::zero, false, Assembler::pn, L_no_method);
__ delayed()->nop(); __ delayed()->nop();
int jobject_oop_offset = 0; const int jobject_oop_offset = 0;
__ ld_ptr(Address(G5_method, jobject_oop_offset), G5_method); __ ld_ptr(Address(G5_method, jobject_oop_offset), G5_method);
__ tst(G5_method); __ tst(G5_method);
__ brx(Assembler::zero, false, Assembler::pn, no_method); __ brx(Assembler::zero, false, Assembler::pn, L_no_method);
__ delayed()->nop(); __ delayed()->nop();
__ verify_oop(G5_method); __ verify_oop(G5_method);
__ jump_indirect_to(G5_method_fie, O1_scratch); __ jump_to(AddressLiteral(c2i_entry), O3_scratch);
__ delayed()->nop(); __ delayed()->nop();
// If we get here, the Java runtime did not do its job of creating the exception. // If we get here, the Java runtime did not do its job of creating the exception.
// Do something that is at least causes a valid throw from the interpreter. // Do something that is at least causes a valid throw from the interpreter.
__ bind(no_method); __ bind(L_no_method);
__ unimplemented("_raise_exception no method"); __ unimplemented("call throw_WrongMethodType_entry");
} }
break; break;
@ -570,10 +563,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
// Throw an exception. // Throw an exception.
// For historical reasons, it will be IncompatibleClassChangeError. // For historical reasons, it will be IncompatibleClassChangeError.
__ unimplemented("not tested yet"); __ unimplemented("not tested yet");
__ ld_ptr(Address(O1_intf, java_mirror_offset), O3_scratch); // required interface __ ld_ptr(Address(O1_intf, java_mirror_offset), O2_required); // required interface
__ mov(O0_klass, O2_scratch); // bad receiver __ mov( O0_klass, O1_actual); // bad receiver
__ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O0_argslot); __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O3_scratch);
__ delayed()->mov(Bytecodes::_invokeinterface, O1_scratch); // who is complaining? __ delayed()->mov(Bytecodes::_invokeinterface, O0_code); // who is complaining?
} }
break; break;
@ -663,11 +656,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ check_klass_subtype(O1_scratch, G5_klass, O0_argslot, O2_scratch, done); __ check_klass_subtype(O1_scratch, G5_klass, O0_argslot, O2_scratch, done);
// If we get here, the type check failed! // If we get here, the type check failed!
__ ldsw(G3_amh_vmargslot, O0_argslot); // reload argslot field __ load_heap_oop(G3_amh_argument, O2_required); // required class
__ load_heap_oop(G3_amh_argument, O3_scratch); // required class __ ld_ptr( vmarg, O1_actual); // bad object
__ ld_ptr(vmarg, O2_scratch); // bad object __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O3_scratch);
__ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O0_argslot); __ delayed()->mov(Bytecodes::_checkcast, O0_code); // who is complaining?
__ delayed()->mov(Bytecodes::_checkcast, O1_scratch); // who is complaining?
__ bind(done); __ bind(done);
// Get the new MH: // Get the new MH:

View File

@ -1086,9 +1086,9 @@ void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
uint MachConstantBaseNode::size(PhaseRegAlloc*) const { uint MachConstantBaseNode::size(PhaseRegAlloc*) const {
if (UseRDPCForConstantTableBase) { if (UseRDPCForConstantTableBase) {
// This is really the worst case but generally it's only 1 instruction. // This is really the worst case but generally it's only 1 instruction.
return 4 /*rdpc*/ + 4 /*sub*/ + MacroAssembler::worst_case_size_of_set(); return (1 /*rdpc*/ + 1 /*sub*/ + MacroAssembler::worst_case_insts_for_set()) * BytesPerInstWord;
} else { } else {
return MacroAssembler::worst_case_size_of_set(); return MacroAssembler::worst_case_insts_for_set() * BytesPerInstWord;
} }
} }
@ -1240,7 +1240,7 @@ const Pipeline * MachEpilogNode::pipeline() const {
int MachEpilogNode::safepoint_offset() const { int MachEpilogNode::safepoint_offset() const {
assert( do_polling(), "no return for this epilog node"); assert( do_polling(), "no return for this epilog node");
return MacroAssembler::size_of_sethi(os::get_polling_page()); return MacroAssembler::insts_for_sethi(os::get_polling_page()) * BytesPerInstWord;
} }
//============================================================================= //=============================================================================
@ -3553,9 +3553,10 @@ operand immP() %{
interface(CONST_INTER); interface(CONST_INTER);
%} %}
// Pointer Immediate: 32 or 64-bit #ifdef _LP64
// Pointer Immediate: 64-bit
operand immP_set() %{ operand immP_set() %{
predicate(!VM_Version::is_niagara1_plus()); predicate(!VM_Version::is_niagara_plus());
match(ConP); match(ConP);
op_cost(5); op_cost(5);
@ -3564,10 +3565,10 @@ operand immP_set() %{
interface(CONST_INTER); interface(CONST_INTER);
%} %}
// Pointer Immediate: 32 or 64-bit // Pointer Immediate: 64-bit
// From Niagara2 processors on a load should be better than materializing. // From Niagara2 processors on a load should be better than materializing.
operand immP_load() %{ operand immP_load() %{
predicate(VM_Version::is_niagara1_plus()); predicate(VM_Version::is_niagara_plus() && (n->bottom_type()->isa_oop_ptr() || (MacroAssembler::insts_for_set(n->get_ptr()) > 3)));
match(ConP); match(ConP);
op_cost(5); op_cost(5);
@ -3576,6 +3577,18 @@ operand immP_load() %{
interface(CONST_INTER); interface(CONST_INTER);
%} %}
// Pointer Immediate: 64-bit
operand immP_no_oop_cheap() %{
predicate(VM_Version::is_niagara_plus() && !n->bottom_type()->isa_oop_ptr() && (MacroAssembler::insts_for_set(n->get_ptr()) <= 3));
match(ConP);
op_cost(5);
// formats are generated automatically for constants and base registers
format %{ %}
interface(CONST_INTER);
%}
#endif
operand immP13() %{ operand immP13() %{
predicate((-4096 < n->get_ptr()) && (n->get_ptr() <= 4095)); predicate((-4096 < n->get_ptr()) && (n->get_ptr() <= 4095));
match(ConP); match(ConP);
@ -3673,7 +3686,7 @@ operand immL_32bits() %{
// Long Immediate: cheap (materialize in <= 3 instructions) // Long Immediate: cheap (materialize in <= 3 instructions)
operand immL_cheap() %{ operand immL_cheap() %{
predicate(!VM_Version::is_niagara1_plus() || MacroAssembler::size_of_set64(n->get_long()) <= 3); predicate(!VM_Version::is_niagara_plus() || MacroAssembler::insts_for_set64(n->get_long()) <= 3);
match(ConL); match(ConL);
op_cost(0); op_cost(0);
@ -3683,7 +3696,7 @@ operand immL_cheap() %{
// Long Immediate: expensive (materialize in > 3 instructions) // Long Immediate: expensive (materialize in > 3 instructions)
operand immL_expensive() %{ operand immL_expensive() %{
predicate(VM_Version::is_niagara1_plus() && MacroAssembler::size_of_set64(n->get_long()) > 3); predicate(VM_Version::is_niagara_plus() && MacroAssembler::insts_for_set64(n->get_long()) > 3);
match(ConL); match(ConL);
op_cost(0); op_cost(0);
@ -6099,6 +6112,16 @@ instruct loadConP_load(iRegP dst, immP_load con) %{
%} %}
ins_pipe(loadConP); ins_pipe(loadConP);
%} %}
instruct loadConP_no_oop_cheap(iRegP dst, immP_no_oop_cheap con) %{
match(Set dst con);
ins_cost(DEFAULT_COST * 3/2);
format %{ "SET $con,$dst\t! non-oop ptr" %}
ins_encode %{
__ set($con$$constant, $dst$$Register);
%}
ins_pipe(loadConP);
%}
#endif // _LP64 #endif // _LP64
instruct loadConP0(iRegP dst, immP0 src) %{ instruct loadConP0(iRegP dst, immP0 src) %{

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -3445,6 +3445,9 @@ void TemplateTable::_new() {
__ cmp(RoldTopValue, RnewTopValue); __ cmp(RoldTopValue, RnewTopValue);
__ brx(Assembler::notEqual, false, Assembler::pn, retry); __ brx(Assembler::notEqual, false, Assembler::pn, retry);
__ delayed()->nop(); __ delayed()->nop();
// bump total bytes allocated by this thread
__ incr_allocated_bytes(Roffset, 0, G1_scratch);
} }
if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) { if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) {

View File

@ -38,12 +38,6 @@
int VM_Version::_features = VM_Version::unknown_m; int VM_Version::_features = VM_Version::unknown_m;
const char* VM_Version::_features_str = ""; const char* VM_Version::_features_str = "";
bool VM_Version::is_niagara1_plus() {
// This is a placeholder until the real test is determined.
return is_niagara1() &&
(os::processor_count() > maximum_niagara1_processor_count());
}
void VM_Version::initialize() { void VM_Version::initialize() {
_features = determine_features(); _features = determine_features();
PrefetchCopyIntervalInBytes = prefetch_copy_interval_in_bytes(); PrefetchCopyIntervalInBytes = prefetch_copy_interval_in_bytes();
@ -69,11 +63,21 @@ void VM_Version::initialize() {
_supports_cx8 = has_v9(); _supports_cx8 = has_v9();
if (is_niagara1()) { if (is_niagara()) {
// Indirect branch is the same cost as direct // Indirect branch is the same cost as direct
if (FLAG_IS_DEFAULT(UseInlineCaches)) { if (FLAG_IS_DEFAULT(UseInlineCaches)) {
FLAG_SET_DEFAULT(UseInlineCaches, false); FLAG_SET_DEFAULT(UseInlineCaches, false);
} }
// Align loops on a single instruction boundary.
if (FLAG_IS_DEFAULT(OptoLoopAlignment)) {
FLAG_SET_DEFAULT(OptoLoopAlignment, 4);
}
// When using CMS, we cannot use memset() in BOT updates because
// the sun4v/CMT version in libc_psr uses BIS which exposes
// "phantom zeros" to concurrent readers. See 6948537.
if (FLAG_IS_DEFAULT(UseMemSetInBOT) && UseConcMarkSweepGC) {
FLAG_SET_DEFAULT(UseMemSetInBOT, false);
}
#ifdef _LP64 #ifdef _LP64
// 32-bit oops don't make sense for the 64-bit VM on sparc // 32-bit oops don't make sense for the 64-bit VM on sparc
// since the 32-bit VM has the same registers and smaller objects. // since the 32-bit VM has the same registers and smaller objects.
@ -89,7 +93,7 @@ void VM_Version::initialize() {
if (FLAG_IS_DEFAULT(InteriorEntryAlignment)) { if (FLAG_IS_DEFAULT(InteriorEntryAlignment)) {
FLAG_SET_DEFAULT(InteriorEntryAlignment, 4); FLAG_SET_DEFAULT(InteriorEntryAlignment, 4);
} }
if (is_niagara1_plus()) { if (is_niagara_plus()) {
if (has_blk_init() && AllocatePrefetchStyle > 0 && if (has_blk_init() && AllocatePrefetchStyle > 0 &&
FLAG_IS_DEFAULT(AllocatePrefetchStyle)) { FLAG_IS_DEFAULT(AllocatePrefetchStyle)) {
// Use BIS instruction for allocation prefetch. // Use BIS instruction for allocation prefetch.
@ -105,15 +109,6 @@ void VM_Version::initialize() {
} }
} }
#endif #endif
if (FLAG_IS_DEFAULT(OptoLoopAlignment)) {
FLAG_SET_DEFAULT(OptoLoopAlignment, 4);
}
// When using CMS, we cannot use memset() in BOT updates because
// the sun4v/CMT version in libc_psr uses BIS which exposes
// "phantom zeros" to concurrent readers. See 6948537.
if (FLAG_IS_DEFAULT(UseMemSetInBOT) && UseConcMarkSweepGC) {
FLAG_SET_DEFAULT(UseMemSetInBOT, false);
}
} }
// Use hardware population count instruction if available. // Use hardware population count instruction if available.
@ -129,17 +124,18 @@ void VM_Version::initialize() {
#endif #endif
char buf[512]; char buf[512];
jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
(has_v8() ? ", has_v8" : ""), (has_v8() ? ", has_v8" : ""),
(has_v9() ? ", has_v9" : ""), (has_v9() ? ", has_v9" : ""),
(has_hardware_popc() ? ", popc" : ""), (has_hardware_popc() ? ", popc" : ""),
(has_vis1() ? ", has_vis1" : ""), (has_vis1() ? ", has_vis1" : ""),
(has_vis2() ? ", has_vis2" : ""), (has_vis2() ? ", has_vis2" : ""),
(has_vis3() ? ", has_vis3" : ""),
(has_blk_init() ? ", has_blk_init" : ""), (has_blk_init() ? ", has_blk_init" : ""),
(is_ultra3() ? ", is_ultra3" : ""), (is_ultra3() ? ", is_ultra3" : ""),
(is_sun4v() ? ", is_sun4v" : ""), (is_sun4v() ? ", is_sun4v" : ""),
(is_niagara1() ? ", is_niagara1" : ""), (is_niagara() ? ", is_niagara" : ""),
(is_niagara1_plus() ? ", is_niagara1_plus" : ""), (is_niagara_plus() ? ", is_niagara_plus" : ""),
(is_sparc64() ? ", is_sparc64" : ""), (is_sparc64() ? ", is_sparc64" : ""),
(!has_hardware_mul32() ? ", no-mul32" : ""), (!has_hardware_mul32() ? ", no-mul32" : ""),
(!has_hardware_div32() ? ", no-div32" : ""), (!has_hardware_div32() ? ", no-div32" : ""),
@ -190,17 +186,18 @@ int VM_Version::determine_features() {
warning("Cannot recognize SPARC version. Default to V9"); warning("Cannot recognize SPARC version. Default to V9");
} }
if (UseNiagaraInstrs) { assert(is_T_family(features) == is_niagara(features), "Niagara should be T series");
if (is_niagara1(features)) { if (UseNiagaraInstrs) { // Force code generation for Niagara
if (is_T_family(features)) {
// Happy to accomodate... // Happy to accomodate...
} else { } else {
NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Version is Forced-Niagara");) NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Version is Forced-Niagara");)
features = niagara1_m; features |= T_family_m;
} }
} else { } else {
if (is_niagara1(features) && !FLAG_IS_DEFAULT(UseNiagaraInstrs)) { if (is_T_family(features) && !FLAG_IS_DEFAULT(UseNiagaraInstrs)) {
NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Version is Forced-Not-Niagara");) NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Version is Forced-Not-Niagara");)
features &= ~niagara1_unique_m; features &= ~(T_family_m | T1_model_m);
} else { } else {
// Happy to accomodate... // Happy to accomodate...
} }
@ -222,7 +219,7 @@ void VM_Version::revert() {
unsigned int VM_Version::calc_parallel_worker_threads() { unsigned int VM_Version::calc_parallel_worker_threads() {
unsigned int result; unsigned int result;
if (is_niagara1_plus()) { if (is_niagara_plus()) {
result = nof_parallel_worker_threads(5, 16, 8); result = nof_parallel_worker_threads(5, 16, 8);
} else { } else {
result = nof_parallel_worker_threads(5, 8, 8); result = nof_parallel_worker_threads(5, 8, 8);

View File

@ -41,7 +41,12 @@ protected:
vis2_instructions = 7, vis2_instructions = 7,
sun4v_instructions = 8, sun4v_instructions = 8,
blk_init_instructions = 9, blk_init_instructions = 9,
fmaf_instructions = 10 fmaf_instructions = 10,
fmau_instructions = 11,
vis3_instructions = 12,
sparc64_family = 13,
T_family = 14,
T1_model = 15
}; };
enum Feature_Flag_Set { enum Feature_Flag_Set {
@ -59,6 +64,11 @@ protected:
sun4v_m = 1 << sun4v_instructions, sun4v_m = 1 << sun4v_instructions,
blk_init_instructions_m = 1 << blk_init_instructions, blk_init_instructions_m = 1 << blk_init_instructions,
fmaf_instructions_m = 1 << fmaf_instructions, fmaf_instructions_m = 1 << fmaf_instructions,
fmau_instructions_m = 1 << fmau_instructions,
vis3_instructions_m = 1 << vis3_instructions,
sparc64_family_m = 1 << sparc64_family,
T_family_m = 1 << T_family,
T1_model_m = 1 << T1_model,
generic_v8_m = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m, generic_v8_m = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m,
generic_v9_m = generic_v8_m | v9_instructions_m, generic_v9_m = generic_v8_m | v9_instructions_m,
@ -76,8 +86,13 @@ protected:
static int determine_features(); static int determine_features();
static int platform_features(int features); static int platform_features(int features);
static bool is_niagara1(int features) { return (features & sun4v_m) != 0; } // Returns true if the platform is in the niagara line (T series)
static bool is_sparc64(int features) { return (features & fmaf_instructions_m) != 0; } static bool is_T_family(int features) { return (features & T_family_m) != 0; }
static bool is_niagara() { return is_T_family(_features); }
DEBUG_ONLY( static bool is_niagara(int features) { return (features & sun4v_m) != 0; } )
// Returns true if it is niagara1 (T1).
static bool is_T1_model(int features) { return is_T_family(features) && ((features & T1_model_m) != 0); }
static int maximum_niagara1_processor_count() { return 32; } static int maximum_niagara1_processor_count() { return 32; }
@ -94,6 +109,7 @@ public:
static bool has_hardware_popc() { return (_features & hardware_popc_m) != 0; } static bool has_hardware_popc() { return (_features & hardware_popc_m) != 0; }
static bool has_vis1() { return (_features & vis1_instructions_m) != 0; } static bool has_vis1() { return (_features & vis1_instructions_m) != 0; }
static bool has_vis2() { return (_features & vis2_instructions_m) != 0; } static bool has_vis2() { return (_features & vis2_instructions_m) != 0; }
static bool has_vis3() { return (_features & vis3_instructions_m) != 0; }
static bool has_blk_init() { return (_features & blk_init_instructions_m) != 0; } static bool has_blk_init() { return (_features & blk_init_instructions_m) != 0; }
static bool supports_compare_and_exchange() static bool supports_compare_and_exchange()
@ -101,14 +117,14 @@ public:
static bool is_ultra3() { return (_features & ultra3_m) == ultra3_m; } static bool is_ultra3() { return (_features & ultra3_m) == ultra3_m; }
static bool is_sun4v() { return (_features & sun4v_m) != 0; } static bool is_sun4v() { return (_features & sun4v_m) != 0; }
static bool is_niagara1() { return is_niagara1(_features); } // Returns true if the platform is in the niagara line (T series)
// Returns true if the platform is in the niagara line and // and newer than the niagara1.
// newer than the niagara1. static bool is_niagara_plus() { return is_T_family(_features) && !is_T1_model(_features); }
static bool is_niagara1_plus(); // Fujitsu SPARC64
static bool is_sparc64() { return is_sparc64(_features); } static bool is_sparc64() { return (_features & sparc64_family_m) != 0; }
static bool has_fast_fxtof() { return has_v9() && !is_ultra3(); } static bool has_fast_fxtof() { return is_niagara() || is_sparc64() || has_v9() && !is_ultra3(); }
static bool has_fast_idiv() { return is_niagara1_plus() || is_sparc64(); } static bool has_fast_idiv() { return is_niagara_plus() || is_sparc64(); }
static const char* cpu_features() { return _features_str; } static const char* cpu_features() { return _features_str; }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -820,7 +820,20 @@ void Assembler::emit_farith(int b1, int b2, int i) {
} }
// Now the Assembler instruction (identical for 32/64 bits) // Now the Assembler instructions (identical for 32/64 bits)
void Assembler::adcl(Address dst, int32_t imm32) {
InstructionMark im(this);
prefix(dst);
emit_arith_operand(0x81, rdx, dst, imm32);
}
void Assembler::adcl(Address dst, Register src) {
InstructionMark im(this);
prefix(dst, src);
emit_byte(0x11);
emit_operand(src, dst);
}
void Assembler::adcl(Register dst, int32_t imm32) { void Assembler::adcl(Register dst, int32_t imm32) {
prefix(dst); prefix(dst);
@ -2195,9 +2208,7 @@ void Assembler::notl(Register dst) {
void Assembler::orl(Address dst, int32_t imm32) { void Assembler::orl(Address dst, int32_t imm32) {
InstructionMark im(this); InstructionMark im(this);
prefix(dst); prefix(dst);
emit_byte(0x81); emit_arith_operand(0x81, rcx, dst, imm32);
emit_operand(rcx, dst, 4);
emit_long(imm32);
} }
void Assembler::orl(Register dst, int32_t imm32) { void Assembler::orl(Register dst, int32_t imm32) {
@ -2205,7 +2216,6 @@ void Assembler::orl(Register dst, int32_t imm32) {
emit_arith(0x81, 0xC8, dst, imm32); emit_arith(0x81, 0xC8, dst, imm32);
} }
void Assembler::orl(Register dst, Address src) { void Assembler::orl(Register dst, Address src) {
InstructionMark im(this); InstructionMark im(this);
prefix(src, dst); prefix(src, dst);
@ -2213,7 +2223,6 @@ void Assembler::orl(Register dst, Address src) {
emit_operand(dst, src); emit_operand(dst, src);
} }
void Assembler::orl(Register dst, Register src) { void Assembler::orl(Register dst, Register src) {
(void) prefix_and_encode(dst->encoding(), src->encoding()); (void) prefix_and_encode(dst->encoding(), src->encoding());
emit_arith(0x0B, 0xC0, dst, src); emit_arith(0x0B, 0xC0, dst, src);
@ -2692,20 +2701,7 @@ void Assembler::stmxcsr( Address dst) {
void Assembler::subl(Address dst, int32_t imm32) { void Assembler::subl(Address dst, int32_t imm32) {
InstructionMark im(this); InstructionMark im(this);
prefix(dst); prefix(dst);
if (is8bit(imm32)) { emit_arith_operand(0x81, rbp, dst, imm32);
emit_byte(0x83);
emit_operand(rbp, dst, 1);
emit_byte(imm32 & 0xFF);
} else {
emit_byte(0x81);
emit_operand(rbp, dst, 4);
emit_long(imm32);
}
}
void Assembler::subl(Register dst, int32_t imm32) {
prefix(dst);
emit_arith(0x81, 0xE8, dst, imm32);
} }
void Assembler::subl(Address dst, Register src) { void Assembler::subl(Address dst, Register src) {
@ -2715,6 +2711,11 @@ void Assembler::subl(Address dst, Register src) {
emit_operand(src, dst); emit_operand(src, dst);
} }
void Assembler::subl(Register dst, int32_t imm32) {
prefix(dst);
emit_arith(0x81, 0xE8, dst, imm32);
}
void Assembler::subl(Register dst, Address src) { void Assembler::subl(Register dst, Address src) {
InstructionMark im(this); InstructionMark im(this);
prefix(src, dst); prefix(src, dst);
@ -4333,6 +4334,7 @@ void Assembler::sarq(Register dst) {
emit_byte(0xD3); emit_byte(0xD3);
emit_byte(0xF8 | encode); emit_byte(0xF8 | encode);
} }
void Assembler::sbbq(Address dst, int32_t imm32) { void Assembler::sbbq(Address dst, int32_t imm32) {
InstructionMark im(this); InstructionMark im(this);
prefixq(dst); prefixq(dst);
@ -4392,20 +4394,7 @@ void Assembler::shrq(Register dst) {
void Assembler::subq(Address dst, int32_t imm32) { void Assembler::subq(Address dst, int32_t imm32) {
InstructionMark im(this); InstructionMark im(this);
prefixq(dst); prefixq(dst);
if (is8bit(imm32)) { emit_arith_operand(0x81, rbp, dst, imm32);
emit_byte(0x83);
emit_operand(rbp, dst, 1);
emit_byte(imm32 & 0xFF);
} else {
emit_byte(0x81);
emit_operand(rbp, dst, 4);
emit_long(imm32);
}
}
void Assembler::subq(Register dst, int32_t imm32) {
(void) prefixq_and_encode(dst->encoding());
emit_arith(0x81, 0xE8, dst, imm32);
} }
void Assembler::subq(Address dst, Register src) { void Assembler::subq(Address dst, Register src) {
@ -4415,6 +4404,11 @@ void Assembler::subq(Address dst, Register src) {
emit_operand(src, dst); emit_operand(src, dst);
} }
void Assembler::subq(Register dst, int32_t imm32) {
(void) prefixq_and_encode(dst->encoding());
emit_arith(0x81, 0xE8, dst, imm32);
}
void Assembler::subq(Register dst, Address src) { void Assembler::subq(Register dst, Address src) {
InstructionMark im(this); InstructionMark im(this);
prefixq(src, dst); prefixq(src, dst);
@ -7136,7 +7130,7 @@ void MacroAssembler::tlab_allocate(Register obj,
} }
// Preserves rbx, and rdx. // Preserves rbx, and rdx.
void MacroAssembler::tlab_refill(Label& retry, Register MacroAssembler::tlab_refill(Label& retry,
Label& try_eden, Label& try_eden,
Label& slow_case) { Label& slow_case) {
Register top = rax; Register top = rax;
@ -7185,7 +7179,7 @@ void MacroAssembler::tlab_refill(Label& retry,
// if tlab is currently allocated (top or end != null) then // if tlab is currently allocated (top or end != null) then
// fill [top, end + alignment_reserve) with array object // fill [top, end + alignment_reserve) with array object
testptr (top, top); testptr(top, top);
jcc(Assembler::zero, do_refill); jcc(Assembler::zero, do_refill);
// set up the mark word // set up the mark word
@ -7197,16 +7191,20 @@ void MacroAssembler::tlab_refill(Label& retry,
movl(Address(top, arrayOopDesc::length_offset_in_bytes()), t1); movl(Address(top, arrayOopDesc::length_offset_in_bytes()), t1);
// set klass to intArrayKlass // set klass to intArrayKlass
// dubious reloc why not an oop reloc? // dubious reloc why not an oop reloc?
movptr(t1, ExternalAddress((address) Universe::intArrayKlassObj_addr())); movptr(t1, ExternalAddress((address)Universe::intArrayKlassObj_addr()));
// store klass last. concurrent gcs assumes klass length is valid if // store klass last. concurrent gcs assumes klass length is valid if
// klass field is not null. // klass field is not null.
store_klass(top, t1); store_klass(top, t1);
movptr(t1, top);
subptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_start_offset())));
incr_allocated_bytes(thread_reg, t1, 0);
// refill the tlab with an eden allocation // refill the tlab with an eden allocation
bind(do_refill); bind(do_refill);
movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_size_offset()))); movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_size_offset())));
shlptr(t1, LogHeapWordSize); shlptr(t1, LogHeapWordSize);
// add object_size ?? // allocate new tlab, address returned in top
eden_allocate(top, t1, 0, t2, slow_case); eden_allocate(top, t1, 0, t2, slow_case);
// Check that t1 was preserved in eden_allocate. // Check that t1 was preserved in eden_allocate.
@ -7234,6 +7232,34 @@ void MacroAssembler::tlab_refill(Label& retry,
movptr(Address(thread_reg, in_bytes(JavaThread::tlab_end_offset())), top); movptr(Address(thread_reg, in_bytes(JavaThread::tlab_end_offset())), top);
verify_tlab(); verify_tlab();
jmp(retry); jmp(retry);
return thread_reg; // for use by caller
}
void MacroAssembler::incr_allocated_bytes(Register thread,
Register var_size_in_bytes,
int con_size_in_bytes,
Register t1) {
#ifdef _LP64
if (var_size_in_bytes->is_valid()) {
addq(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), var_size_in_bytes);
} else {
addq(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), con_size_in_bytes);
}
#else
if (!thread->is_valid()) {
assert(t1->is_valid(), "need temp reg");
thread = t1;
get_thread(thread);
}
if (var_size_in_bytes->is_valid()) {
addl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), var_size_in_bytes);
} else {
addl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())), con_size_in_bytes);
}
adcl(Address(thread, in_bytes(JavaThread::allocated_bytes_offset())+4), 0);
#endif
} }
static const double pi_4 = 0.7853981633974483; static const double pi_4 = 0.7853981633974483;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -674,12 +674,14 @@ private:
// Utilities // Utilities
#ifdef _LP64 #ifdef _LP64
static bool is_simm(int64_t x, int nbits) { return -( CONST64(1) << (nbits-1) ) <= x && x < ( CONST64(1) << (nbits-1) ); } static bool is_simm(int64_t x, int nbits) { return -(CONST64(1) << (nbits-1)) <= x &&
x < (CONST64(1) << (nbits-1)); }
static bool is_simm32(int64_t x) { return x == (int64_t)(int32_t)x; } static bool is_simm32(int64_t x) { return x == (int64_t)(int32_t)x; }
#else #else
static bool is_simm(int32_t x, int nbits) { return -( 1 << (nbits-1) ) <= x && x < ( 1 << (nbits-1) ); } static bool is_simm(int32_t x, int nbits) { return -(1 << (nbits-1)) <= x &&
x < (1 << (nbits-1)); }
static bool is_simm32(int32_t x) { return true; } static bool is_simm32(int32_t x) { return true; }
#endif // LP64 #endif // _LP64
// Generic instructions // Generic instructions
// Does 32bit or 64bit as needed for the platform. In some sense these // Does 32bit or 64bit as needed for the platform. In some sense these
@ -705,7 +707,6 @@ private:
void push(void* v); void push(void* v);
void pop(void* v); void pop(void* v);
// These do register sized moves/scans // These do register sized moves/scans
void rep_mov(); void rep_mov();
void rep_set(); void rep_set();
@ -716,6 +717,8 @@ private:
// Vanilla instructions in lexical order // Vanilla instructions in lexical order
void adcl(Address dst, int32_t imm32);
void adcl(Address dst, Register src);
void adcl(Register dst, int32_t imm32); void adcl(Register dst, int32_t imm32);
void adcl(Register dst, Address src); void adcl(Register dst, Address src);
void adcl(Register dst, Register src); void adcl(Register dst, Register src);
@ -724,7 +727,6 @@ private:
void adcq(Register dst, Address src); void adcq(Register dst, Address src);
void adcq(Register dst, Register src); void adcq(Register dst, Register src);
void addl(Address dst, int32_t imm32); void addl(Address dst, int32_t imm32);
void addl(Address dst, Register src); void addl(Address dst, Register src);
void addl(Register dst, int32_t imm32); void addl(Register dst, int32_t imm32);
@ -737,7 +739,6 @@ private:
void addq(Register dst, Address src); void addq(Register dst, Address src);
void addq(Register dst, Register src); void addq(Register dst, Register src);
void addr_nop_4(); void addr_nop_4();
void addr_nop_5(); void addr_nop_5();
void addr_nop_7(); void addr_nop_7();
@ -759,7 +760,6 @@ private:
void andq(Register dst, Address src); void andq(Register dst, Address src);
void andq(Register dst, Register src); void andq(Register dst, Register src);
// Bitwise Logical AND of Packed Double-Precision Floating-Point Values // Bitwise Logical AND of Packed Double-Precision Floating-Point Values
void andpd(XMMRegister dst, Address src); void andpd(XMMRegister dst, Address src);
void andpd(XMMRegister dst, XMMRegister src); void andpd(XMMRegister dst, XMMRegister src);
@ -1857,7 +1857,10 @@ class MacroAssembler: public Assembler {
Register t2, // temp register Register t2, // temp register
Label& slow_case // continuation point if fast allocation fails Label& slow_case // continuation point if fast allocation fails
); );
void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); Register tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); // returns TLS address
void incr_allocated_bytes(Register thread,
Register var_size_in_bytes, int con_size_in_bytes,
Register t1 = noreg);
// interface method calling // interface method calling
void lookup_interface_method(Register recv_klass, void lookup_interface_method(Register recv_klass,

View File

@ -2036,7 +2036,7 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) {
} }
} }
void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result) { void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) {
Assembler::Condition acond, ncond; Assembler::Condition acond, ncond;
switch (condition) { switch (condition) {
case lir_cond_equal: acond = Assembler::equal; ncond = Assembler::notEqual; break; case lir_cond_equal: acond = Assembler::equal; ncond = Assembler::notEqual; break;

View File

@ -741,7 +741,7 @@ void LIRGenerator::do_AttemptUpdate(Intrinsic* x) {
// generate conditional move of boolean result // generate conditional move of boolean result
LIR_Opr result = rlock_result(x); LIR_Opr result = rlock_result(x);
__ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result, T_LONG);
} }
@ -810,7 +810,8 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
// generate conditional move of boolean result // generate conditional move of boolean result
LIR_Opr result = rlock_result(x); LIR_Opr result = rlock_result(x);
__ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0),
result, as_BasicType(type));
if (type == objectType) { // Write-barrier needed for Object fields. if (type == objectType) { // Write-barrier needed for Object fields.
// Seems to be precise // Seems to be precise
post_barrier(addr, val.result()); post_barrier(addr, val.result());

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -141,6 +141,7 @@ void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, i
tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case); tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
} else { } else {
eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case); eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
incr_allocated_bytes(noreg, var_size_in_bytes, con_size_in_bytes, t1);
} }
} }
@ -234,7 +235,7 @@ void C1_MacroAssembler::initialize_body(Register obj, Register len_in_bytes, int
void C1_MacroAssembler::allocate_object(Register obj, Register t1, Register t2, int header_size, int object_size, Register klass, Label& slow_case) { void C1_MacroAssembler::allocate_object(Register obj, Register t1, Register t2, int header_size, int object_size, Register klass, Label& slow_case) {
assert(obj == rax, "obj must be in rax, for cmpxchg"); assert(obj == rax, "obj must be in rax, for cmpxchg");
assert(obj != t1 && obj != t2 && t1 != t2, "registers must be different"); // XXX really? assert_different_registers(obj, t1, t2); // XXX really?
assert(header_size >= 0 && object_size >= header_size, "illegal sizes"); assert(header_size >= 0 && object_size >= header_size, "illegal sizes");
try_allocate(obj, noreg, object_size * BytesPerWord, t1, t2, slow_case); try_allocate(obj, noreg, object_size * BytesPerWord, t1, t2, slow_case);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -977,7 +977,6 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
// verify that that there is really a valid exception in rax, // verify that that there is really a valid exception in rax,
__ verify_not_null_oop(exception_oop); __ verify_not_null_oop(exception_oop);
oop_maps = new OopMapSet(); oop_maps = new OopMapSet();
OopMap* oop_map = generate_oop_map(sasm, 1); OopMap* oop_map = generate_oop_map(sasm, 1);
generate_handle_exception(sasm, oop_maps, oop_map); generate_handle_exception(sasm, oop_maps, oop_map);
@ -1037,13 +1036,16 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
// if we got here then the TLAB allocation failed, so try // if we got here then the TLAB allocation failed, so try
// refilling the TLAB or allocating directly from eden. // refilling the TLAB or allocating directly from eden.
Label retry_tlab, try_eden; Label retry_tlab, try_eden;
__ tlab_refill(retry_tlab, try_eden, slow_path); // does not destroy rdx (klass) const Register thread =
__ tlab_refill(retry_tlab, try_eden, slow_path); // does not destroy rdx (klass), returns rdi
__ bind(retry_tlab); __ bind(retry_tlab);
// get the instance size (size is postive so movl is fine for 64bit) // get the instance size (size is postive so movl is fine for 64bit)
__ movl(obj_size, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); __ movl(obj_size, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes()));
__ tlab_allocate(obj, obj_size, 0, t1, t2, slow_path); __ tlab_allocate(obj, obj_size, 0, t1, t2, slow_path);
__ initialize_object(obj, klass, obj_size, 0, t1, t2); __ initialize_object(obj, klass, obj_size, 0, t1, t2);
__ verify_oop(obj); __ verify_oop(obj);
__ pop(rbx); __ pop(rbx);
@ -1053,7 +1055,10 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ bind(try_eden); __ bind(try_eden);
// get the instance size (size is postive so movl is fine for 64bit) // get the instance size (size is postive so movl is fine for 64bit)
__ movl(obj_size, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); __ movl(obj_size, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes()));
__ eden_allocate(obj, obj_size, 0, t1, slow_path); __ eden_allocate(obj, obj_size, 0, t1, slow_path);
__ incr_allocated_bytes(thread, obj_size, 0);
__ initialize_object(obj, klass, obj_size, 0, t1, t2); __ initialize_object(obj, klass, obj_size, 0, t1, t2);
__ verify_oop(obj); __ verify_oop(obj);
__ pop(rbx); __ pop(rbx);
@ -1143,12 +1148,13 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
// if we got here then the TLAB allocation failed, so try // if we got here then the TLAB allocation failed, so try
// refilling the TLAB or allocating directly from eden. // refilling the TLAB or allocating directly from eden.
Label retry_tlab, try_eden; Label retry_tlab, try_eden;
__ tlab_refill(retry_tlab, try_eden, slow_path); // preserves rbx, & rdx const Register thread =
__ tlab_refill(retry_tlab, try_eden, slow_path); // preserves rbx & rdx, returns rdi
__ bind(retry_tlab); __ bind(retry_tlab);
// get the allocation size: round_up(hdr + length << (layout_helper & 0x1F)) // get the allocation size: round_up(hdr + length << (layout_helper & 0x1F))
// since size is postive movl does right thing on 64bit // since size is positive movl does right thing on 64bit
__ movl(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); __ movl(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes()));
// since size is postive movl does right thing on 64bit // since size is postive movl does right thing on 64bit
__ movl(arr_size, length); __ movl(arr_size, length);
@ -1175,7 +1181,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ bind(try_eden); __ bind(try_eden);
// get the allocation size: round_up(hdr + length << (layout_helper & 0x1F)) // get the allocation size: round_up(hdr + length << (layout_helper & 0x1F))
// since size is postive movl does right thing on 64bit // since size is positive movl does right thing on 64bit
__ movl(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); __ movl(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes()));
// since size is postive movl does right thing on 64bit // since size is postive movl does right thing on 64bit
__ movl(arr_size, length); __ movl(arr_size, length);
@ -1188,6 +1194,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ andptr(arr_size, ~MinObjAlignmentInBytesMask); __ andptr(arr_size, ~MinObjAlignmentInBytesMask);
__ eden_allocate(obj, arr_size, 0, t1, slow_path); // preserves arr_size __ eden_allocate(obj, arr_size, 0, t1, slow_path); // preserves arr_size
__ incr_allocated_bytes(thread, arr_size, 0);
__ initialize_header(obj, klass, length, t1, t2); __ initialize_header(obj, klass, length, t1, t2);
__ movb(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes() + (Klass::_lh_header_size_shift / BitsPerByte))); __ movb(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes() + (Klass::_lh_header_size_shift / BitsPerByte)));

View File

@ -385,9 +385,12 @@ int MethodHandles::adapter_conversion_ops_supported_mask() {
// FIXME: MethodHandlesTest gets a crash if we enable OP_SPREAD_ARGS. // FIXME: MethodHandlesTest gets a crash if we enable OP_SPREAD_ARGS.
} }
//------------------------------------------------------------------------------
// MethodHandles::generate_method_handle_stub
//
// Generate an "entry" field for a method handle. // Generate an "entry" field for a method handle.
// This determines how the method handle will respond to calls. // This determines how the method handle will respond to calls.
void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) { void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek, TRAPS) {
// Here is the register state during an interpreted call, // Here is the register state during an interpreted call,
// as set up by generate_method_handle_interpreter_entry(): // as set up by generate_method_handle_interpreter_entry():
// - rbx: garbage temp (was MethodHandle.invoke methodOop, unused) // - rbx: garbage temp (was MethodHandle.invoke methodOop, unused)
@ -396,14 +399,21 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
// - rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted) // - rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted)
// - rdx: garbage temp, can blow away // - rdx: garbage temp, can blow away
Register rcx_recv = rcx; const Register rcx_recv = rcx;
Register rax_argslot = rax; const Register rax_argslot = rax;
Register rbx_temp = rbx; const Register rbx_temp = rbx;
Register rdx_temp = rdx; const Register rdx_temp = rdx;
// This guy is set up by prepare_to_jump_from_interpreted (from interpreted calls) // This guy is set up by prepare_to_jump_from_interpreted (from interpreted calls)
// and gen_c2i_adapter (from compiled calls): // and gen_c2i_adapter (from compiled calls):
Register saved_last_sp = LP64_ONLY(r13) NOT_LP64(rsi); const Register saved_last_sp = LP64_ONLY(r13) NOT_LP64(rsi);
// Argument registers for _raise_exception.
// 32-bit: Pass first two oop/int args in registers ECX and EDX.
const Register rarg0_code = LP64_ONLY(j_rarg0) NOT_LP64(rcx);
const Register rarg1_actual = LP64_ONLY(j_rarg1) NOT_LP64(rdx);
const Register rarg2_required = LP64_ONLY(j_rarg2) NOT_LP64(rdi);
assert_different_registers(rarg0_code, rarg1_actual, rarg2_required, saved_last_sp);
guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets");
@ -437,47 +447,41 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
switch ((int) ek) { switch ((int) ek) {
case _raise_exception: case _raise_exception:
{ {
// Not a real MH entry, but rather shared code for raising an exception. // Not a real MH entry, but rather shared code for raising an
// Extra local arguments are pushed on stack, as required type at TOS+8, // exception. Since we use a C2I adapter to set up the
// failing object (or NULL) at TOS+4, failing bytecode type at TOS. // interpreter state, arguments are expected in compiler
// Beyond those local arguments are the PC, of course. // argument registers.
Register rdx_code = rdx_temp; methodHandle mh(raise_exception_method());
Register rcx_fail = rcx_recv; address c2i_entry = methodOopDesc::make_adapters(mh, CHECK);
Register rax_want = rax_argslot;
Register rdi_pc = rdi; const Register rdi_pc = rax;
__ pop(rdx_code); // TOS+0
__ pop(rcx_fail); // TOS+4
__ pop(rax_want); // TOS+8
__ pop(rdi_pc); // caller PC __ pop(rdi_pc); // caller PC
__ mov(rsp, saved_last_sp); // cut the stack back to where the caller started
__ mov(rsp, rsi); // cut the stack back to where the caller started
// Repush the arguments as if coming from the interpreter.
__ push(rdx_code);
__ push(rcx_fail);
__ push(rax_want);
Register rbx_method = rbx_temp; Register rbx_method = rbx_temp;
Label no_method; Label L_no_method;
// FIXME: fill in _raise_exception_method with a suitable sun.dyn method // FIXME: fill in _raise_exception_method with a suitable sun.dyn method
__ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method)); __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method));
__ testptr(rbx_method, rbx_method); __ testptr(rbx_method, rbx_method);
__ jccb(Assembler::zero, no_method); __ jccb(Assembler::zero, L_no_method);
int jobject_oop_offset = 0;
const int jobject_oop_offset = 0;
__ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject
__ testptr(rbx_method, rbx_method); __ testptr(rbx_method, rbx_method);
__ jccb(Assembler::zero, no_method); __ jccb(Assembler::zero, L_no_method);
__ verify_oop(rbx_method); __ verify_oop(rbx_method);
__ push(rdi_pc); // and restore caller PC
__ jmp(rbx_method_fie); // 32-bit: push remaining arguments as if coming from the compiler.
NOT_LP64(__ push(rarg2_required));
__ push(rdi_pc); // restore caller PC
__ jump(ExternalAddress(c2i_entry)); // do C2I transition
// If we get here, the Java runtime did not do its job of creating the exception. // If we get here, the Java runtime did not do its job of creating the exception.
// Do something that is at least causes a valid throw from the interpreter. // Do something that is at least causes a valid throw from the interpreter.
__ bind(no_method); __ bind(L_no_method);
__ pop(rax_want); __ push(rarg2_required);
__ pop(rcx_fail); __ push(rarg1_actual);
__ push(rax_want);
__ push(rcx_fail);
__ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
} }
break; break;
@ -572,9 +576,11 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ bind(no_such_interface); __ bind(no_such_interface);
// Throw an exception. // Throw an exception.
// For historical reasons, it will be IncompatibleClassChangeError. // For historical reasons, it will be IncompatibleClassChangeError.
__ pushptr(Address(rdx_intf, java_mirror_offset)); // required interface __ mov(rbx_temp, rcx_recv); // rarg2_required might be RCX
__ push(rcx_recv); // bad receiver assert_different_registers(rarg2_required, rbx_temp);
__ push((int)Bytecodes::_invokeinterface); // who is complaining? __ movptr(rarg2_required, Address(rdx_intf, java_mirror_offset)); // required interface
__ mov( rarg1_actual, rbx_temp); // bad receiver
__ movl( rarg0_code, (int) Bytecodes::_invokeinterface); // who is complaining?
__ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); __ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
} }
break; break;
@ -669,10 +675,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ movl(rax_argslot, rcx_amh_vmargslot); // reload argslot field __ movl(rax_argslot, rcx_amh_vmargslot); // reload argslot field
__ movptr(rdx_temp, vmarg); __ movptr(rdx_temp, vmarg);
__ load_heap_oop(rbx_klass, rcx_amh_argument); // required class assert_different_registers(rarg2_required, rdx_temp);
__ push(rbx_klass); __ load_heap_oop(rarg2_required, rcx_amh_argument); // required class
__ push(rdx_temp); // bad object __ mov( rarg1_actual, rdx_temp); // bad object
__ push((int)Bytecodes::_checkcast); // who is complaining? __ movl( rarg0_code, (int) Bytecodes::_checkcast); // who is complaining?
__ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); __ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
__ bind(done); __ bind(done);
@ -1189,16 +1195,18 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ bind(bad_array_klass); __ bind(bad_array_klass);
UNPUSH_RSI_RDI; UNPUSH_RSI_RDI;
__ pushptr(Address(rdx_array_klass, java_mirror_offset)); // required type assert(!vmarg.uses(rarg2_required), "must be different registers");
__ pushptr(vmarg); // bad array __ movptr(rarg2_required, Address(rdx_array_klass, java_mirror_offset)); // required type
__ push((int)Bytecodes::_aaload); // who is complaining? __ movptr(rarg1_actual, vmarg); // bad array
__ movl( rarg0_code, (int) Bytecodes::_aaload); // who is complaining?
__ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); __ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
__ bind(bad_array_length); __ bind(bad_array_length);
UNPUSH_RSI_RDI; UNPUSH_RSI_RDI;
__ push(rcx_recv); // AMH requiring a certain length assert(!vmarg.uses(rarg2_required), "must be different registers");
__ pushptr(vmarg); // bad array __ mov (rarg2_required, rcx_recv); // AMH requiring a certain length
__ push((int)Bytecodes::_arraylength); // who is complaining? __ movptr(rarg1_actual, vmarg); // bad array
__ movl( rarg0_code, (int) Bytecodes::_arraylength); // who is complaining?
__ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); __ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
#undef UNPUSH_RSI_RDI #undef UNPUSH_RSI_RDI

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -3203,10 +3203,12 @@ void TemplateTable::_new() {
const bool allow_shared_alloc = const bool allow_shared_alloc =
Universe::heap()->supports_inline_contig_alloc() && !CMSIncrementalMode; Universe::heap()->supports_inline_contig_alloc() && !CMSIncrementalMode;
if (UseTLAB) {
const Register thread = rcx; const Register thread = rcx;
if (UseTLAB || allow_shared_alloc) {
__ get_thread(thread); __ get_thread(thread);
}
if (UseTLAB) {
__ movptr(rax, Address(thread, in_bytes(JavaThread::tlab_top_offset()))); __ movptr(rax, Address(thread, in_bytes(JavaThread::tlab_top_offset())));
__ lea(rbx, Address(rax, rdx, Address::times_1)); __ lea(rbx, Address(rax, rdx, Address::times_1));
__ cmpptr(rbx, Address(thread, in_bytes(JavaThread::tlab_end_offset()))); __ cmpptr(rbx, Address(thread, in_bytes(JavaThread::tlab_end_offset())));
@ -3247,6 +3249,8 @@ void TemplateTable::_new() {
// if someone beat us on the allocation, try again, otherwise continue // if someone beat us on the allocation, try again, otherwise continue
__ jcc(Assembler::notEqual, retry); __ jcc(Assembler::notEqual, retry);
__ incr_allocated_bytes(thread, rdx, 0);
} }
if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) { if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -3266,6 +3266,8 @@ void TemplateTable::_new() {
// if someone beat us on the allocation, try again, otherwise continue // if someone beat us on the allocation, try again, otherwise continue
__ jcc(Assembler::notEqual, retry); __ jcc(Assembler::notEqual, retry);
__ incr_allocated_bytes(r15_thread, rdx, 0);
} }
if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) { if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) {

View File

@ -635,7 +635,29 @@ static int create_sharedmem_resources(const char* dirname, const char* filename,
return -1; return -1;
} }
// 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; return fd;
} else {
RESTARTABLE(::close(fd), result);
return -1;
}
} }
// open the shared memory file for the given user and vmid. returns // open the shared memory file for the given user and vmid. returns

View File

@ -28,7 +28,6 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <fcntl.h> #include <fcntl.h>
#include <inttypes.h> #include <inttypes.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -80,6 +80,7 @@
// put OS-includes here // put OS-includes here
# include <dlfcn.h> # include <dlfcn.h>
# include <errno.h> # include <errno.h>
# include <exception>
# include <link.h> # include <link.h>
# include <poll.h> # include <poll.h>
# include <pthread.h> # include <pthread.h>
@ -282,7 +283,7 @@ Thread* ThreadLocalStorage::get_thread_via_cache_slowly(uintptr_t raw_id,
is_error_reported(), is_error_reported(),
"sp must be inside of selected thread stack"); "sp must be inside of selected thread stack");
thread->_self_raw_id = raw_id; // mark for quick retrieval thread->set_self_raw_id(raw_id); // mark for quick retrieval
_get_thread_cache[ index ] = thread; _get_thread_cache[ index ] = thread;
} }
return thread; return thread;
@ -1475,6 +1476,13 @@ sigset_t* os::Solaris::allowdebug_blocked_signals() {
return &allowdebug_blocked_sigs; 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. // First crack at OS-specific initialization, from inside the new thread.
void os::initialize_thread() { void os::initialize_thread() {
int r = thr_main() ; int r = thr_main() ;
@ -1564,6 +1572,7 @@ void os::initialize_thread() {
// use the dynamic check for T2 libthread. // use the dynamic check for T2 libthread.
os::Solaris::init_thread_fpu_state(); os::Solaris::init_thread_fpu_state();
std::set_terminate(_handle_uncaught_cxx_exception);
} }
@ -3081,7 +3090,7 @@ char* os::attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
if (addr == NULL) { if (addr == NULL) {
jio_snprintf(buf, sizeof(buf), ": %s", strerror(err)); jio_snprintf(buf, sizeof(buf), ": %s", strerror(err));
} }
warning("attempt_reserve_memory_at: couldn't reserve %d bytes at " warning("attempt_reserve_memory_at: couldn't reserve " SIZE_FORMAT " bytes at "
PTR_FORMAT ": reserve_memory_helper returned " PTR_FORMAT PTR_FORMAT ": reserve_memory_helper returned " PTR_FORMAT
"%s", bytes, requested_addr, addr, buf); "%s", bytes, requested_addr, addr, buf);
} }
@ -5188,7 +5197,7 @@ int os::open(const char *path, int oflag, int mode) {
int o_delete = (oflag & O_DELETE); int o_delete = (oflag & O_DELETE);
oflag = oflag & ~O_DELETE; oflag = oflag & ~O_DELETE;
fd = ::open(path, oflag, mode); fd = ::open64(path, oflag, mode);
if (fd == -1) return -1; if (fd == -1) return -1;
//If the open succeeded, the file might still be a directory //If the open succeeded, the file might still be a directory

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -53,10 +53,10 @@ inline Thread* ThreadLocalStorage::thread() {
uintptr_t raw = pd_raw_thread_id(); uintptr_t raw = pd_raw_thread_id();
int ix = pd_cache_index(raw); int ix = pd_cache_index(raw);
Thread *Candidate = ThreadLocalStorage::_get_thread_cache[ix]; Thread* candidate = ThreadLocalStorage::_get_thread_cache[ix];
if (Candidate->_self_raw_id == raw) { if (candidate->self_raw_id() == raw) {
// hit // hit
return Candidate; return candidate;
} else { } else {
return ThreadLocalStorage::get_thread_via_cache_slowly(raw, ix); return ThreadLocalStorage::get_thread_via_cache_slowly(raw, ix);
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -2004,6 +2004,16 @@ struct siglabel {
int number; 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[] = { struct siglabel exceptlabels[] = {
def_excpt(EXCEPTION_ACCESS_VIOLATION), def_excpt(EXCEPTION_ACCESS_VIOLATION),
def_excpt(EXCEPTION_DATATYPE_MISALIGNMENT), def_excpt(EXCEPTION_DATATYPE_MISALIGNMENT),
@ -2028,6 +2038,7 @@ struct siglabel exceptlabels[] = {
def_excpt(EXCEPTION_INVALID_DISPOSITION), def_excpt(EXCEPTION_INVALID_DISPOSITION),
def_excpt(EXCEPTION_GUARD_PAGE), def_excpt(EXCEPTION_GUARD_PAGE),
def_excpt(EXCEPTION_INVALID_HANDLE), def_excpt(EXCEPTION_INVALID_HANDLE),
def_excpt(EXCEPTION_UNCAUGHT_CXX_EXCEPTION),
NULL, 0 NULL, 0
}; };
@ -2261,7 +2272,6 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
} }
} }
if (t != NULL && t->is_Java_thread()) { if (t != NULL && t->is_Java_thread()) {
JavaThread* thread = (JavaThread*) t; JavaThread* thread = (JavaThread*) t;
bool in_java = thread->thread_state() == _thread_in_Java; bool in_java = thread->thread_state() == _thread_in_Java;
@ -2465,8 +2475,9 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
} // switch } // switch
} }
#ifndef _WIN64 #ifndef _WIN64
if ((thread->thread_state() == _thread_in_Java) || if (((thread->thread_state() == _thread_in_Java) ||
(thread->thread_state() == _thread_in_native) ) (thread->thread_state() == _thread_in_native)) &&
exception_code != EXCEPTION_UNCAUGHT_CXX_EXCEPTION)
{ {
LONG result=Handle_FLT_Exception(exceptionInfo); LONG result=Handle_FLT_Exception(exceptionInfo);
if (result==EXCEPTION_CONTINUE_EXECUTION) return result; if (result==EXCEPTION_CONTINUE_EXECUTION) return result;
@ -2490,6 +2501,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
case EXCEPTION_ILLEGAL_INSTRUCTION_2: case EXCEPTION_ILLEGAL_INSTRUCTION_2:
case EXCEPTION_INT_OVERFLOW: case EXCEPTION_INT_OVERFLOW:
case EXCEPTION_INT_DIVIDE_BY_ZERO: case EXCEPTION_INT_DIVIDE_BY_ZERO:
case EXCEPTION_UNCAUGHT_CXX_EXCEPTION:
{ report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord, { report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord,
exceptionInfo->ContextRecord); exceptionInfo->ContextRecord);
} }

View File

@ -585,6 +585,13 @@ int JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, int abort_
sigaddset(&newset, sig); sigaddset(&newset, sig);
sigprocmask(SIG_UNBLOCK, &newset, NULL); sigprocmask(SIG_UNBLOCK, &newset, NULL);
// Determine which sort of error to throw. Out of swap may signal
// on the thread stack, which could get a mapping error when touched.
address addr = (address) info->si_addr;
if (sig == SIGBUS && info->si_code == BUS_OBJERR && info->si_errno == ENOMEM) {
vm_exit_out_of_memory(0, "Out of swap space to map in thread stack.");
}
VMError err(t, sig, pc, info, ucVoid); VMError err(t, sig, pc, info, ucVoid);
err.report_and_die(); err.report_and_die();

View File

@ -29,6 +29,7 @@
# include <sys/auxv.h> # include <sys/auxv.h>
# include <sys/auxv_SPARC.h> # include <sys/auxv_SPARC.h>
# include <sys/systeminfo.h> # include <sys/systeminfo.h>
# include <kstat.h>
// We need to keep these here as long as we have to build on Solaris // We need to keep these here as long as we have to build on Solaris
// versions before 10. // versions before 10.
@ -95,12 +96,24 @@ int VM_Version::platform_features(int features) {
// but Solaris 8 is used for jdk6 update builds. // but Solaris 8 is used for jdk6 update builds.
#ifndef AV_SPARC_ASI_BLK_INIT #ifndef AV_SPARC_ASI_BLK_INIT
#define AV_SPARC_ASI_BLK_INIT 0x0080 /* ASI_BLK_INIT_xxx ASI */ #define AV_SPARC_ASI_BLK_INIT 0x0080 /* ASI_BLK_INIT_xxx ASI */
#endif
#ifndef AV_SPARC_FMAF
#define AV_SPARC_FMAF 0x0100 /* Sparc64 Fused Multiply-Add */
#endif #endif
if (av & AV_SPARC_ASI_BLK_INIT) features |= blk_init_instructions_m; if (av & AV_SPARC_ASI_BLK_INIT) features |= blk_init_instructions_m;
#ifndef AV_SPARC_FMAF
#define AV_SPARC_FMAF 0x0100 /* Fused Multiply-Add */
#endif
if (av & AV_SPARC_FMAF) features |= fmaf_instructions_m; if (av & AV_SPARC_FMAF) features |= fmaf_instructions_m;
#ifndef AV_SPARC_FMAU
#define AV_SPARC_FMAU 0x0200 /* Unfused Multiply-Add */
#endif
if (av & AV_SPARC_FMAU) features |= fmau_instructions_m;
#ifndef AV_SPARC_VIS3
#define AV_SPARC_VIS3 0x0400 /* VIS3 instruction set extensions */
#endif
if (av & AV_SPARC_VIS3) features |= vis3_instructions_m;
} else { } else {
// getisax(2) failed, use the old legacy code. // getisax(2) failed, use the old legacy code.
#ifndef PRODUCT #ifndef PRODUCT
@ -140,5 +153,59 @@ int VM_Version::platform_features(int features) {
// Determine the machine type. // Determine the machine type.
do_sysinfo(SI_MACHINE, "sun4v", &features, sun4v_m); do_sysinfo(SI_MACHINE, "sun4v", &features, sun4v_m);
{
// Using kstat to determine the machine type.
kstat_ctl_t* kc = kstat_open();
kstat_t* ksp = kstat_lookup(kc, (char*)"cpu_info", -1, NULL);
const char* implementation = "UNKNOWN";
if (ksp != NULL) {
if (kstat_read(kc, ksp, NULL) != -1 && ksp->ks_data != NULL) {
kstat_named_t* knm = (kstat_named_t *)ksp->ks_data;
for (int i = 0; i < ksp->ks_ndata; i++) {
if (strcmp((const char*)&(knm[i].name),"implementation") == 0) {
#ifndef KSTAT_DATA_STRING
#define KSTAT_DATA_STRING 9
#endif
if (knm[i].data_type == KSTAT_DATA_CHAR) {
// VM is running on Solaris 8 which does not have value.str.
implementation = &(knm[i].value.c[0]);
} else if (knm[i].data_type == KSTAT_DATA_STRING) {
// VM is running on Solaris 10.
#ifndef KSTAT_NAMED_STR_PTR
// Solaris 8 was used to build VM, define the structure it misses.
struct str_t {
union {
char *ptr; /* NULL-term string */
char __pad[8]; /* 64-bit padding */
} addr;
uint32_t len; /* # bytes for strlen + '\0' */
};
#define KSTAT_NAMED_STR_PTR(knptr) (( (str_t*)&((knptr)->value) )->addr.ptr)
#endif
implementation = KSTAT_NAMED_STR_PTR(&knm[i]);
}
#ifndef PRODUCT
if (PrintMiscellaneous && Verbose) {
tty->print_cr("cpu_info.implementation: %s", implementation);
}
#endif
if (strncmp(implementation, "SPARC64", 7) == 0) {
features |= sparc64_family_m;
} else if (strncmp(implementation, "UltraSPARC-T", 12) == 0) {
features |= T_family_m;
if (strncmp(implementation, "UltraSPARC-T1", 13) == 0) {
features |= T1_model_m;
}
}
break;
}
} // for(
}
}
assert(strcmp(implementation, "UNKNOWN") != 0,
"unknown cpu info (changed kstat interface?)");
kstat_close(kc);
}
return features; return features;
} }

View File

@ -742,6 +742,13 @@ int JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, int abort_
sigaddset(&newset, sig); sigaddset(&newset, sig);
sigprocmask(SIG_UNBLOCK, &newset, NULL); sigprocmask(SIG_UNBLOCK, &newset, NULL);
// Determine which sort of error to throw. Out of swap may signal
// on the thread stack, which could get a mapping error when touched.
address addr = (address) info->si_addr;
if (sig == SIGBUS && info->si_code == BUS_OBJERR && info->si_errno == ENOMEM) {
vm_exit_out_of_memory(0, "Out of swap space to map in thread stack.");
}
VMError err(t, sig, pc, info, ucVoid); VMError err(t, sig, pc, info, ucVoid);
err.report_and_die(); err.report_and_die();

View File

@ -34,7 +34,7 @@
#define MAXID 20 #define MAXID 20
static char initflag = 0; // True after 1st initialization static char initflag = 0; // True after 1st initialization
static char shft[MAXID] = {1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6}; static char shft[MAXID] = {1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6};
static short xsum[MAXID + 1]; static short xsum[MAXID];
//------------------------------bucket--------------------------------------- //------------------------------bucket---------------------------------------
class bucket { class bucket {
@ -66,7 +66,7 @@ void Dict::init() {
// Precompute table of null character hashes // Precompute table of null character hashes
if( !initflag ) { // Not initializated yet? if( !initflag ) { // Not initializated yet?
xsum[0] = (1<<shft[0])+1; // Initialize xsum[0] = (1<<shft[0])+1; // Initialize
for( i = 1; i < MAXID + 1; i++) { for( i = 1; i < MAXID; i++) {
xsum[i] = (1<<shft[i])+1+xsum[i-1]; xsum[i] = (1<<shft[i])+1+xsum[i-1];
} }
initflag = 1; // Never again initflag = 1; // Never again
@ -291,7 +291,7 @@ int hashstr(const void *t) {
c = (c<<1)+1; // Characters are always odd! c = (c<<1)+1; // Characters are always odd!
sum += c + (c<<shft[k++]); // Universal hash function sum += c + (c<<shft[k++]); // Universal hash function
} }
assert( k < (MAXID + 1), "Exceeded maximum name length"); assert( k < (MAXID), "Exceeded maximum name length");
return (int)((sum+xsum[k]) >> 1); // Hash key, un-modulo'd table size return (int)((sum+xsum[k]) >> 1); // Hash key, un-modulo'd table size
} }

View File

@ -245,7 +245,7 @@ void Compilation::emit_code_epilog(LIR_Assembler* assembler) {
} }
void Compilation::setup_code_buffer(CodeBuffer* code, int call_stub_estimate) { bool Compilation::setup_code_buffer(CodeBuffer* code, int call_stub_estimate) {
// Preinitialize the consts section to some large size: // Preinitialize the consts section to some large size:
int locs_buffer_size = 20 * (relocInfo::length_limit + sizeof(relocInfo)); int locs_buffer_size = 20 * (relocInfo::length_limit + sizeof(relocInfo));
char* locs_buffer = NEW_RESOURCE_ARRAY(char, locs_buffer_size); char* locs_buffer = NEW_RESOURCE_ARRAY(char, locs_buffer_size);
@ -253,15 +253,20 @@ void Compilation::setup_code_buffer(CodeBuffer* code, int call_stub_estimate) {
locs_buffer_size / sizeof(relocInfo)); locs_buffer_size / sizeof(relocInfo));
code->initialize_consts_size(Compilation::desired_max_constant_size()); code->initialize_consts_size(Compilation::desired_max_constant_size());
// Call stubs + two deopt handlers (regular and MH) + exception handler // Call stubs + two deopt handlers (regular and MH) + exception handler
code->initialize_stubs_size((call_stub_estimate * LIR_Assembler::call_stub_size) + int stub_size = (call_stub_estimate * LIR_Assembler::call_stub_size) +
LIR_Assembler::exception_handler_size + LIR_Assembler::exception_handler_size +
2 * LIR_Assembler::deopt_handler_size); (2 * LIR_Assembler::deopt_handler_size);
if (stub_size >= code->insts_capacity()) return false;
code->initialize_stubs_size(stub_size);
return true;
} }
int Compilation::emit_code_body() { int Compilation::emit_code_body() {
// emit code // emit code
setup_code_buffer(code(), allocator()->num_calls()); if (!setup_code_buffer(code(), allocator()->num_calls())) {
BAILOUT_("size requested greater than avail code buffer size", 0);
}
code()->initialize_oop_recorder(env()->oop_recorder()); code()->initialize_oop_recorder(env()->oop_recorder());
_masm = new C1_MacroAssembler(code()); _masm = new C1_MacroAssembler(code());

View File

@ -192,7 +192,7 @@ class Compilation: public StackObj {
return desired_max_code_buffer_size() / 10; return desired_max_code_buffer_size() / 10;
} }
static void setup_code_buffer(CodeBuffer* cb, int call_stub_estimate); static bool setup_code_buffer(CodeBuffer* cb, int call_stub_estimate);
// timers // timers
static void print_timers(); static void print_timers();

View File

@ -92,7 +92,7 @@ CallingConvention* FrameMap::java_calling_convention(const BasicTypeArray* signa
if (opr->is_address()) { if (opr->is_address()) {
LIR_Address* addr = opr->as_address_ptr(); LIR_Address* addr = opr->as_address_ptr();
assert(addr->disp() == (int)addr->disp(), "out of range value"); assert(addr->disp() == (int)addr->disp(), "out of range value");
out_preserve = MAX2(out_preserve, (intptr_t)addr->disp() / 4); out_preserve = MAX2(out_preserve, (intptr_t)(addr->disp() - STACK_BIAS) / 4);
} }
i += type2size[t]; i += type2size[t];
} }
@ -143,7 +143,7 @@ CallingConvention* FrameMap::c_calling_convention(const BasicTypeArray* signatur
args->append(opr); args->append(opr);
if (opr->is_address()) { if (opr->is_address()) {
LIR_Address* addr = opr->as_address_ptr(); LIR_Address* addr = opr->as_address_ptr();
out_preserve = MAX2(out_preserve, (intptr_t)addr->disp() / 4); out_preserve = MAX2(out_preserve, (intptr_t)(addr->disp() - STACK_BIAS) / 4);
} }
i += type2size[t]; i += type2size[t];
} }

View File

@ -1568,15 +1568,16 @@ class LIR_Op2: public LIR_Op {
assert(code == lir_cmp, "code check"); assert(code == lir_cmp, "code check");
} }
LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result) LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type)
: LIR_Op(code, result, NULL) : LIR_Op(code, result, NULL)
, _opr1(opr1) , _opr1(opr1)
, _opr2(opr2) , _opr2(opr2)
, _type(T_ILLEGAL) , _type(type)
, _condition(condition) , _condition(condition)
, _fpu_stack_size(0) , _fpu_stack_size(0)
, _tmp(LIR_OprFact::illegalOpr) { , _tmp(LIR_OprFact::illegalOpr) {
assert(code == lir_cmove, "code check"); assert(code == lir_cmove, "code check");
assert(type != T_ILLEGAL, "cmove should have type");
} }
LIR_Op2(LIR_Code code, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result = LIR_OprFact::illegalOpr, LIR_Op2(LIR_Code code, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result = LIR_OprFact::illegalOpr,
@ -1993,8 +1994,8 @@ class LIR_List: public CompilationResourceObj {
void cmp_mem_int(LIR_Condition condition, LIR_Opr base, int disp, int c, CodeEmitInfo* info); void cmp_mem_int(LIR_Condition condition, LIR_Opr base, int disp, int c, CodeEmitInfo* info);
void cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Address* addr, CodeEmitInfo* info); void cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Address* addr, CodeEmitInfo* info);
void cmove(LIR_Condition condition, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst) { void cmove(LIR_Condition condition, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst, BasicType type) {
append(new LIR_Op2(lir_cmove, condition, src1, src2, dst)); append(new LIR_Op2(lir_cmove, condition, src1, src2, dst, type));
} }
void cas_long(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value, void cas_long(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value,

View File

@ -685,7 +685,7 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) {
break; break;
case lir_cmove: case lir_cmove:
cmove(op->condition(), op->in_opr1(), op->in_opr2(), op->result_opr()); cmove(op->condition(), op->in_opr1(), op->in_opr2(), op->result_opr(), op->type());
break; break;
case lir_shl: case lir_shl:

View File

@ -217,7 +217,7 @@ class LIR_Assembler: public CompilationResourceObj {
void volatile_move_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); void volatile_move_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info);
void comp_mem_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); // info set for null exceptions void comp_mem_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); // info set for null exceptions
void comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr result, LIR_Op2* op); void comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr result, LIR_Op2* op);
void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result); void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result, BasicType type);
void call( LIR_OpJavaCall* op, relocInfo::relocType rtype); void call( LIR_OpJavaCall* op, relocInfo::relocType rtype);
void ic_call( LIR_OpJavaCall* op); void ic_call( LIR_OpJavaCall* op);

View File

@ -856,7 +856,7 @@ void LIRGenerator::profile_branch(If* if_instr, If::Condition cond) {
__ cmove(lir_cond(cond), __ cmove(lir_cond(cond),
LIR_OprFact::intptrConst(taken_count_offset), LIR_OprFact::intptrConst(taken_count_offset),
LIR_OprFact::intptrConst(not_taken_count_offset), LIR_OprFact::intptrConst(not_taken_count_offset),
data_offset_reg); data_offset_reg, as_BasicType(if_instr->x()->type()));
// MDO cells are intptr_t, so the data_reg width is arch-dependent. // MDO cells are intptr_t, so the data_reg width is arch-dependent.
LIR_Opr data_reg = new_pointer_register(); LIR_Opr data_reg = new_pointer_register();
@ -2591,7 +2591,7 @@ void LIRGenerator::do_IfOp(IfOp* x) {
LIR_Opr reg = rlock_result(x); LIR_Opr reg = rlock_result(x);
__ cmp(lir_cond(x->cond()), left.result(), right.result()); __ cmp(lir_cond(x->cond()), left.result(), right.result());
__ cmove(lir_cond(x->cond()), t_val.result(), f_val.result(), reg); __ cmove(lir_cond(x->cond()), t_val.result(), f_val.result(), reg, as_BasicType(x->x()->type()));
} }

View File

@ -90,6 +90,7 @@ LinearScan::LinearScan(IR* ir, LIRGenerator* gen, FrameMap* frame_map)
, _intervals(0) // initialized later with correct length , _intervals(0) // initialized later with correct length
, _new_intervals_from_allocation(new IntervalList()) , _new_intervals_from_allocation(new IntervalList())
, _sorted_intervals(NULL) , _sorted_intervals(NULL)
, _needs_full_resort(false)
, _lir_ops(0) // initialized later with correct length , _lir_ops(0) // initialized later with correct length
, _block_of_op(0) // initialized later with correct length , _block_of_op(0) // initialized later with correct length
, _has_info(0) , _has_info(0)
@ -1520,6 +1521,14 @@ void LinearScan::create_unhandled_lists(Interval** list1, Interval** list2, bool
void LinearScan::sort_intervals_before_allocation() { void LinearScan::sort_intervals_before_allocation() {
TIME_LINEAR_SCAN(timer_sort_intervals_before); TIME_LINEAR_SCAN(timer_sort_intervals_before);
if (_needs_full_resort) {
// There is no known reason why this should occur but just in case...
assert(false, "should never occur");
// Re-sort existing interval list because an Interval::from() has changed
_sorted_intervals->sort(interval_cmp);
_needs_full_resort = false;
}
IntervalList* unsorted_list = &_intervals; IntervalList* unsorted_list = &_intervals;
int unsorted_len = unsorted_list->length(); int unsorted_len = unsorted_list->length();
int sorted_len = 0; int sorted_len = 0;
@ -1559,11 +1568,18 @@ void LinearScan::sort_intervals_before_allocation() {
} }
} }
_sorted_intervals = sorted_list; _sorted_intervals = sorted_list;
assert(is_sorted(_sorted_intervals), "intervals unsorted");
} }
void LinearScan::sort_intervals_after_allocation() { void LinearScan::sort_intervals_after_allocation() {
TIME_LINEAR_SCAN(timer_sort_intervals_after); TIME_LINEAR_SCAN(timer_sort_intervals_after);
if (_needs_full_resort) {
// Re-sort existing interval list because an Interval::from() has changed
_sorted_intervals->sort(interval_cmp);
_needs_full_resort = false;
}
IntervalArray* old_list = _sorted_intervals; IntervalArray* old_list = _sorted_intervals;
IntervalList* new_list = _new_intervals_from_allocation; IntervalList* new_list = _new_intervals_from_allocation;
int old_len = old_list->length(); int old_len = old_list->length();
@ -1571,6 +1587,7 @@ void LinearScan::sort_intervals_after_allocation() {
if (new_len == 0) { if (new_len == 0) {
// no intervals have been added during allocation, so sorted list is already up to date // no intervals have been added during allocation, so sorted list is already up to date
assert(is_sorted(_sorted_intervals), "intervals unsorted");
return; return;
} }
@ -1593,6 +1610,7 @@ void LinearScan::sort_intervals_after_allocation() {
} }
_sorted_intervals = combined_list; _sorted_intervals = combined_list;
assert(is_sorted(_sorted_intervals), "intervals unsorted");
} }
@ -1825,6 +1843,8 @@ void LinearScan::resolve_exception_entry(BlockBegin* block, int reg_num, MoveRes
interval = interval->split(from_op_id); interval = interval->split(from_op_id);
interval->assign_reg(reg, regHi); interval->assign_reg(reg, regHi);
append_interval(interval); append_interval(interval);
} else {
_needs_full_resort = true;
} }
assert(interval->from() == from_op_id, "must be true now"); assert(interval->from() == from_op_id, "must be true now");
@ -4492,7 +4512,8 @@ void Interval::print(outputStream* out) const {
} }
} else { } else {
type_name = type2name(type()); type_name = type2name(type());
if (assigned_reg() != -1) { if (assigned_reg() != -1 &&
(LinearScan::num_physical_regs(type()) == 1 || assigned_regHi() != -1)) {
opr = LinearScan::calc_operand_for_interval(this); opr = LinearScan::calc_operand_for_interval(this);
} }
} }

View File

@ -148,6 +148,7 @@ class LinearScan : public CompilationResourceObj {
IntervalList _intervals; // mapping from register number to interval IntervalList _intervals; // mapping from register number to interval
IntervalList* _new_intervals_from_allocation; // list with all intervals created during allocation when an existing interval is split IntervalList* _new_intervals_from_allocation; // list with all intervals created during allocation when an existing interval is split
IntervalArray* _sorted_intervals; // intervals sorted by Interval::from() IntervalArray* _sorted_intervals; // intervals sorted by Interval::from()
bool _needs_full_resort; // set to true if an Interval::from() is changed and _sorted_intervals must be resorted
LIR_OpArray _lir_ops; // mapping from LIR_Op id to LIR_Op node LIR_OpArray _lir_ops; // mapping from LIR_Op id to LIR_Op node
BlockBeginArray _block_of_op; // mapping from LIR_Op id to the BlockBegin containing this instruction BlockBeginArray _block_of_op; // mapping from LIR_Op id to the BlockBegin containing this instruction

View File

@ -2386,19 +2386,21 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(constantPoolHa
valid_cp_range(bootstrap_method_index, cp_size) && valid_cp_range(bootstrap_method_index, cp_size) &&
cp->tag_at(bootstrap_method_index).is_method_handle(), cp->tag_at(bootstrap_method_index).is_method_handle(),
"bootstrap_method_index %u has bad constant type in class file %s", "bootstrap_method_index %u has bad constant type in class file %s",
bootstrap_method_index,
CHECK); CHECK);
operands->short_at_put(operand_fill_index++, bootstrap_method_index); operands->short_at_put(operand_fill_index++, bootstrap_method_index);
operands->short_at_put(operand_fill_index++, argument_count); operands->short_at_put(operand_fill_index++, argument_count);
cfs->guarantee_more(sizeof(u2) * argument_count, CHECK); // argv[argc] cfs->guarantee_more(sizeof(u2) * argument_count, CHECK); // argv[argc]
for (int j = 0; j < argument_count; j++) { for (int j = 0; j < argument_count; j++) {
u2 arg_index = cfs->get_u2_fast(); u2 argument_index = cfs->get_u2_fast();
check_property( check_property(
valid_cp_range(arg_index, cp_size) && valid_cp_range(argument_index, cp_size) &&
cp->tag_at(arg_index).is_loadable_constant(), cp->tag_at(argument_index).is_loadable_constant(),
"argument_index %u has bad constant type in class file %s", "argument_index %u has bad constant type in class file %s",
argument_index,
CHECK); CHECK);
operands->short_at_put(operand_fill_index++, arg_index); operands->short_at_put(operand_fill_index++, argument_index);
} }
} }

View File

@ -939,7 +939,9 @@ void CodeCache::print_bounds(outputStream* st) {
_heap->high(), _heap->high(),
_heap->high_boundary()); _heap->high_boundary());
st->print_cr(" total_blobs=" UINT32_FORMAT " nmethods=" UINT32_FORMAT st->print_cr(" total_blobs=" UINT32_FORMAT " nmethods=" UINT32_FORMAT
" adapters=" UINT32_FORMAT " free_code_cache=" SIZE_FORMAT, " adapters=" UINT32_FORMAT " free_code_cache=" SIZE_FORMAT
" largest_free_block=" SIZE_FORMAT,
CodeCache::nof_blobs(), CodeCache::nof_nmethods(), CodeCache::nof_blobs(), CodeCache::nof_nmethods(),
CodeCache::nof_adapters(), CodeCache::unallocated_capacity()); CodeCache::nof_adapters(), CodeCache::unallocated_capacity(),
CodeCache::largest_free_block());
} }

View File

@ -158,6 +158,7 @@ class CodeCache : AllStatic {
static size_t capacity() { return _heap->capacity(); } static size_t capacity() { return _heap->capacity(); }
static size_t max_capacity() { return _heap->max_capacity(); } static size_t max_capacity() { return _heap->max_capacity(); }
static size_t unallocated_capacity() { return _heap->unallocated_capacity(); } static size_t unallocated_capacity() { return _heap->unallocated_capacity(); }
static size_t largest_free_block() { return _heap->largest_free_block(); }
static bool needs_flushing() { return unallocated_capacity() < CodeCacheFlushingMinimumFreeSpace; } static bool needs_flushing() { return unallocated_capacity() < CodeCacheFlushingMinimumFreeSpace; }
static bool needs_cache_clean() { return _needs_cache_clean; } static bool needs_cache_clean() { return _needs_cache_clean; }

View File

@ -811,9 +811,11 @@ nmethod::nmethod(
_stub_offset = content_offset() + code_buffer->total_offset_of(code_buffer->stubs()); _stub_offset = content_offset() + code_buffer->total_offset_of(code_buffer->stubs());
// Exception handler and deopt handler are in the stub section // Exception handler and deopt handler are in the stub section
assert(offsets->value(CodeOffsets::Exceptions) != -1, "must be set");
assert(offsets->value(CodeOffsets::Deopt ) != -1, "must be set");
_exception_offset = _stub_offset + offsets->value(CodeOffsets::Exceptions); _exception_offset = _stub_offset + offsets->value(CodeOffsets::Exceptions);
_deoptimize_offset = _stub_offset + offsets->value(CodeOffsets::Deopt); _deoptimize_offset = _stub_offset + offsets->value(CodeOffsets::Deopt);
if (has_method_handle_invokes()) { if (offsets->value(CodeOffsets::DeoptMH) != -1) {
_deoptimize_mh_offset = _stub_offset + offsets->value(CodeOffsets::DeoptMH); _deoptimize_mh_offset = _stub_offset + offsets->value(CodeOffsets::DeoptMH);
} else { } else {
_deoptimize_mh_offset = -1; _deoptimize_mh_offset = -1;
@ -1909,6 +1911,7 @@ void nmethod::copy_scopes_pcs(PcDesc* pcs, int count) {
break; break;
} }
} }
assert(has_method_handle_invokes() == (_deoptimize_mh_offset != -1), "must have deopt mh handler");
int size = count * sizeof(PcDesc); int size = count * sizeof(PcDesc);
assert(scopes_pcs_size() >= size, "oob"); assert(scopes_pcs_size() >= size, "oob");

View File

@ -33,6 +33,7 @@ void AbstractCompiler::initialize_runtimes(initializer f, volatile int* state) {
bool do_initialization = false; bool do_initialization = false;
{ {
ThreadInVMfromNative tv(thread); ThreadInVMfromNative tv(thread);
ResetNoHandleMark rnhm;
MutexLocker only_one(CompileThread_lock, thread); MutexLocker only_one(CompileThread_lock, thread);
if ( *state == uninitialized) { if ( *state == uninitialized) {
do_initialization = true; do_initialization = true;
@ -53,6 +54,7 @@ void AbstractCompiler::initialize_runtimes(initializer f, volatile int* state) {
// To in_vm so we can use the lock // To in_vm so we can use the lock
ThreadInVMfromNative tv(thread); ThreadInVMfromNative tv(thread);
ResetNoHandleMark rnhm;
MutexLocker only_one(CompileThread_lock, thread); MutexLocker only_one(CompileThread_lock, thread);
assert(*state == initializing, "wrong state"); assert(*state == initializing, "wrong state");
*state = initialized; *state = initialized;

View File

@ -332,7 +332,7 @@ static OracleCommand parse_command_name(const char * line, int* bytes_read) {
"command_names size mismatch"); "command_names size mismatch");
*bytes_read = 0; *bytes_read = 0;
char command[32]; char command[33];
int result = sscanf(line, "%32[a-z]%n", command, bytes_read); int result = sscanf(line, "%32[a-z]%n", command, bytes_read);
for (uint i = 0; i < ARRAY_SIZE(command_names); i++) { for (uint i = 0; i < ARRAY_SIZE(command_names); i++) {
if (strcmp(command, command_names[i]) == 0) { if (strcmp(command, command_names[i]) == 0) {
@ -470,6 +470,12 @@ void CompilerOracle::parse_from_line(char* line) {
OracleCommand command = parse_command_name(line, &bytes_read); OracleCommand command = parse_command_name(line, &bytes_read);
line += bytes_read; line += bytes_read;
if (command == UnknownCommand) {
tty->print_cr("CompilerOracle: unrecognized line");
tty->print_cr(" \"%s\"", original_line);
return;
}
if (command == QuietCommand) { if (command == QuietCommand) {
_quiet = true; _quiet = true;
return; return;
@ -498,7 +504,7 @@ void CompilerOracle::parse_from_line(char* line) {
line += bytes_read; line += bytes_read;
// there might be a signature following the method. // there might be a signature following the method.
// signatures always begin with ( so match that by hand // signatures always begin with ( so match that by hand
if (1 == sscanf(line, "%*[ \t](%254[);/" RANGEBASE "]%n", sig + 1, &bytes_read)) { if (1 == sscanf(line, "%*[ \t](%254[[);/" RANGEBASE "]%n", sig + 1, &bytes_read)) {
sig[0] = '('; sig[0] = '(';
line += bytes_read; line += bytes_read;
signature = oopFactory::new_symbol_handle(sig, CHECK); signature = oopFactory::new_symbol_handle(sig, CHECK);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -153,6 +153,7 @@ HeapWord* CollectedHeap::common_mem_allocate_noinit(size_t size, bool is_noref,
check_for_non_bad_heap_word_value(result, size)); check_for_non_bad_heap_word_value(result, size));
assert(!HAS_PENDING_EXCEPTION, assert(!HAS_PENDING_EXCEPTION,
"Unexpected exception, will result in uninitialized storage"); "Unexpected exception, will result in uninitialized storage");
THREAD->incr_allocated_bytes(size * HeapWordSize);
return result; return result;
} }

View File

@ -315,6 +315,15 @@ size_t CodeHeap::allocated_capacity() const {
return l; return l;
} }
size_t CodeHeap::largest_free_block() const {
size_t len = 0;
for (FreeBlock* b = _freelist; b != NULL; b = b->link()) {
if (b->length() > len)
len = b->length();
}
return size(len);
}
// Free list management // Free list management
FreeBlock *CodeHeap::following_block(FreeBlock *b) { FreeBlock *CodeHeap::following_block(FreeBlock *b) {

View File

@ -161,6 +161,7 @@ class CodeHeap : public CHeapObj {
size_t max_capacity() const; size_t max_capacity() const;
size_t allocated_capacity() const; size_t allocated_capacity() const;
size_t unallocated_capacity() const { return max_capacity() - allocated_capacity(); } size_t unallocated_capacity() const { return max_capacity() - allocated_capacity(); }
size_t largest_free_block() const;
// Debugging // Debugging
void verify(); void verify();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -114,6 +114,11 @@ void ThreadLocalAllocBuffer::accumulate_statistics() {
void ThreadLocalAllocBuffer::make_parsable(bool retire) { void ThreadLocalAllocBuffer::make_parsable(bool retire) {
if (end() != NULL) { if (end() != NULL) {
invariants(); invariants();
if (retire) {
myThread()->incr_allocated_bytes(used_bytes());
}
CollectedHeap::fill_with_object(top(), hard_end(), retire); CollectedHeap::fill_with_object(top(), hard_end(), retire);
if (retire || ZeroTLAB) { // "Reset" the TLAB if (retire || ZeroTLAB) { // "Reset" the TLAB

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -112,6 +112,8 @@ public:
HeapWord* top() const { return _top; } HeapWord* top() const { return _top; }
HeapWord* pf_top() const { return _pf_top; } HeapWord* pf_top() const { return _pf_top; }
size_t desired_size() const { return _desired_size; } size_t desired_size() const { return _desired_size; }
size_t used() const { return pointer_delta(top(), start()); }
size_t used_bytes() const { return pointer_delta(top(), start(), 1); }
size_t free() const { return pointer_delta(end(), top()); } size_t free() const { return pointer_delta(end(), top()); }
// Don't discard tlab if remaining space is larger than this. // Don't discard tlab if remaining space is larger than this.
size_t refill_waste_limit() const { return _refill_waste_limit; } size_t refill_waste_limit() const { return _refill_waste_limit; }

View File

@ -934,7 +934,8 @@ jint Universe::initialize_heap() {
// See needs_explicit_null_check. // See needs_explicit_null_check.
// Only set the heap base for compressed oops because it indicates // Only set the heap base for compressed oops because it indicates
// compressed oops for pstack code. // compressed oops for pstack code.
if (PrintCompressedOopsMode) { bool verbose = PrintCompressedOopsMode || (PrintMiscellaneous && Verbose);
if (verbose) {
tty->cr(); tty->cr();
tty->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB", tty->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB",
Universe::heap()->base(), Universe::heap()->reserved_region().byte_size()/M); Universe::heap()->base(), Universe::heap()->reserved_region().byte_size()/M);
@ -943,12 +944,12 @@ jint Universe::initialize_heap() {
// Can't reserve heap below 32Gb. // Can't reserve heap below 32Gb.
Universe::set_narrow_oop_base(Universe::heap()->base() - os::vm_page_size()); Universe::set_narrow_oop_base(Universe::heap()->base() - os::vm_page_size());
Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
if (PrintCompressedOopsMode) { if (verbose) {
tty->print(", Compressed Oops with base: "PTR_FORMAT, Universe::narrow_oop_base()); tty->print(", Compressed Oops with base: "PTR_FORMAT, Universe::narrow_oop_base());
} }
} else { } else {
Universe::set_narrow_oop_base(0); Universe::set_narrow_oop_base(0);
if (PrintCompressedOopsMode) { if (verbose) {
tty->print(", zero based Compressed Oops"); tty->print(", zero based Compressed Oops");
} }
#ifdef _WIN64 #ifdef _WIN64
@ -963,12 +964,12 @@ jint Universe::initialize_heap() {
Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
} else { } else {
Universe::set_narrow_oop_shift(0); Universe::set_narrow_oop_shift(0);
if (PrintCompressedOopsMode) { if (verbose) {
tty->print(", 32-bits Oops"); tty->print(", 32-bits Oops");
} }
} }
} }
if (PrintCompressedOopsMode) { if (verbose) {
tty->cr(); tty->cr();
tty->cr(); tty->cr();
} }

View File

@ -444,15 +444,24 @@ void Compile::print_compile_messages() {
} }
//-----------------------init_scratch_buffer_blob------------------------------
// Construct a temporary BufferBlob and cache it for this compile.
void Compile::init_scratch_buffer_blob(int const_size) { void Compile::init_scratch_buffer_blob(int const_size) {
if (scratch_buffer_blob() != NULL) return; // If there is already a scratch buffer blob allocated and the
// constant section is big enough, use it. Otherwise free the
// current and allocate a new one.
BufferBlob* blob = scratch_buffer_blob();
if ((blob != NULL) && (const_size <= _scratch_const_size)) {
// Use the current blob.
} else {
if (blob != NULL) {
BufferBlob::free(blob);
}
// Construct a temporary CodeBuffer to have it construct a BufferBlob
// Cache this BufferBlob for this compile.
ResourceMark rm; ResourceMark rm;
_scratch_const_size = const_size; _scratch_const_size = const_size;
int size = (MAX_inst_size + MAX_stubs_size + _scratch_const_size); int size = (MAX_inst_size + MAX_stubs_size + _scratch_const_size);
BufferBlob* blob = BufferBlob::create("Compile::scratch_buffer", size); blob = BufferBlob::create("Compile::scratch_buffer", size);
// Record the buffer blob for next time. // Record the buffer blob for next time.
set_scratch_buffer_blob(blob); set_scratch_buffer_blob(blob);
// Have we run out of code space? // Have we run out of code space?
@ -461,6 +470,7 @@ void Compile::init_scratch_buffer_blob(int const_size) {
record_failure("Not enough space for scratch buffer in CodeCache"); record_failure("Not enough space for scratch buffer in CodeCache");
return; return;
} }
}
// Initialize the relocation buffers // Initialize the relocation buffers
relocInfo* locs_buf = (relocInfo*) blob->content_end() - MAX_locs_size; relocInfo* locs_buf = (relocInfo*) blob->content_end() - MAX_locs_size;
@ -468,13 +478,6 @@ void Compile::init_scratch_buffer_blob(int const_size) {
} }
void Compile::clear_scratch_buffer_blob() {
assert(scratch_buffer_blob(), "no BufferBlob set");
set_scratch_buffer_blob(NULL);
set_scratch_locs_memory(NULL);
}
//-----------------------scratch_emit_size------------------------------------- //-----------------------scratch_emit_size-------------------------------------
// Helper function that computes size by emitting code // Helper function that computes size by emitting code
uint Compile::scratch_emit_size(const Node* n) { uint Compile::scratch_emit_size(const Node* n) {

View File

@ -1609,10 +1609,11 @@ bool ConnectionGraph::compute_escape() {
// //
// Normally only 1-3 passes needed to build // Normally only 1-3 passes needed to build
// Connection Graph depending on graph complexity. // Connection Graph depending on graph complexity.
// Set limit to 10 to catch situation when something // Observed 8 passes in jvm2008 compiler.compiler.
// Set limit to 20 to catch situation when something
// did go wrong and recompile the method without EA. // did go wrong and recompile the method without EA.
#define CG_BUILD_ITER_LIMIT 10 #define CG_BUILD_ITER_LIMIT 20
uint length = worklist.length(); uint length = worklist.length();
int iterations = 0; int iterations = 0;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1158,7 +1158,7 @@ void PhaseMacroExpand::expand_allocate_common(
// Note: We set the control input on "eden_end" and "old_eden_top" when using // Note: We set the control input on "eden_end" and "old_eden_top" when using
// a TLAB to work around a bug where these values were being moved across // a TLAB to work around a bug where these values were being moved across
// a safepoint. These are not oops, so they cannot be include in the oop // a safepoint. These are not oops, so they cannot be include in the oop
// map, but the can be changed by a GC. The proper way to fix this would // map, but they can be changed by a GC. The proper way to fix this would
// be to set the raw memory state when generating a SafepointNode. However // be to set the raw memory state when generating a SafepointNode. However
// this will require extensive changes to the loop optimization in order to // this will require extensive changes to the loop optimization in order to
// prevent a degradation of the optimization. // prevent a degradation of the optimization.
@ -1167,24 +1167,24 @@ void PhaseMacroExpand::expand_allocate_common(
// allocate the Region and Phi nodes for the result // allocate the Region and Phi nodes for the result
result_region = new (C, 3) RegionNode(3); result_region = new (C, 3) RegionNode(3);
result_phi_rawmem = new (C, 3) PhiNode( result_region, Type::MEMORY, TypeRawPtr::BOTTOM ); result_phi_rawmem = new (C, 3) PhiNode(result_region, Type::MEMORY, TypeRawPtr::BOTTOM);
result_phi_rawoop = new (C, 3) PhiNode( result_region, TypeRawPtr::BOTTOM ); result_phi_rawoop = new (C, 3) PhiNode(result_region, TypeRawPtr::BOTTOM);
result_phi_i_o = new (C, 3) PhiNode( result_region, Type::ABIO ); // I/O is used for Prefetch result_phi_i_o = new (C, 3) PhiNode(result_region, Type::ABIO); // I/O is used for Prefetch
// We need a Region for the loop-back contended case. // We need a Region for the loop-back contended case.
enum { fall_in_path = 1, contended_loopback_path = 2 }; enum { fall_in_path = 1, contended_loopback_path = 2 };
Node *contended_region; Node *contended_region;
Node *contended_phi_rawmem; Node *contended_phi_rawmem;
if( UseTLAB ) { if (UseTLAB) {
contended_region = toobig_false; contended_region = toobig_false;
contended_phi_rawmem = mem; contended_phi_rawmem = mem;
} else { } else {
contended_region = new (C, 3) RegionNode(3); contended_region = new (C, 3) RegionNode(3);
contended_phi_rawmem = new (C, 3) PhiNode( contended_region, Type::MEMORY, TypeRawPtr::BOTTOM); contended_phi_rawmem = new (C, 3) PhiNode(contended_region, Type::MEMORY, TypeRawPtr::BOTTOM);
// Now handle the passing-too-big test. We fall into the contended // Now handle the passing-too-big test. We fall into the contended
// loop-back merge point. // loop-back merge point.
contended_region ->init_req( fall_in_path, toobig_false ); contended_region ->init_req(fall_in_path, toobig_false);
contended_phi_rawmem->init_req( fall_in_path, mem ); contended_phi_rawmem->init_req(fall_in_path, mem);
transform_later(contended_region); transform_later(contended_region);
transform_later(contended_phi_rawmem); transform_later(contended_phi_rawmem);
} }
@ -1192,26 +1192,26 @@ void PhaseMacroExpand::expand_allocate_common(
// Load(-locked) the heap top. // Load(-locked) the heap top.
// See note above concerning the control input when using a TLAB // See note above concerning the control input when using a TLAB
Node *old_eden_top = UseTLAB Node *old_eden_top = UseTLAB
? new (C, 3) LoadPNode ( ctrl, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM ) ? new (C, 3) LoadPNode (ctrl, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM)
: new (C, 3) LoadPLockedNode( contended_region, contended_phi_rawmem, eden_top_adr ); : new (C, 3) LoadPLockedNode(contended_region, contended_phi_rawmem, eden_top_adr);
transform_later(old_eden_top); transform_later(old_eden_top);
// Add to heap top to get a new heap top // Add to heap top to get a new heap top
Node *new_eden_top = new (C, 4) AddPNode( top(), old_eden_top, size_in_bytes ); Node *new_eden_top = new (C, 4) AddPNode(top(), old_eden_top, size_in_bytes);
transform_later(new_eden_top); transform_later(new_eden_top);
// Check for needing a GC; compare against heap end // Check for needing a GC; compare against heap end
Node *needgc_cmp = new (C, 3) CmpPNode( new_eden_top, eden_end ); Node *needgc_cmp = new (C, 3) CmpPNode(new_eden_top, eden_end);
transform_later(needgc_cmp); transform_later(needgc_cmp);
Node *needgc_bol = new (C, 2) BoolNode( needgc_cmp, BoolTest::ge ); Node *needgc_bol = new (C, 2) BoolNode(needgc_cmp, BoolTest::ge);
transform_later(needgc_bol); transform_later(needgc_bol);
IfNode *needgc_iff = new (C, 2) IfNode(contended_region, needgc_bol, PROB_UNLIKELY_MAG(4), COUNT_UNKNOWN ); IfNode *needgc_iff = new (C, 2) IfNode(contended_region, needgc_bol, PROB_UNLIKELY_MAG(4), COUNT_UNKNOWN);
transform_later(needgc_iff); transform_later(needgc_iff);
// Plug the failing-heap-space-need-gc test into the slow-path region // Plug the failing-heap-space-need-gc test into the slow-path region
Node *needgc_true = new (C, 1) IfTrueNode( needgc_iff ); Node *needgc_true = new (C, 1) IfTrueNode(needgc_iff);
transform_later(needgc_true); transform_later(needgc_true);
if( initial_slow_test ) { if (initial_slow_test) {
slow_region ->init_req( need_gc_path, needgc_true ); slow_region->init_req(need_gc_path, needgc_true);
// This completes all paths into the slow merge point // This completes all paths into the slow merge point
transform_later(slow_region); transform_later(slow_region);
} else { // No initial slow path needed! } else { // No initial slow path needed!
@ -1219,51 +1219,74 @@ void PhaseMacroExpand::expand_allocate_common(
slow_region = needgc_true; slow_region = needgc_true;
} }
// No need for a GC. Setup for the Store-Conditional // No need for a GC. Setup for the Store-Conditional
Node *needgc_false = new (C, 1) IfFalseNode( needgc_iff ); Node *needgc_false = new (C, 1) IfFalseNode(needgc_iff);
transform_later(needgc_false); transform_later(needgc_false);
// Grab regular I/O before optional prefetch may change it. // Grab regular I/O before optional prefetch may change it.
// Slow-path does no I/O so just set it to the original I/O. // Slow-path does no I/O so just set it to the original I/O.
result_phi_i_o->init_req( slow_result_path, i_o ); result_phi_i_o->init_req(slow_result_path, i_o);
i_o = prefetch_allocation(i_o, needgc_false, contended_phi_rawmem, i_o = prefetch_allocation(i_o, needgc_false, contended_phi_rawmem,
old_eden_top, new_eden_top, length); old_eden_top, new_eden_top, length);
// Name successful fast-path variables
Node* fast_oop = old_eden_top;
Node* fast_oop_ctrl;
Node* fast_oop_rawmem;
// Store (-conditional) the modified eden top back down. // Store (-conditional) the modified eden top back down.
// StorePConditional produces flags for a test PLUS a modified raw // StorePConditional produces flags for a test PLUS a modified raw
// memory state. // memory state.
Node *store_eden_top; if (UseTLAB) {
Node *fast_oop_ctrl; Node* store_eden_top =
if( UseTLAB ) { new (C, 4) StorePNode(needgc_false, contended_phi_rawmem, eden_top_adr,
store_eden_top = new (C, 4) StorePNode( needgc_false, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, new_eden_top ); TypeRawPtr::BOTTOM, new_eden_top);
transform_later(store_eden_top); transform_later(store_eden_top);
fast_oop_ctrl = needgc_false; // No contention, so this is the fast path fast_oop_ctrl = needgc_false; // No contention, so this is the fast path
fast_oop_rawmem = store_eden_top;
} else { } else {
store_eden_top = new (C, 5) StorePConditionalNode( needgc_false, contended_phi_rawmem, eden_top_adr, new_eden_top, old_eden_top ); Node* store_eden_top =
new (C, 5) StorePConditionalNode(needgc_false, contended_phi_rawmem, eden_top_adr,
new_eden_top, fast_oop/*old_eden_top*/);
transform_later(store_eden_top); transform_later(store_eden_top);
Node *contention_check = new (C, 2) BoolNode( store_eden_top, BoolTest::ne ); Node *contention_check = new (C, 2) BoolNode(store_eden_top, BoolTest::ne);
transform_later(contention_check); transform_later(contention_check);
store_eden_top = new (C, 1) SCMemProjNode(store_eden_top); store_eden_top = new (C, 1) SCMemProjNode(store_eden_top);
transform_later(store_eden_top); transform_later(store_eden_top);
// If not using TLABs, check to see if there was contention. // If not using TLABs, check to see if there was contention.
IfNode *contention_iff = new (C, 2) IfNode ( needgc_false, contention_check, PROB_MIN, COUNT_UNKNOWN ); IfNode *contention_iff = new (C, 2) IfNode (needgc_false, contention_check, PROB_MIN, COUNT_UNKNOWN);
transform_later(contention_iff); transform_later(contention_iff);
Node *contention_true = new (C, 1) IfTrueNode( contention_iff ); Node *contention_true = new (C, 1) IfTrueNode(contention_iff);
transform_later(contention_true); transform_later(contention_true);
// If contention, loopback and try again. // If contention, loopback and try again.
contended_region->init_req( contended_loopback_path, contention_true ); contended_region->init_req(contended_loopback_path, contention_true);
contended_phi_rawmem->init_req( contended_loopback_path, store_eden_top ); contended_phi_rawmem->init_req(contended_loopback_path, store_eden_top);
// Fast-path succeeded with no contention! // Fast-path succeeded with no contention!
Node *contention_false = new (C, 1) IfFalseNode( contention_iff ); Node *contention_false = new (C, 1) IfFalseNode(contention_iff);
transform_later(contention_false); transform_later(contention_false);
fast_oop_ctrl = contention_false; fast_oop_ctrl = contention_false;
// Bump total allocated bytes for this thread
Node* thread = new (C, 1) ThreadLocalNode();
transform_later(thread);
Node* alloc_bytes_adr = basic_plus_adr(top()/*not oop*/, thread,
in_bytes(JavaThread::allocated_bytes_offset()));
Node* alloc_bytes = make_load(fast_oop_ctrl, store_eden_top, alloc_bytes_adr,
0, TypeLong::LONG, T_LONG);
#ifdef _LP64
Node* alloc_size = size_in_bytes;
#else
Node* alloc_size = new (C, 2) ConvI2LNode(size_in_bytes);
transform_later(alloc_size);
#endif
Node* new_alloc_bytes = new (C, 3) AddLNode(alloc_bytes, alloc_size);
transform_later(new_alloc_bytes);
fast_oop_rawmem = make_store(fast_oop_ctrl, store_eden_top, alloc_bytes_adr,
0, new_alloc_bytes, T_LONG);
} }
// Rename successful fast-path variables to make meaning more obvious
Node* fast_oop = old_eden_top;
Node* fast_oop_rawmem = store_eden_top;
fast_oop_rawmem = initialize_object(alloc, fast_oop_rawmem = initialize_object(alloc,
fast_oop_ctrl, fast_oop_rawmem, fast_oop, fast_oop_ctrl, fast_oop_rawmem, fast_oop,
klass_node, length, size_in_bytes); klass_node, length, size_in_bytes);
@ -1282,11 +1305,11 @@ void PhaseMacroExpand::expand_allocate_common(
call->init_req(TypeFunc::Parms+0, thread); call->init_req(TypeFunc::Parms+0, thread);
call->init_req(TypeFunc::Parms+1, fast_oop); call->init_req(TypeFunc::Parms+1, fast_oop);
call->init_req( TypeFunc::Control, fast_oop_ctrl ); call->init_req(TypeFunc::Control, fast_oop_ctrl);
call->init_req( TypeFunc::I_O , top() ) ; // does no i/o call->init_req(TypeFunc::I_O , top()); // does no i/o
call->init_req( TypeFunc::Memory , fast_oop_rawmem ); call->init_req(TypeFunc::Memory , fast_oop_rawmem);
call->init_req( TypeFunc::ReturnAdr, alloc->in(TypeFunc::ReturnAdr) ); call->init_req(TypeFunc::ReturnAdr, alloc->in(TypeFunc::ReturnAdr));
call->init_req( TypeFunc::FramePtr, alloc->in(TypeFunc::FramePtr) ); call->init_req(TypeFunc::FramePtr, alloc->in(TypeFunc::FramePtr));
transform_later(call); transform_later(call);
fast_oop_ctrl = new (C, 1) ProjNode(call,TypeFunc::Control); fast_oop_ctrl = new (C, 1) ProjNode(call,TypeFunc::Control);
transform_later(fast_oop_ctrl); transform_later(fast_oop_ctrl);
@ -1295,10 +1318,10 @@ void PhaseMacroExpand::expand_allocate_common(
} }
// Plug in the successful fast-path into the result merge point // Plug in the successful fast-path into the result merge point
result_region ->init_req( fast_result_path, fast_oop_ctrl ); result_region ->init_req(fast_result_path, fast_oop_ctrl);
result_phi_rawoop->init_req( fast_result_path, fast_oop ); result_phi_rawoop->init_req(fast_result_path, fast_oop);
result_phi_i_o ->init_req( fast_result_path, i_o ); result_phi_i_o ->init_req(fast_result_path, i_o);
result_phi_rawmem->init_req( fast_result_path, fast_oop_rawmem ); result_phi_rawmem->init_req(fast_result_path, fast_oop_rawmem);
} else { } else {
slow_region = ctrl; slow_region = ctrl;
} }

View File

@ -1746,9 +1746,6 @@ void Compile::ScheduleAndBundle() {
// Walk backwards over each basic block, computing the needed alignment // Walk backwards over each basic block, computing the needed alignment
// Walk over all the basic blocks // Walk over all the basic blocks
scheduling.DoScheduling(); scheduling.DoScheduling();
// Clear the BufferBlob used for scheduling.
clear_scratch_buffer_blob();
} }
//------------------------------ComputeLocalLatenciesForward------------------- //------------------------------ComputeLocalLatenciesForward-------------------

View File

@ -59,7 +59,8 @@ class StringConcat : public ResourceObj {
enum { enum {
StringMode, StringMode,
IntMode, IntMode,
CharMode CharMode,
StringNullCheckMode
}; };
StringConcat(PhaseStringOpts* stringopts, CallStaticJavaNode* end): StringConcat(PhaseStringOpts* stringopts, CallStaticJavaNode* end):
@ -114,6 +115,9 @@ class StringConcat : public ResourceObj {
void push_string(Node* value) { void push_string(Node* value) {
push(value, StringMode); push(value, StringMode);
} }
void push_string_null_check(Node* value) {
push(value, StringNullCheckMode);
}
void push_int(Node* value) { void push_int(Node* value) {
push(value, IntMode); push(value, IntMode);
} }
@ -416,7 +420,19 @@ StringConcat* PhaseStringOpts::build_candidate(CallStaticJavaNode* call) {
if (sig == ciSymbol::string_void_signature()) { if (sig == ciSymbol::string_void_signature()) {
// StringBuilder(String) so pick this up as the first argument // StringBuilder(String) so pick this up as the first argument
assert(use->in(TypeFunc::Parms + 1) != NULL, "what?"); assert(use->in(TypeFunc::Parms + 1) != NULL, "what?");
sc->push_string(use->in(TypeFunc::Parms + 1)); const Type* type = _gvn->type(use->in(TypeFunc::Parms + 1));
if (type == TypePtr::NULL_PTR) {
// StringBuilder(null) throws exception.
#ifndef PRODUCT
if (PrintOptimizeStringConcat) {
tty->print("giving up because StringBuilder(null) throws exception");
alloc->jvms()->dump_spec(tty); tty->cr();
}
#endif
return NULL;
}
// StringBuilder(str) argument needs null check.
sc->push_string_null_check(use->in(TypeFunc::Parms + 1));
} }
// The int variant takes an initial size for the backing // The int variant takes an initial size for the backing
// array so just treat it like the void version. // array so just treat it like the void version.
@ -436,7 +452,7 @@ StringConcat* PhaseStringOpts::build_candidate(CallStaticJavaNode* call) {
#ifndef PRODUCT #ifndef PRODUCT
if (PrintOptimizeStringConcat) { if (PrintOptimizeStringConcat) {
tty->print("giving up because couldn't find constructor "); tty->print("giving up because couldn't find constructor ");
alloc->jvms()->dump_spec(tty); alloc->jvms()->dump_spec(tty); tty->cr();
} }
#endif #endif
break; break;
@ -1269,6 +1285,25 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
string_sizes->init_req(argi, string_size); string_sizes->init_req(argi, string_size);
break; break;
} }
case StringConcat::StringNullCheckMode: {
const Type* type = kit.gvn().type(arg);
assert(type != TypePtr::NULL_PTR, "missing check");
if (!type->higher_equal(TypeInstPtr::NOTNULL)) {
// Null check with uncommont trap since
// StringBuilder(null) throws exception.
// Use special uncommon trap instead of
// calling normal do_null_check().
Node* p = __ Bool(__ CmpP(arg, kit.null()), BoolTest::ne);
IfNode* iff = kit.create_and_map_if(kit.control(), p, PROB_MIN, COUNT_UNKNOWN);
overflow->add_req(__ IfFalse(iff));
Node* notnull = __ IfTrue(iff);
kit.set_control(notnull); // set control for the cast_not_null
arg = kit.cast_not_null(arg, false);
sc->set_argument(argi, arg);
}
assert(kit.gvn().type(arg)->higher_equal(TypeInstPtr::NOTNULL), "sanity");
// Fallthrough to add string length.
}
case StringConcat::StringMode: { case StringConcat::StringMode: {
const Type* type = kit.gvn().type(arg); const Type* type = kit.gvn().type(arg);
if (type == TypePtr::NULL_PTR) { if (type == TypePtr::NULL_PTR) {
@ -1328,6 +1363,7 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
// Hook // Hook
PreserveJVMState pjvms(&kit); PreserveJVMState pjvms(&kit);
kit.set_control(overflow); kit.set_control(overflow);
C->record_for_igvn(overflow);
kit.uncommon_trap(Deoptimization::Reason_intrinsic, kit.uncommon_trap(Deoptimization::Reason_intrinsic,
Deoptimization::Action_make_not_entrant); Deoptimization::Action_make_not_entrant);
} }
@ -1363,6 +1399,7 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
start = end; start = end;
break; break;
} }
case StringConcat::StringNullCheckMode:
case StringConcat::StringMode: { case StringConcat::StringMode: {
start = copy_string(kit, arg, char_array, start); start = copy_string(kit, arg, char_array, start);
break; break;

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="jvmti.xsl"?> <?xml-stylesheet type="text/xsl" href="jvmti.xsl"?>
<!-- <!--
Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it This code is free software; you can redistribute it and/or modify it
@ -10697,7 +10697,7 @@ myInit() {
<internallink id="mUTF">modified UTF-8</internallink> string. <internallink id="mUTF">modified UTF-8</internallink> string.
</description> </description>
</param> </param>
<param id="value"> <param id="value_ptr">
<inbuf> <inbuf>
<char/> <char/>
<nullok> <nullok>

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1802,7 +1802,7 @@ JvmtiEnv::GetLocalObject(JavaThread* java_thread, jint depth, jint slot, jobject
// depth - pre-checked as non-negative // depth - pre-checked as non-negative
// value - pre-checked for NULL // value - pre-checked for NULL
jvmtiError jvmtiError
JvmtiEnv::GetLocalInstance(JavaThread* java_thread, jint depth, jobject* value){ JvmtiEnv::GetLocalInstance(JavaThread* java_thread, jint depth, jobject* value_ptr){
JavaThread* current_thread = JavaThread::current(); JavaThread* current_thread = JavaThread::current();
// rm object is created to clean up the javaVFrame created in // rm object is created to clean up the javaVFrame created in
// doit_prologue(), but after doit() is finished with it. // doit_prologue(), but after doit() is finished with it.
@ -1814,7 +1814,7 @@ JvmtiEnv::GetLocalInstance(JavaThread* java_thread, jint depth, jobject* value){
if (err != JVMTI_ERROR_NONE) { if (err != JVMTI_ERROR_NONE) {
return err; return err;
} else { } else {
*value = op.value().l; *value_ptr = op.value().l;
return JVMTI_ERROR_NONE; return JVMTI_ERROR_NONE;
} }
} /* end GetLocalInstance */ } /* end GetLocalInstance */
@ -3440,12 +3440,12 @@ JvmtiEnv::GetSystemProperty(const char* property, char** value_ptr) {
// property - pre-checked for NULL // property - pre-checked for NULL
// value - NULL is a valid value, must be checked // value - NULL is a valid value, must be checked
jvmtiError jvmtiError
JvmtiEnv::SetSystemProperty(const char* property, const char* value) { JvmtiEnv::SetSystemProperty(const char* property, const char* value_ptr) {
jvmtiError err =JVMTI_ERROR_NOT_AVAILABLE; jvmtiError err =JVMTI_ERROR_NOT_AVAILABLE;
for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
if (strcmp(property, p->key()) == 0) { if (strcmp(property, p->key()) == 0) {
if (p->set_value((char *)value)) { if (p->set_value((char *)value_ptr)) {
err = JVMTI_ERROR_NONE; err = JVMTI_ERROR_NONE;
} }
} }

View File

@ -111,7 +111,7 @@ bool MethodHandles::spot_check_entry_names() {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// MethodHandles::generate_adapters // MethodHandles::generate_adapters
// //
void MethodHandles::generate_adapters() { void MethodHandles::generate_adapters(TRAPS) {
if (!EnableMethodHandles || SystemDictionary::MethodHandle_klass() == NULL) return; if (!EnableMethodHandles || SystemDictionary::MethodHandle_klass() == NULL) return;
assert(_adapter_code == NULL, "generate only once"); assert(_adapter_code == NULL, "generate only once");
@ -123,20 +123,20 @@ void MethodHandles::generate_adapters() {
vm_exit_out_of_memory(_adapter_code_size, "CodeCache: no room for MethodHandles adapters"); vm_exit_out_of_memory(_adapter_code_size, "CodeCache: no room for MethodHandles adapters");
CodeBuffer code(_adapter_code); CodeBuffer code(_adapter_code);
MethodHandlesAdapterGenerator g(&code); MethodHandlesAdapterGenerator g(&code);
g.generate(); g.generate(CHECK);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// MethodHandlesAdapterGenerator::generate // MethodHandlesAdapterGenerator::generate
// //
void MethodHandlesAdapterGenerator::generate() { void MethodHandlesAdapterGenerator::generate(TRAPS) {
// Generate generic method handle adapters. // Generate generic method handle adapters.
for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST;
ek < MethodHandles::_EK_LIMIT; ek < MethodHandles::_EK_LIMIT;
ek = MethodHandles::EntryKind(1 + (int)ek)) { ek = MethodHandles::EntryKind(1 + (int)ek)) {
StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek));
MethodHandles::generate_method_handle_stub(_masm, ek); MethodHandles::generate_method_handle_stub(_masm, ek, CHECK);
} }
} }
@ -2645,5 +2645,10 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class))
MethodHandles::set_enabled(true); MethodHandles::set_enabled(true);
} }
} }
// Generate method handles adapters if enabled.
if (MethodHandles::enabled()) {
MethodHandles::generate_adapters(CHECK);
}
} }
JVM_END JVM_END

View File

@ -294,11 +294,11 @@ class MethodHandles: AllStatic {
enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 }; enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
// Generate MethodHandles adapters. // Generate MethodHandles adapters.
static void generate_adapters(); static void generate_adapters(TRAPS);
// Called from InterpreterGenerator and MethodHandlesAdapterGenerator. // Called from InterpreterGenerator and MethodHandlesAdapterGenerator.
static address generate_method_handle_interpreter_entry(MacroAssembler* _masm); static address generate_method_handle_interpreter_entry(MacroAssembler* _masm);
static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek); static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek, TRAPS);
// argument list parsing // argument list parsing
static int argument_slot(oop method_type, int arg); static int argument_slot(oop method_type, int arg);
@ -530,7 +530,7 @@ class MethodHandlesAdapterGenerator : public StubCodeGenerator {
public: public:
MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code) {} MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code) {}
void generate(); void generate(TRAPS);
}; };
#endif // SHARE_VM_PRIMS_METHODHANDLES_HPP #endif // SHARE_VM_PRIMS_METHODHANDLES_HPP

View File

@ -2297,14 +2297,15 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
} else if (match_option(option, "-Xoss", &tail)) { } else if (match_option(option, "-Xoss", &tail)) {
// HotSpot does not have separate native and Java stacks, ignore silently for compatibility // HotSpot does not have separate native and Java stacks, ignore silently for compatibility
// -Xmaxjitcodesize // -Xmaxjitcodesize
} else if (match_option(option, "-Xmaxjitcodesize", &tail)) { } else if (match_option(option, "-Xmaxjitcodesize", &tail) ||
match_option(option, "-XX:ReservedCodeCacheSize=", &tail)) {
julong long_ReservedCodeCacheSize = 0; julong long_ReservedCodeCacheSize = 0;
ArgsRange errcode = parse_memory_size(tail, &long_ReservedCodeCacheSize, ArgsRange errcode = parse_memory_size(tail, &long_ReservedCodeCacheSize,
(size_t)InitialCodeCacheSize); (size_t)InitialCodeCacheSize);
if (errcode != arg_in_range) { if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(), jio_fprintf(defaultStream::error_stream(),
"Invalid maximum code cache size: %s\n", "Invalid maximum code cache size: %s. Should be greater than InitialCodeCacheSize=%dK\n",
option->optionString); option->optionString, InitialCodeCacheSize/K);
describe_range_error(errcode); describe_range_error(errcode);
return JNI_EINVAL; return JNI_EINVAL;
} }

View File

@ -125,9 +125,6 @@ jint init_globals() {
javaClasses_init(); // must happen after vtable initialization javaClasses_init(); // must happen after vtable initialization
stubRoutines_init2(); // note: StubRoutines need 2-phase init stubRoutines_init2(); // note: StubRoutines need 2-phase init
// Generate MethodHandles adapters.
MethodHandles::generate_adapters();
// Although we'd like to, we can't easily do a heap verify // Although we'd like to, we can't easily do a heap verify
// here because the main thread isn't yet a JavaThread, so // here because the main thread isn't yet a JavaThread, so
// its TLAB may not be made parseable from the usual interfaces. // its TLAB may not be made parseable from the usual interfaces.

View File

@ -515,8 +515,8 @@ void before_exit(JavaThread * thread) {
} }
void vm_exit(int code) { void vm_exit(int code) {
Thread* thread = ThreadLocalStorage::thread_index() == -1 ? NULL Thread* thread = ThreadLocalStorage::is_initialized() ?
: ThreadLocalStorage::get_thread_slow(); ThreadLocalStorage::get_thread_slow() : NULL;
if (thread == NULL) { if (thread == NULL) {
// we have serious problems -- just exit // we have serious problems -- just exit
vm_direct_exit(code); vm_direct_exit(code);
@ -553,8 +553,9 @@ void vm_perform_shutdown_actions() {
// Calling 'exit_globals()' will disable thread-local-storage and cause all // Calling 'exit_globals()' will disable thread-local-storage and cause all
// kinds of assertions to trigger in debug mode. // kinds of assertions to trigger in debug mode.
if (is_init_completed()) { if (is_init_completed()) {
Thread* thread = Thread::current(); Thread* thread = ThreadLocalStorage::is_initialized() ?
if (thread->is_Java_thread()) { ThreadLocalStorage::get_thread_slow() : NULL;
if (thread != NULL && thread->is_Java_thread()) {
// We are leaving the VM, set state to native (in case any OS exit // We are leaving the VM, set state to native (in case any OS exit
// handlers call back to the VM) // handlers call back to the VM)
JavaThread* jt = (JavaThread*)thread; JavaThread* jt = (JavaThread*)thread;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -177,20 +177,19 @@ void Thread::operator delete(void* p) {
Thread::Thread() { Thread::Thread() {
// stack // stack and get_thread
_stack_base = NULL; set_stack_base(NULL);
_stack_size = 0; set_stack_size(0);
_self_raw_id = 0; set_self_raw_id(0);
_lgrp_id = -1; set_lgrp_id(-1);
_osthread = NULL;
// allocated data structures // allocated data structures
set_osthread(NULL);
set_resource_area(new ResourceArea()); set_resource_area(new ResourceArea());
set_handle_area(new HandleArea(NULL)); set_handle_area(new HandleArea(NULL));
set_active_handles(NULL); set_active_handles(NULL);
set_free_handle_block(NULL); set_free_handle_block(NULL);
set_last_handle_mark(NULL); set_last_handle_mark(NULL);
set_osthread(NULL);
// This initial value ==> never claimed. // This initial value ==> never claimed.
_oops_do_parity = 0; _oops_do_parity = 0;
@ -205,6 +204,7 @@ Thread::Thread() {
NOT_PRODUCT(_skip_gcalot = false;) NOT_PRODUCT(_skip_gcalot = false;)
CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;) CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;)
_jvmti_env_iteration_count = 0; _jvmti_env_iteration_count = 0;
set_allocated_bytes(0);
_vm_operation_started_count = 0; _vm_operation_started_count = 0;
_vm_operation_completed_count = 0; _vm_operation_completed_count = 0;
_current_pending_monitor = NULL; _current_pending_monitor = NULL;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -60,7 +60,7 @@ class JvmtiThreadState;
class JvmtiGetLoadedClassesClosure; class JvmtiGetLoadedClassesClosure;
class ThreadStatistics; class ThreadStatistics;
class ConcurrentLocksDump; class ConcurrentLocksDump;
class ParkEvent ; class ParkEvent;
class Parker; class Parker;
class ciEnv; class ciEnv;
@ -243,6 +243,8 @@ class Thread: public ThreadShadow {
friend class GC_locker; friend class GC_locker;
ThreadLocalAllocBuffer _tlab; // Thread-local eden ThreadLocalAllocBuffer _tlab; // Thread-local eden
jlong _allocated_bytes; // Cumulative number of bytes allocated on
// the Java heap
int _vm_operation_started_count; // VM_Operation support int _vm_operation_started_count; // VM_Operation support
int _vm_operation_completed_count; // VM_Operation support int _vm_operation_completed_count; // VM_Operation support
@ -256,10 +258,10 @@ class Thread: public ThreadShadow {
// Private thread-local objectmonitor list - a simple cache organized as a SLL. // Private thread-local objectmonitor list - a simple cache organized as a SLL.
public: public:
ObjectMonitor * omFreeList ; ObjectMonitor* omFreeList;
int omFreeCount ; // length of omFreeList int omFreeCount; // length of omFreeList
int omFreeProvision ; // reload chunk size int omFreeProvision; // reload chunk size
ObjectMonitor * omInUseList; // SLL to track monitors in circulation ObjectMonitor* omInUseList; // SLL to track monitors in circulation
int omInUseCount; // length of omInUseList int omInUseCount; // length of omInUseList
public: public:
@ -280,7 +282,6 @@ class Thread: public ThreadShadow {
// Testers // Testers
virtual bool is_VM_thread() const { return false; } virtual bool is_VM_thread() const { return false; }
virtual bool is_Java_thread() const { return false; } virtual bool is_Java_thread() const { return false; }
// Remove this ifdef when C1 is ported to the compiler interface.
virtual bool is_Compiler_thread() const { return false; } virtual bool is_Compiler_thread() const { return false; }
virtual bool is_hidden_from_external_view() const { return false; } virtual bool is_hidden_from_external_view() const { return false; }
virtual bool is_jvmti_agent_thread() const { return false; } virtual bool is_jvmti_agent_thread() const { return false; }
@ -344,7 +345,7 @@ class Thread: public ThreadShadow {
// Support for Unhandled Oop detection // Support for Unhandled Oop detection
#ifdef CHECK_UNHANDLED_OOPS #ifdef CHECK_UNHANDLED_OOPS
private: private:
UnhandledOops *_unhandled_oops; UnhandledOops* _unhandled_oops;
public: public:
UnhandledOops* unhandled_oops() { return _unhandled_oops; } UnhandledOops* unhandled_oops() { return _unhandled_oops; }
// Mark oop safe for gc. It may be stack allocated but won't move. // Mark oop safe for gc. It may be stack allocated but won't move.
@ -392,6 +393,22 @@ class Thread: public ThreadShadow {
} }
} }
jlong allocated_bytes() { return _allocated_bytes; }
void set_allocated_bytes(jlong value) { _allocated_bytes = value; }
void incr_allocated_bytes(jlong size) { _allocated_bytes += size; }
jlong cooked_allocated_bytes() {
jlong allocated_bytes = OrderAccess::load_acquire(&_allocated_bytes);
if (UseTLAB) {
size_t used_bytes = tlab().used_bytes();
if ((ssize_t)used_bytes > 0) {
// More-or-less valid tlab. The load_acquire above should ensure
// that the result of the add is <= the instantaneous value
return allocated_bytes + used_bytes;
}
}
return allocated_bytes;
}
// VM operation support // VM operation support
int vm_operation_ticket() { return ++_vm_operation_started_count; } int vm_operation_ticket() { return ++_vm_operation_started_count; }
int vm_operation_completed_count() { return _vm_operation_completed_count; } int vm_operation_completed_count() { return _vm_operation_completed_count; }
@ -489,6 +506,9 @@ public:
return (_stack_base >= adr && adr >= (_stack_base - _stack_size)); return (_stack_base >= adr && adr >= (_stack_base - _stack_size));
} }
uintptr_t self_raw_id() { return _self_raw_id; }
void set_self_raw_id(uintptr_t value) { _self_raw_id = value; }
int lgrp_id() const { return _lgrp_id; } int lgrp_id() const { return _lgrp_id; }
void set_lgrp_id(int value) { _lgrp_id = value; } void set_lgrp_id(int value) { _lgrp_id = value; }
@ -502,7 +522,7 @@ public:
#ifdef ASSERT #ifdef ASSERT
private: private:
// Deadlock detection support for Mutex locks. List of locks own by thread. // Deadlock detection support for Mutex locks. List of locks own by thread.
Monitor *_owned_locks; Monitor* _owned_locks;
// Mutex::set_owner_implementation is the only place where _owned_locks is modified, // Mutex::set_owner_implementation is the only place where _owned_locks is modified,
// thus the friendship // thus the friendship
friend class Mutex; friend class Mutex;
@ -511,7 +531,7 @@ public:
public: public:
void print_owned_locks_on(outputStream* st) const; void print_owned_locks_on(outputStream* st) const;
void print_owned_locks() const { print_owned_locks_on(tty); } void print_owned_locks() const { print_owned_locks_on(tty); }
Monitor * owned_locks() const { return _owned_locks; } Monitor* owned_locks() const { return _owned_locks; }
bool owns_locks() const { return owned_locks() != NULL; } bool owns_locks() const { return owned_locks() != NULL; }
bool owns_locks_but_compiled_lock() const; bool owns_locks_but_compiled_lock() const;
@ -552,6 +572,8 @@ public:
#undef TLAB_FIELD_OFFSET #undef TLAB_FIELD_OFFSET
static ByteSize allocated_bytes_offset() { return byte_offset_of(Thread, _allocated_bytes ); }
public: public:
volatile intptr_t _Stalled ; volatile intptr_t _Stalled ;
volatile int _TypeTag ; volatile int _TypeTag ;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -60,7 +60,8 @@ typedef struct {
unsigned int isBootClassPathSupported : 1; unsigned int isBootClassPathSupported : 1;
unsigned int isObjectMonitorUsageSupported : 1; unsigned int isObjectMonitorUsageSupported : 1;
unsigned int isSynchronizerUsageSupported : 1; unsigned int isSynchronizerUsageSupported : 1;
unsigned int : 24; unsigned int isThreadAllocatedMemorySupported : 1;
unsigned int : 23;
} jmmOptionalSupport; } jmmOptionalSupport;
typedef enum { typedef enum {
@ -105,7 +106,8 @@ typedef enum {
JMM_VERBOSE_GC = 21, JMM_VERBOSE_GC = 21,
JMM_VERBOSE_CLASS = 22, JMM_VERBOSE_CLASS = 22,
JMM_THREAD_CONTENTION_MONITORING = 23, JMM_THREAD_CONTENTION_MONITORING = 23,
JMM_THREAD_CPU_TIME = 24 JMM_THREAD_CPU_TIME = 24,
JMM_THREAD_ALLOCATED_MEMORY = 25
} jmmBoolAttribute; } jmmBoolAttribute;
@ -213,7 +215,10 @@ typedef struct jmmInterface_1_ {
jobject (JNICALL *GetMemoryPoolUsage) (JNIEnv* env, jobject pool); jobject (JNICALL *GetMemoryPoolUsage) (JNIEnv* env, jobject pool);
jobject (JNICALL *GetPeakMemoryPoolUsage) (JNIEnv* env, jobject pool); jobject (JNICALL *GetPeakMemoryPoolUsage) (JNIEnv* env, jobject pool);
void* reserved4; void (JNICALL *GetThreadAllocatedMemory)
(JNIEnv *env,
jlongArray ids,
jlongArray sizeArray);
jobject (JNICALL *GetMemoryUsage) (JNIEnv* env, jboolean heap); jobject (JNICALL *GetMemoryUsage) (JNIEnv* env, jboolean heap);
@ -228,6 +233,8 @@ typedef struct jmmInterface_1_ {
jlong* result); jlong* result);
jobjectArray (JNICALL *FindCircularBlockedThreads) (JNIEnv *env); jobjectArray (JNICALL *FindCircularBlockedThreads) (JNIEnv *env);
// Not used in JDK 6 or JDK 7
jlong (JNICALL *GetThreadCpuTime) (JNIEnv *env, jlong thread_id); jlong (JNICALL *GetThreadCpuTime) (JNIEnv *env, jlong thread_id);
jobjectArray (JNICALL *GetVMGlobalNames) (JNIEnv *env); jobjectArray (JNICALL *GetVMGlobalNames) (JNIEnv *env);
@ -262,14 +269,22 @@ typedef struct jmmInterface_1_ {
void (JNICALL *GetLastGCStat) (JNIEnv *env, void (JNICALL *GetLastGCStat) (JNIEnv *env,
jobject mgr, jobject mgr,
jmmGCStat *gc_stat); jmmGCStat *gc_stat);
jlong (JNICALL *GetThreadCpuTimeWithKind) (JNIEnv *env,
jlong (JNICALL *GetThreadCpuTimeWithKind)
(JNIEnv *env,
jlong thread_id, jlong thread_id,
jboolean user_sys_cpu_time); jboolean user_sys_cpu_time);
void* reserved5; void (JNICALL *GetThreadCpuTimesWithKind)
(JNIEnv *env,
jlongArray ids,
jlongArray timeArray,
jboolean user_sys_cpu_time);
jint (JNICALL *DumpHeap0) (JNIEnv *env, jint (JNICALL *DumpHeap0) (JNIEnv *env,
jstring outputfile, jstring outputfile,
jboolean live); jboolean live);
jobjectArray (JNICALL *FindDeadlocks) (JNIEnv *env, jboolean object_monitors_only); jobjectArray (JNICALL *FindDeadlocks) (JNIEnv *env,
jboolean object_monitors_only);
void (JNICALL *SetVMGlobal) (JNIEnv *env, void (JNICALL *SetVMGlobal) (JNIEnv *env,
jstring flag_name, jstring flag_name,
jvalue new_value); jvalue new_value);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -101,12 +101,14 @@ void Management::init() {
_optional_support.isCurrentThreadCpuTimeSupported = 0; _optional_support.isCurrentThreadCpuTimeSupported = 0;
_optional_support.isOtherThreadCpuTimeSupported = 0; _optional_support.isOtherThreadCpuTimeSupported = 0;
} }
_optional_support.isBootClassPathSupported = 1; _optional_support.isBootClassPathSupported = 1;
_optional_support.isObjectMonitorUsageSupported = 1; _optional_support.isObjectMonitorUsageSupported = 1;
#ifndef SERVICES_KERNEL #ifndef SERVICES_KERNEL
// This depends on the heap inspector // This depends on the heap inspector
_optional_support.isSynchronizerUsageSupported = 1; _optional_support.isSynchronizerUsageSupported = 1;
#endif // SERVICES_KERNEL #endif // SERVICES_KERNEL
_optional_support.isThreadAllocatedMemorySupported = 1;
} }
void Management::initialize(TRAPS) { void Management::initialize(TRAPS) {
@ -386,11 +388,6 @@ static MemoryPool* get_memory_pool_from_jobject(jobject obj, TRAPS) {
static void validate_thread_id_array(typeArrayHandle ids_ah, TRAPS) { static void validate_thread_id_array(typeArrayHandle ids_ah, TRAPS) {
int num_threads = ids_ah->length(); int num_threads = ids_ah->length();
// should be non-empty array
if (num_threads == 0) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Empty array of thread IDs");
}
// Validate input thread IDs // Validate input thread IDs
int i = 0; int i = 0;
@ -402,11 +399,9 @@ static void validate_thread_id_array(typeArrayHandle ids_ah, TRAPS) {
"Invalid thread ID entry"); "Invalid thread ID entry");
} }
} }
} }
static void validate_thread_info_array(objArrayHandle infoArray_h, TRAPS) { static void validate_thread_info_array(objArrayHandle infoArray_h, TRAPS) {
// check if the element of infoArray is of type ThreadInfo class // check if the element of infoArray is of type ThreadInfo class
klassOop threadinfo_klass = Management::java_lang_management_ThreadInfo_klass(CHECK); klassOop threadinfo_klass = Management::java_lang_management_ThreadInfo_klass(CHECK);
klassOop element_klass = objArrayKlass::cast(infoArray_h->klass())->element_klass(); klassOop element_klass = objArrayKlass::cast(infoArray_h->klass())->element_klass();
@ -414,7 +409,6 @@ static void validate_thread_info_array(objArrayHandle infoArray_h, TRAPS) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"infoArray element type is not ThreadInfo class"); "infoArray element type is not ThreadInfo class");
} }
} }
@ -770,6 +764,45 @@ JVM_ENTRY(jlong, jmm_SetPoolThreshold(JNIEnv* env, jobject obj, jmmThresholdType
return prev; return prev;
JVM_END JVM_END
// Gets an array containing the amount of memory allocated on the Java
// heap for a set of threads (in bytes). Each element of the array is
// the amount of memory allocated for the thread ID specified in the
// corresponding entry in the given array of thread IDs; or -1 if the
// thread does not exist or has terminated.
JVM_ENTRY(void, jmm_GetThreadAllocatedMemory(JNIEnv *env, jlongArray ids,
jlongArray sizeArray))
// Check if threads is null
if (ids == NULL || sizeArray == NULL) {
THROW(vmSymbols::java_lang_NullPointerException());
}
ResourceMark rm(THREAD);
typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
typeArrayHandle ids_ah(THREAD, ta);
typeArrayOop sa = typeArrayOop(JNIHandles::resolve_non_null(sizeArray));
typeArrayHandle sizeArray_h(THREAD, sa);
// validate the thread id array
validate_thread_id_array(ids_ah, CHECK);
// sizeArray must be of the same length as the given array of thread IDs
int num_threads = ids_ah->length();
if (num_threads != sizeArray_h->length()) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"The length of the given long array does not match the length of "
"the given array of thread IDs");
}
MutexLockerEx ml(Threads_lock);
for (int i = 0; i < num_threads; i++) {
JavaThread* java_thread = find_java_thread_from_id(ids_ah->long_at(i));
if (java_thread != NULL) {
sizeArray_h->long_at_put(i, java_thread->cooked_allocated_bytes());
}
}
JVM_END
// Returns a java/lang/management/MemoryUsage object representing // Returns a java/lang/management/MemoryUsage object representing
// the memory usage for the heap or non-heap memory. // the memory usage for the heap or non-heap memory.
JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap)) JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap))
@ -834,6 +867,8 @@ JVM_LEAF(jboolean, jmm_GetBoolAttribute(JNIEnv *env, jmmBoolAttribute att))
return ThreadService::is_thread_monitoring_contention(); return ThreadService::is_thread_monitoring_contention();
case JMM_THREAD_CPU_TIME: case JMM_THREAD_CPU_TIME:
return ThreadService::is_thread_cpu_time_enabled(); return ThreadService::is_thread_cpu_time_enabled();
case JMM_THREAD_ALLOCATED_MEMORY:
return ThreadService::is_thread_allocated_memory_enabled();
default: default:
assert(0, "Unrecognized attribute"); assert(0, "Unrecognized attribute");
return false; return false;
@ -851,6 +886,8 @@ JVM_ENTRY(jboolean, jmm_SetBoolAttribute(JNIEnv *env, jmmBoolAttribute att, jboo
return ThreadService::set_thread_monitoring_contention(flag != 0); return ThreadService::set_thread_monitoring_contention(flag != 0);
case JMM_THREAD_CPU_TIME: case JMM_THREAD_CPU_TIME:
return ThreadService::set_thread_cpu_time_enabled(flag != 0); return ThreadService::set_thread_cpu_time_enabled(flag != 0);
case JMM_THREAD_ALLOCATED_MEMORY:
return ThreadService::set_thread_allocated_memory_enabled(flag != 0);
default: default:
assert(0, "Unrecognized attribute"); assert(0, "Unrecognized attribute");
return false; return false;
@ -1096,6 +1133,7 @@ static void do_thread_dump(ThreadDumpResult* dump_result,
// maxDepth == 0 requests no stack trace. // maxDepth == 0 requests no stack trace.
// infoArray - array of ThreadInfo objects // infoArray - array of ThreadInfo objects
// //
// QQQ - Why does this method return a value instead of void?
JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jobjectArray infoArray)) JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jobjectArray infoArray))
// Check if threads is null // Check if threads is null
if (ids == NULL || infoArray == NULL) { if (ids == NULL || infoArray == NULL) {
@ -1159,7 +1197,6 @@ JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jo
} }
} else { } else {
// obtain thread dump with the specific list of threads with stack trace // obtain thread dump with the specific list of threads with stack trace
do_thread_dump(&dump_result, do_thread_dump(&dump_result,
ids_ah, ids_ah,
num_threads, num_threads,
@ -1252,8 +1289,6 @@ JVM_ENTRY(jobjectArray, jmm_DumpThreads(JNIEnv *env, jlongArray thread_ids, jboo
continue; continue;
} }
ThreadStackTrace* stacktrace = ts->get_stack_trace(); ThreadStackTrace* stacktrace = ts->get_stack_trace();
assert(stacktrace != NULL, "Must have a stack trace dumped"); assert(stacktrace != NULL, "Must have a stack trace dumped");
@ -1500,6 +1535,49 @@ JVM_ENTRY(jlong, jmm_GetThreadCpuTimeWithKind(JNIEnv *env, jlong thread_id, jboo
return -1; return -1;
JVM_END JVM_END
// Gets an array containing the CPU times consumed by a set of threads
// (in nanoseconds). Each element of the array is the CPU time for the
// thread ID specified in the corresponding entry in the given array
// of thread IDs; or -1 if the thread does not exist or has terminated.
// If user_sys_cpu_time = true, the sum of user level and system CPU time
// for the given thread is returned; otherwise, only user level CPU time
// is returned.
JVM_ENTRY(void, jmm_GetThreadCpuTimesWithKind(JNIEnv *env, jlongArray ids,
jlongArray timeArray,
jboolean user_sys_cpu_time))
// Check if threads is null
if (ids == NULL || timeArray == NULL) {
THROW(vmSymbols::java_lang_NullPointerException());
}
ResourceMark rm(THREAD);
typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
typeArrayHandle ids_ah(THREAD, ta);
typeArrayOop tia = typeArrayOop(JNIHandles::resolve_non_null(timeArray));
typeArrayHandle timeArray_h(THREAD, tia);
// validate the thread id array
validate_thread_id_array(ids_ah, CHECK);
// timeArray must be of the same length as the given array of thread IDs
int num_threads = ids_ah->length();
if (num_threads != timeArray_h->length()) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"The length of the given long array does not match the length of "
"the given array of thread IDs");
}
MutexLockerEx ml(Threads_lock);
for (int i = 0; i < num_threads; i++) {
JavaThread* java_thread = find_java_thread_from_id(ids_ah->long_at(i));
if (java_thread != NULL) {
timeArray_h->long_at_put(i, os::thread_cpu_time((Thread*)java_thread,
user_sys_cpu_time != 0));
}
}
JVM_END
// Returns a String array of all VM global flag names // Returns a String array of all VM global flag names
JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env)) JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env))
// last flag entry is always NULL, so subtract 1 // last flag entry is always NULL, so subtract 1
@ -2020,7 +2098,7 @@ const struct jmmInterface_1_ jmm_interface = {
jmm_GetMemoryManagers, jmm_GetMemoryManagers,
jmm_GetMemoryPoolUsage, jmm_GetMemoryPoolUsage,
jmm_GetPeakMemoryPoolUsage, jmm_GetPeakMemoryPoolUsage,
NULL, jmm_GetThreadAllocatedMemory,
jmm_GetMemoryUsage, jmm_GetMemoryUsage,
jmm_GetLongAttribute, jmm_GetLongAttribute,
jmm_GetBoolAttribute, jmm_GetBoolAttribute,
@ -2038,7 +2116,7 @@ const struct jmmInterface_1_ jmm_interface = {
jmm_GetGCExtAttributeInfo, jmm_GetGCExtAttributeInfo,
jmm_GetLastGCStat, jmm_GetLastGCStat,
jmm_GetThreadCpuTimeWithKind, jmm_GetThreadCpuTimeWithKind,
NULL, jmm_GetThreadCpuTimesWithKind,
jmm_DumpHeap0, jmm_DumpHeap0,
jmm_FindDeadlockedThreads, jmm_FindDeadlockedThreads,
jmm_SetVMGlobal, jmm_SetVMGlobal,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -46,6 +46,7 @@
// Default is disabled. // Default is disabled.
bool ThreadService::_thread_monitoring_contention_enabled = false; bool ThreadService::_thread_monitoring_contention_enabled = false;
bool ThreadService::_thread_cpu_time_enabled = false; bool ThreadService::_thread_cpu_time_enabled = false;
bool ThreadService::_thread_allocated_memory_enabled = false;
PerfCounter* ThreadService::_total_threads_count = NULL; PerfCounter* ThreadService::_total_threads_count = NULL;
PerfVariable* ThreadService::_live_threads_count = NULL; PerfVariable* ThreadService::_live_threads_count = NULL;
@ -84,6 +85,8 @@ void ThreadService::init() {
if (os::is_thread_cpu_time_supported()) { if (os::is_thread_cpu_time_supported()) {
_thread_cpu_time_enabled = true; _thread_cpu_time_enabled = true;
} }
_thread_allocated_memory_enabled = true; // Always on, so enable it
} }
void ThreadService::reset_peak_thread_count() { void ThreadService::reset_peak_thread_count() {
@ -181,6 +184,15 @@ bool ThreadService::set_thread_cpu_time_enabled(bool flag) {
return prev; return prev;
} }
bool ThreadService::set_thread_allocated_memory_enabled(bool flag) {
MutexLocker m(Management_lock);
bool prev = _thread_allocated_memory_enabled;
_thread_allocated_memory_enabled = flag;
return prev;
}
// GC support // GC support
void ThreadService::oops_do(OopClosure* f) { void ThreadService::oops_do(OopClosure* f) {
for (ThreadDumpResult* dump = _threaddump_list; dump != NULL; dump = dump->next()) { for (ThreadDumpResult* dump = _threaddump_list; dump != NULL; dump = dump->next()) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -65,6 +65,7 @@ private:
static bool _thread_monitoring_contention_enabled; static bool _thread_monitoring_contention_enabled;
static bool _thread_cpu_time_enabled; static bool _thread_cpu_time_enabled;
static bool _thread_allocated_memory_enabled;
// Need to keep the list of thread dump result that // Need to keep the list of thread dump result that
// keep references to methodOop since thread dump can be // keep references to methodOop since thread dump can be
@ -83,6 +84,9 @@ public:
static bool set_thread_cpu_time_enabled(bool flag); static bool set_thread_cpu_time_enabled(bool flag);
static bool is_thread_cpu_time_enabled() { return _thread_cpu_time_enabled; } static bool is_thread_cpu_time_enabled() { return _thread_cpu_time_enabled; }
static bool set_thread_allocated_memory_enabled(bool flag);
static bool is_thread_allocated_memory_enabled() { return _thread_cpu_time_enabled; }
static jlong get_total_thread_count() { return _total_threads_count->get_value(); } static jlong get_total_thread_count() { return _total_threads_count->get_value(); }
static jlong get_peak_thread_count() { return _peak_threads_count->get_value(); } static jlong get_peak_thread_count() { return _peak_threads_count->get_value(); }
static jlong get_live_thread_count() { return _live_threads_count->get_value() - _exiting_threads_count; } static jlong get_live_thread_count() { return _live_threads_count->get_value() - _exiting_threads_count; }

View File

@ -226,7 +226,7 @@ static jint _exiting_out_of_mem = 0;
void report_vm_out_of_memory(const char* file, int line, size_t size, void report_vm_out_of_memory(const char* file, int line, size_t size,
const char* message) { const char* message) {
if (Debugging || error_is_suppressed(file, line)) return; if (Debugging) return;
// We try to gather additional information for the first out of memory // We try to gather additional information for the first out of memory
// error only; gathering additional data might cause an allocation and a // error only; gathering additional data might cause an allocation and a

View File

@ -67,7 +67,7 @@ const char *env_list[] = {
// threads are blocked forever inside report_and_die(). // threads are blocked forever inside report_and_die().
// Constructor for crashes // Constructor for crashes
VMError::VMError(Thread* thread, int sig, address pc, void* siginfo, void* context) { VMError::VMError(Thread* thread, unsigned int sig, address pc, void* siginfo, void* context) {
_thread = thread; _thread = thread;
_id = sig; _id = sig;
_pc = pc; _pc = pc;
@ -323,28 +323,50 @@ void VMError::report(outputStream* st) {
STEP(10, "(printing fatal error message)") STEP(10, "(printing fatal error message)")
st->print_cr("#"); st->print_cr("#");
if (should_report_bug(_id)) {
st->print_cr("# A fatal error has been detected by the Java Runtime Environment:"); st->print_cr("# A fatal error has been detected by the Java Runtime Environment:");
} else {
st->print_cr("# There is insufficient memory for the Java "
"Runtime Environment to continue.");
}
STEP(15, "(printing type of error)") STEP(15, "(printing type of error)")
switch(_id) { switch(_id) {
case oom_error: case oom_error:
st->print_cr("#");
st->print("# java.lang.OutOfMemoryError: ");
if (_size) { if (_size) {
st->print("requested "); st->print("# Native memory allocation (malloc) failed to allocate ");
sprintf(buf,SIZE_FORMAT,_size); jio_snprintf(buf, sizeof(buf), SIZE_FORMAT, _size);
st->print(buf); st->print(buf);
st->print(" bytes"); st->print(" bytes");
if (_message != NULL) { if (_message != NULL) {
st->print(" for "); st->print(" for ");
st->print(_message); st->print(_message);
} }
st->print_cr(". Out of swap space?"); st->cr();
} else { } else {
if (_message != NULL) if (_message != NULL)
st->print("# ");
st->print_cr(_message); st->print_cr(_message);
} }
// In error file give some solutions
if (_verbose) {
st->print_cr("# Possible reasons:");
st->print_cr("# The system is out of physical RAM or swap space");
st->print_cr("# In 32 bit mode, the process size limit was hit");
st->print_cr("# Possible solutions:");
st->print_cr("# Reduce memory load on the system");
st->print_cr("# Increase physical memory or swap space");
st->print_cr("# Check if swap backing store is full");
st->print_cr("# Use 64 bit Java on a 64 bit OS");
st->print_cr("# Decrease Java heap size (-Xmx/-Xms)");
st->print_cr("# Decrease number of Java threads");
st->print_cr("# Decrease Java thread stack sizes (-Xss)");
st->print_cr("# Set larger code cache with -XX:ReservedCodeCacheSize=");
st->print_cr("# This output file may be truncated or incomplete.");
} else {
return; // that's enough for the screen
}
break; break;
case internal_error: case internal_error:
default: default:
@ -361,7 +383,11 @@ void VMError::report(outputStream* st) {
st->print(" (0x%x)", _id); // signal number st->print(" (0x%x)", _id); // signal number
st->print(" at pc=" PTR_FORMAT, _pc); st->print(" at pc=" PTR_FORMAT, _pc);
} else { } else {
if (should_report_bug(_id)) {
st->print("Internal Error"); st->print("Internal Error");
} else {
st->print("Out of Memory Error");
}
if (_filename != NULL && _lineno > 0) { if (_filename != NULL && _lineno > 0) {
#ifdef PRODUCT #ifdef PRODUCT
// In product mode chop off pathname? // In product mode chop off pathname?
@ -393,12 +419,14 @@ void VMError::report(outputStream* st) {
STEP(40, "(printing error message)") STEP(40, "(printing error message)")
if (should_report_bug(_id)) { // already printed the message.
// error message // error message
if (_detail_msg) { if (_detail_msg) {
st->print_cr("# %s: %s", _message ? _message : "Error", _detail_msg); st->print_cr("# %s: %s", _message ? _message : "Error", _detail_msg);
} else if (_message) { } else if (_message) {
st->print_cr("# Error: %s", _message); st->print_cr("# Error: %s", _message);
} }
}
STEP(50, "(printing Java version string)") STEP(50, "(printing Java version string)")
@ -428,7 +456,9 @@ void VMError::report(outputStream* st) {
STEP(65, "(printing bug submit message)") STEP(65, "(printing bug submit message)")
if (_verbose) print_bug_submit_message(st, _thread); if (should_report_bug(_id) && _verbose) {
print_bug_submit_message(st, _thread);
}
STEP(70, "(printing thread)" ) STEP(70, "(printing thread)" )
@ -906,7 +936,7 @@ void VMError::report_and_die() {
OnError = NULL; OnError = NULL;
} }
static bool skip_bug_url = false; static bool skip_bug_url = !should_report_bug(first_error->_id);
if (!skip_bug_url) { if (!skip_bug_url) {
skip_bug_url = true; skip_bug_url = true;
@ -919,7 +949,8 @@ void VMError::report_and_die() {
static bool skip_os_abort = false; static bool skip_os_abort = false;
if (!skip_os_abort) { if (!skip_os_abort) {
skip_os_abort = true; skip_os_abort = true;
os::abort(); bool dump_core = should_report_bug(first_error->_id);
os::abort(dump_core);
} }
// if os::abort() doesn't abort, try os::die(); // if os::abort() doesn't abort, try os::die();

View File

@ -87,10 +87,12 @@ class VMError : public StackObj {
// accessor // accessor
const char* message() const { return _message; } const char* message() const { return _message; }
const char* detail_msg() const { return _detail_msg; } const char* detail_msg() const { return _detail_msg; }
bool should_report_bug(unsigned int id) { return id != oom_error; }
public: public:
// Constructor for crashes // Constructor for crashes
VMError(Thread* thread, int sig, address pc, void* siginfo, void* context); VMError(Thread* thread, unsigned int sig, address pc, void* siginfo,
void* context);
// Constructor for VM internal errors // Constructor for VM internal errors
VMError(Thread* thread, const char* filename, int lineno, VMError(Thread* thread, const char* filename, int lineno,
const char* message, const char * detail_msg); const char* message, const char * detail_msg);

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 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.
*
*/
/**
* @test
* @bug 6579789
* @summary Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
* @run main/othervm -Xcomp -XX:UseSSE=0 -XX:CompileOnly=Test6579789.bug Test6579789
*/
public class Test6579789 {
public static void main(String[] args) {
bug(4);
}
public static void bug(int n) {
float f = 1;
int i = 1;
try {
int x = 1 / n; // instruction that can trap
f = 2;
i = 2;
int y = 2 / n; // instruction that can trap
} catch (Exception ex) {
f++;
i++;
}
}
}

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 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.
*
*/
/**
* @test
* @bug 7009231
* @summary C1: Incorrect CAS code for longs on SPARC 32bit
*
* @run main/othervm -Xbatch Test7009231
*
*/
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
public class Test7009231 {
public static void main(String[] args) throws InterruptedException {
doTest(8);
}
private static void doTest(int nThreads) throws InterruptedException {
Thread[] aThreads = new Thread[nThreads];
final AtomicLong atl = new AtomicLong();
for (int i = 0; i < nThreads; i++) {
aThreads[i] = new RunnerThread(atl, 1L << (8 * i));
}
for (int i = 0; i < nThreads; i++) {
aThreads[i].start();
}
for (int i = 0; i < nThreads; i++) {
aThreads[i].join();
}
}
public static class RunnerThread extends Thread {
public RunnerThread(AtomicLong atomic, long lMask) {
m_lMask = lMask;
m_atomic = atomic;
}
public void run() {
AtomicLong atomic = m_atomic;
long lMask = m_lMask;
for (int i = 0; i < 100000; i++) {
setBit(atomic, lMask);
clearBit(atomic, lMask);
}
}
protected void setBit(AtomicLong atomic, long lMask) {
long lWord;
do {
lWord = atomic.get();
} while (!atomic.compareAndSet(lWord, lWord | lMask));
if ((atomic.get() & lMask) == 0L) {
throw new InternalError();
}
}
protected void clearBit(AtomicLong atomic, long lMask) {
long lWord;
do {
lWord = atomic.get();
} while (!atomic.compareAndSet(lWord, lWord & ~lMask));
if ((atomic.get() & lMask) != 0L) {
throw new InternalError();
}
}
private long m_lMask;
private AtomicLong m_atomic;
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 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.
*
*/
/**
* @test
* @bug 7009359
* @summary HS with -XX:+AggressiveOpts optimize new StringBuffer(null) so it does not throw NPE as expected
*
* @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+OptimizeStringConcat -XX:CompileCommand=exclude,Test7009359,main Test7009359
*
*/
public class Test7009359 {
public static void main (String[] args) {
for(int i = 0; i < 1000000; i++) {
if(!stringmakerBUG(null).equals("NPE")) {
System.out.println("StringBuffer(null) does not throw NPE");
System.exit(97);
}
}
}
public static String stringmakerBUG(String str) {
try {
return new StringBuffer(str).toString();
} catch (NullPointerException e) {
return "NPE";
}
}
}

View File

@ -98,3 +98,4 @@ b2f6d9c4f12ffd307a5de40455b2b61b31a5cb79 jdk7-b118
63dae40fa19fd3bf4689ea2f3c1d9d690e1abcee jdk7-b121 63dae40fa19fd3bf4689ea2f3c1d9d690e1abcee jdk7-b121
03ff13d19c8fa983cbab6542930a7f352e9b5b33 jdk7-b122 03ff13d19c8fa983cbab6542930a7f352e9b5b33 jdk7-b122
e2aedea6495d61557326928de20dbb2d78fdd9aa jdk7-b123 e2aedea6495d61557326928de20dbb2d78fdd9aa jdk7-b123
57ed1f3bec72924cdad102f9bf90f7449ea7bb83 jdk7-b124

View File

@ -98,3 +98,4 @@ a4f2e1ca67163ef79555082809d7cd719893c338 jdk7-b120
0fa950117faac7bdbc94e6c46b88f6f892031c17 jdk7-b121 0fa950117faac7bdbc94e6c46b88f6f892031c17 jdk7-b121
17b6c48a344968880925dcef1178fec282feb335 jdk7-b122 17b6c48a344968880925dcef1178fec282feb335 jdk7-b122
5a8e43bcce56b7cd5576419067a929b74575ae71 jdk7-b123 5a8e43bcce56b7cd5576419067a929b74575ae71 jdk7-b123
86f60e5b3975840968f3147ddce047a27a9fc83e jdk7-b124

View File

@ -98,3 +98,4 @@ ecab7eefb8f2326fd90fb632f47f1b6f81e928f8 jdk7-b119
a661d8587b5d8986aacae086f5df66af9e1a96b1 jdk7-b121 a661d8587b5d8986aacae086f5df66af9e1a96b1 jdk7-b121
ac311eb325bfc763698219252bf3cee9e091f3af jdk7-b122 ac311eb325bfc763698219252bf3cee9e091f3af jdk7-b122
869190935eedee7750d955019ab2a1b80f0a13a8 jdk7-b123 869190935eedee7750d955019ab2a1b80f0a13a8 jdk7-b123
1c72adc9d5f331cb882cf5354ba0dcb118a60b23 jdk7-b124