aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortrims <none@none>2011-01-07 22:56:35 -0800
committertrims <none@none>2011-01-07 22:56:35 -0800
commit4ec94652362c578c5b0f65ec673bea30842f9ee0 (patch)
tree87a7faced2c948cdad3f7c02883700f89e0ed9d2
parente6f787b355b119b61693e6f2675dd8c8ddc26b3b (diff)
parentc901cd9d2fade8eada21e5e137fc47e9344edd76 (diff)
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java21
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java59
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java57
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java6
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java191
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java3
-rw-r--r--make/jprt.properties16
-rw-r--r--make/solaris/makefiles/buildtree.make2
-rw-r--r--make/solaris/makefiles/vm.make4
-rw-r--r--make/windows/makefiles/compile.make2
-rw-r--r--src/cpu/sparc/vm/assembler_sparc.cpp89
-rw-r--r--src/cpu/sparc/vm/assembler_sparc.hpp16
-rw-r--r--src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp23
-rw-r--r--src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp6
-rw-r--r--src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp5
-rw-r--r--src/cpu/sparc/vm/c1_MacroAssembler_sparc.hpp2
-rw-r--r--src/cpu/sparc/vm/c1_Runtime1_sparc.cpp7
-rw-r--r--src/cpu/sparc/vm/methodHandles_sparc.cpp70
-rw-r--r--src/cpu/sparc/vm/sparc.ad45
-rw-r--r--src/cpu/sparc/vm/templateTable_sparc.cpp27
-rw-r--r--src/cpu/sparc/vm/vm_version_sparc.cpp49
-rw-r--r--src/cpu/sparc/vm/vm_version_sparc.hpp38
-rw-r--r--src/cpu/x86/vm/assembler_x86.cpp108
-rw-r--r--src/cpu/x86/vm/assembler_x86.hpp31
-rw-r--r--src/cpu/x86/vm/c1_LIRAssembler_x86.cpp2
-rw-r--r--src/cpu/x86/vm/c1_LIRGenerator_x86.cpp5
-rw-r--r--src/cpu/x86/vm/c1_MacroAssembler_x86.cpp5
-rw-r--r--src/cpu/x86/vm/c1_Runtime1_x86.cpp19
-rw-r--r--src/cpu/x86/vm/methodHandles_x86.cpp106
-rw-r--r--src/cpu/x86/vm/templateTable_x86_32.cpp18
-rw-r--r--src/cpu/x86/vm/templateTable_x86_64.cpp4
-rw-r--r--src/os/linux/vm/perfMemory_linux.cpp24
-rw-r--r--src/os/posix/launcher/java_md.c1
-rw-r--r--src/os/solaris/vm/os_solaris.cpp17
-rw-r--r--src/os/solaris/vm/thread_solaris.inline.hpp8
-rw-r--r--src/os/windows/vm/os_windows.cpp20
-rw-r--r--src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp7
-rw-r--r--src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp71
-rw-r--r--src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp7
-rw-r--r--src/share/vm/adlc/dict2.cpp6
-rw-r--r--src/share/vm/c1/c1_Compilation.cpp15
-rw-r--r--src/share/vm/c1/c1_Compilation.hpp2
-rw-r--r--src/share/vm/c1/c1_FrameMap.cpp4
-rw-r--r--src/share/vm/c1/c1_LIR.hpp9
-rw-r--r--src/share/vm/c1/c1_LIRAssembler.cpp2
-rw-r--r--src/share/vm/c1/c1_LIRAssembler.hpp2
-rw-r--r--src/share/vm/c1/c1_LIRGenerator.cpp4
-rw-r--r--src/share/vm/c1/c1_LinearScan.cpp23
-rw-r--r--src/share/vm/c1/c1_LinearScan.hpp1
-rw-r--r--src/share/vm/classfile/classFileParser.cpp10
-rw-r--r--src/share/vm/code/codeCache.cpp6
-rw-r--r--src/share/vm/code/codeCache.hpp1
-rw-r--r--src/share/vm/code/nmethod.cpp5
-rw-r--r--src/share/vm/compiler/abstractCompiler.cpp2
-rw-r--r--src/share/vm/compiler/compilerOracle.cpp10
-rw-r--r--src/share/vm/gc_interface/collectedHeap.inline.hpp3
-rw-r--r--src/share/vm/memory/heap.cpp9
-rw-r--r--src/share/vm/memory/heap.hpp1
-rw-r--r--src/share/vm/memory/threadLocalAllocBuffer.cpp7
-rw-r--r--src/share/vm/memory/threadLocalAllocBuffer.hpp4
-rw-r--r--src/share/vm/memory/universe.cpp11
-rw-r--r--src/share/vm/opto/compile.cpp47
-rw-r--r--src/share/vm/opto/escape.cpp5
-rw-r--r--src/share/vm/opto/macro.cpp111
-rw-r--r--src/share/vm/opto/output.cpp3
-rw-r--r--src/share/vm/opto/stringopts.cpp43
-rw-r--r--src/share/vm/prims/jvmti.xml4
-rw-r--r--src/share/vm/prims/jvmtiEnv.cpp10
-rw-r--r--src/share/vm/prims/methodHandles.cpp13
-rw-r--r--src/share/vm/prims/methodHandles.hpp6
-rw-r--r--src/share/vm/runtime/arguments.cpp7
-rw-r--r--src/share/vm/runtime/init.cpp3
-rw-r--r--src/share/vm/runtime/java.cpp9
-rw-r--r--src/share/vm/runtime/thread.cpp18
-rw-r--r--src/share/vm/runtime/thread.hpp78
-rw-r--r--src/share/vm/services/jmm.h33
-rw-r--r--src/share/vm/services/management.cpp106
-rw-r--r--src/share/vm/services/threadService.cpp14
-rw-r--r--src/share/vm/services/threadService.hpp6
-rw-r--r--src/share/vm/utilities/debug.cpp2
-rw-r--r--src/share/vm/utilities/vmError.cpp67
-rw-r--r--src/share/vm/utilities/vmError.hpp4
-rw-r--r--test/compiler/6579789/Test6579789.java49
-rw-r--r--test/compiler/7009231/Test7009231.java100
-rw-r--r--test/compiler/7009359/Test7009359.java52
85 files changed, 1501 insertions, 617 deletions
diff --git a/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java b/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java
index 967f8a4f1..9cf6122c7 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -99,15 +99,8 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
long typeEntrySizeOffset;
long typeEntryArrayStride;
- typeEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset");
- typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset");
- typeEntryIsOopTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset");
- typeEntryIsIntegerTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset");
- typeEntryIsUnsignedOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset");
- typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset");
- typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride");
-
- // Fetch the address of the VMTypeEntry*
+ // Fetch the address of the VMTypeEntry*. We get this symbol first
+ // and try to use it to make sure that symbol lookup is working.
Address entryAddr = lookupInProcess("gHotSpotVMTypes");
// System.err.println("gHotSpotVMTypes address = " + entryAddr);
// Dereference this once to get the pointer to the first VMTypeEntry
@@ -118,6 +111,14 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
throw new RuntimeException("gHotSpotVMTypes was not initialized properly in the remote process; can not continue");
}
+ typeEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset");
+ typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset");
+ typeEntryIsOopTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset");
+ typeEntryIsIntegerTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset");
+ typeEntryIsUnsignedOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset");
+ typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset");
+ typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride");
+
// Start iterating down it until we find an entry with no name
Address typeNameAddr = null;
do {
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java
index b2c988224..d29a62659 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/COFFFileParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -122,10 +122,14 @@ public class COFFFileParser {
private MemoizedObject[] sectionHeaders;
private MemoizedObject[] symbols;
+ // Init stringTable at decl time since other fields init'ed in the
+ // constructor need the String Table.
private MemoizedObject stringTable = new MemoizedObject() {
public Object computeValue() {
+ // the String Table follows the Symbol Table
int ptr = getPointerToSymbolTable();
if (ptr == 0) {
+ // no Symbol Table so no String Table
return new StringTable(0);
} else {
return new StringTable(ptr + SYMBOL_SIZE * getNumberOfSymbols());
@@ -140,6 +144,8 @@ public class COFFFileParser {
timeDateStamp = readInt();
pointerToSymbolTable = readInt();
numberOfSymbols = readInt();
+ // String Table can be accessed at this point because
+ // pointerToSymbolTable and numberOfSymbols fields are set.
sizeOfOptionalHeader = readShort();
characteristics = readShort();
@@ -222,6 +228,8 @@ public class COFFFileParser {
private MemoizedObject windowsSpecificFields;
private MemoizedObject dataDirectories;
+ // We use an offset of 2 because OptionalHeaderStandardFieldsImpl doesn't
+ // include the 'magic' field.
private static final int STANDARD_FIELDS_OFFSET = 2;
private static final int PE32_WINDOWS_SPECIFIC_FIELDS_OFFSET = 28;
private static final int PE32_DATA_DIRECTORIES_OFFSET = 96;
@@ -288,7 +296,7 @@ public class COFFFileParser {
private int sizeOfUninitializedData;
private int addressOfEntryPoint;
private int baseOfCode;
- private int baseOfData;
+ private int baseOfData; // only set in PE32
OptionalHeaderStandardFieldsImpl(int offset,
boolean isPE32Plus) {
@@ -301,7 +309,8 @@ public class COFFFileParser {
sizeOfUninitializedData = readInt();
addressOfEntryPoint = readInt();
baseOfCode = readInt();
- if (isPE32Plus) {
+ if (!isPE32Plus) {
+ // only available in PE32
baseOfData = readInt();
}
}
@@ -433,7 +442,10 @@ public class COFFFileParser {
if (dir.getRVA() == 0 || dir.getSize() == 0) {
return null;
}
- return new ExportDirectoryTableImpl(rvaToFileOffset(dir.getRVA()), dir.getSize());
+ // ExportDirectoryTableImpl needs both the RVA and the
+ // RVA converted to a file offset.
+ return new
+ ExportDirectoryTableImpl(dir.getRVA(), dir.getSize());
}
};
@@ -526,6 +538,7 @@ public class COFFFileParser {
}
class ExportDirectoryTableImpl implements ExportDirectoryTable {
+ private int exportDataDirRVA;
private int offset;
private int size;
@@ -548,8 +561,9 @@ public class COFFFileParser {
private MemoizedObject exportOrdinalTable;
private MemoizedObject exportAddressTable;
- ExportDirectoryTableImpl(int offset, int size) {
- this.offset = offset;
+ ExportDirectoryTableImpl(int exportDataDirRVA, int size) {
+ this.exportDataDirRVA = exportDataDirRVA;
+ offset = rvaToFileOffset(exportDataDirRVA);
this.size = size;
seek(offset);
exportFlags = readInt();
@@ -595,6 +609,7 @@ public class COFFFileParser {
exportOrdinalTable = new MemoizedObject() {
public Object computeValue() {
+ // number of ordinals is same as the number of name pointers
short[] ordinals = new short[getNumberOfNamePointers()];
seek(rvaToFileOffset(getOrdinalTableRVA()));
for (int i = 0; i < ordinals.length; i++) {
@@ -608,14 +623,18 @@ public class COFFFileParser {
public Object computeValue() {
int[] addresses = new int[getNumberOfAddressTableEntries()];
seek(rvaToFileOffset(getExportAddressTableRVA()));
- // Must make two passes to avoid rvaToFileOffset
- // destroying seek() position
+ // The Export Address Table values are a union of two
+ // possible values:
+ // Export RVA - The address of the exported symbol when
+ // loaded into memory, relative to the image base.
+ // This value doesn't get converted into a file offset.
+ // Forwarder RVA - The pointer to a null-terminated ASCII
+ // string in the export section. This value gets
+ // converted into a file offset because we have to
+ // fetch the string.
for (int i = 0; i < addresses.length; i++) {
addresses[i] = readInt();
}
- for (int i = 0; i < addresses.length; i++) {
- addresses[i] = rvaToFileOffset(addresses[i]);
- }
return addresses;
}
};
@@ -648,11 +667,12 @@ public class COFFFileParser {
public boolean isExportAddressForwarder(short ordinal) {
int addr = getExportAddress(ordinal);
- return ((offset <= addr) && (addr < (offset + size)));
+ return ((exportDataDirRVA <= addr) &&
+ (addr < (exportDataDirRVA + size)));
}
public String getExportAddressForwarder(short ordinal) {
- seek(getExportAddress(ordinal));
+ seek(rvaToFileOffset(getExportAddress(ordinal)));
return readCString();
}
@@ -3371,10 +3391,17 @@ public class COFFFileParser {
throw new COFFException(e);
}
// Look up in string table
+ // FIXME: this index value is assumed to be in the valid range
name = getStringTable().get(index);
} else {
try {
- name = new String(tmpName, US_ASCII);
+ int length = 0;
+ // find last non-NULL
+ for (; length < tmpName.length && tmpName[length] != '\0';) {
+ length++;
+ }
+ // don't include NULL chars in returned name String
+ name = new String(tmpName, 0, length, US_ASCII);
} catch (UnsupportedEncodingException e) {
throw new COFFException(e);
}
@@ -3487,6 +3514,7 @@ public class COFFFileParser {
tmpName[5] << 16 |
tmpName[6] << 8 |
tmpName[7]);
+ // FIXME: stringOffset is assumed to be in the valid range
name = getStringTable().getAtOffset(stringOffset);
}
@@ -3698,12 +3726,13 @@ public class COFFFileParser {
StringTable(int offset) {
if (offset == 0) {
+ // no String Table
strings = new COFFString[0];
return;
}
seek(offset);
- int length = readInt();
+ int length = readInt(); // length includes itself
byte[] data = new byte[length - 4];
int numBytesRead = readBytes(data);
if (numBytesRead != data.length) {
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java
index ec563f1d6..fd9d39aa5 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/DumpExports.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,35 +37,48 @@ public class DumpExports {
String filename = args[0];
COFFFile file = COFFFileParser.getParser().parse(filename);
- ExportDirectoryTable exports =
- file.getHeader().
- getOptionalHeader().
- getDataDirectories().
- getExportDirectoryTable();
+
+ // get common point for both things we want to dump
+ OptionalHeaderDataDirectories dataDirs = file.getHeader().getOptionalHeader().
+ getDataDirectories();
+
+ // dump the header data directory for the Export Table:
+ DataDirectory dir = dataDirs.getExportTable();
+ System.out.println("Export table: RVA = " + dir.getRVA() + "/0x" +
+ Integer.toHexString(dir.getRVA()) + ", size = " + dir.getSize() + "/0x" +
+ Integer.toHexString(dir.getSize()));
+
+ System.out.println(file.getHeader().getNumberOfSections() + " sections in file");
+ for (int i = 1; i <= file.getHeader().getNumberOfSections(); i++) {
+ SectionHeader sec = file.getHeader().getSectionHeader(i);
+ System.out.println(" Section " + i + ":");
+ System.out.println(" Name = '" + sec.getName() + "'");
+ System.out.println(" VirtualSize = " + sec.getSize() + "/0x" +
+ Integer.toHexString(sec.getSize()));
+ System.out.println(" VirtualAddress = " + sec.getVirtualAddress() + "/0x" +
+ Integer.toHexString(sec.getVirtualAddress()));
+ System.out.println(" SizeOfRawData = " + sec.getSizeOfRawData() + "/0x" +
+ Integer.toHexString(sec.getSizeOfRawData()));
+ System.out.println(" PointerToRawData = " + sec.getPointerToRawData() + "/0x" +
+ Integer.toHexString(sec.getPointerToRawData()));
+ }
+
+ ExportDirectoryTable exports = dataDirs.getExportDirectoryTable();
if (exports == null) {
System.out.println("No exports found.");
} else {
- System.out.println(file.getHeader().getNumberOfSections() + " sections in file");
- for (int i = 0; i < file.getHeader().getNumberOfSections(); i++) {
- System.out.println(" Section " + i + ": " + file.getHeader().getSectionHeader(1 + i).getName());
- }
-
- DataDirectory dir = file.getHeader().getOptionalHeader().getDataDirectories().getExportTable();
- System.out.println("Export table: RVA = 0x" + Integer.toHexString(dir.getRVA()) +
- ", size = 0x" + Integer.toHexString(dir.getSize()));
-
System.out.println("DLL name: " + exports.getDLLName());
System.out.println("Time/date stamp 0x" + Integer.toHexString(exports.getTimeDateStamp()));
System.out.println("Major version 0x" + Integer.toHexString(exports.getMajorVersion() & 0xFFFF));
System.out.println("Minor version 0x" + Integer.toHexString(exports.getMinorVersion() & 0xFFFF));
- System.out.println(exports.getNumberOfNamePointers() + " functions found");
+ System.out.println(exports.getNumberOfNamePointers() + " exports found");
for (int i = 0; i < exports.getNumberOfNamePointers(); i++) {
- System.out.println(" 0x" +
- Integer.toHexString(exports.getExportAddress(exports.getExportOrdinal(i))) +
- " " +
- (exports.isExportAddressForwarder(exports.getExportOrdinal(i)) ?
- ("Forwarded to " + exports.getExportAddressForwarder(exports.getExportOrdinal(i))) :
- exports.getExportName(i)));
+ short ordinal = exports.getExportOrdinal(i);
+ System.out.print("[" + i + "] '" + exports.getExportName(i) + "': [" +
+ ordinal + "] = 0x" + Integer.toHexString(exports.getExportAddress(ordinal)));
+ System.out.println(exports.isExportAddressForwarder(ordinal)
+ ? " Forwarded to '" + exports.getExportAddressForwarder(ordinal) + "'"
+ : "");
}
}
}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java
index 6f026838d..e6f42df3a 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/coff/TestParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,8 +42,8 @@ public class TestParser {
COFFHeader header = file.getHeader();
int numSections = header.getNumberOfSections();
System.out.println(numSections + " sections detected.");
- for (int i = 0; i < numSections; i++) {
- SectionHeader secHeader = header.getSectionHeader(1 + i);
+ for (int i = 1; i <= numSections; i++) {
+ SectionHeader secHeader = header.getSectionHeader(i);
System.out.println(secHeader.getName());
}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java
index 53141a6d2..3e5a6aa96 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -506,7 +506,6 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger
throw new DebuggerException("Unimplemented");
}
- private static String DTFWHome;
private static String imagePath;
private static String symbolPath;
private static boolean useNativeLookup;
@@ -514,81 +513,143 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger
static {
/*
- * sawindbg.dll depends on dbgeng.dll which
- * itself depends on dbghelp.dll. dbgeng.dll and dbghelp.dll.
- * On systems newer than Windows 2000, these two .dlls are
- * in the standard system directory so we will find them there.
- * On Windows 2000 and earlier, these files do not exist.
- * The user must download Debugging Tools For Windows (DTFW)
- * and install it in order to use SA.
+ * sawindbg.dll depends on dbgeng.dll which itself depends on
+ * dbghelp.dll. We have to make sure that the dbgeng.dll and
+ * dbghelp.dll that we load are compatible with each other. We
+ * load both of those libraries from the same directory based
+ * on the theory that co-located libraries are compatible.
*
- * We have to make sure we use the two files from the same directory
- * in case there are more than one copy on the system because
- * one version of dbgeng.dll might not be compatible with a
- * different version of dbghelp.dll.
- * We first look for them in the directory pointed at by
- * env. var. DEBUGGINGTOOLSFORWINDOWS, next in the default
- * installation dir for DTFW, and lastly in the standard
- * system directory. We expect that that we will find
- * them in the standard system directory on all systems
- * newer than Windows 2000.
+ * On Windows 2000 and earlier, dbgeng.dll and dbghelp.dll were
+ * not included as part of the standard system directory. On
+ * systems newer than Windows 2000, dbgeng.dll and dbghelp.dll
+ * are included in the standard system directory. However, the
+ * versions included in the standard system directory may not
+ * be able to handle symbol information for the newer compilers.
+ *
+ * We search for and explicitly load the libraries using the
+ * following directory search order:
+ *
+ * - java.home/bin (same as $JAVA_HOME/jre/bin)
+ * - dir named by DEBUGGINGTOOLSFORWINDOWS environment variable
+ * - various "Debugging Tools For Windows" program directories
+ * - the system directory ($SYSROOT/system32)
+ *
+ * If SA is invoked with -Dsun.jvm.hotspot.loadLibrary.DEBUG=1,
+ * then debug messages about library loading are printed to
+ * System.err.
*/
- String dirName = null;
- DTFWHome = System.getenv("DEBUGGINGTOOLSFORWINDOWS");
- if (DTFWHome == null) {
- // See if we have the files in the default location.
+ String dbgengPath = null;
+ String dbghelpPath = null;
+ String sawindbgPath = null;
+ List searchList = new ArrayList();
+
+ boolean loadLibraryDEBUG =
+ System.getProperty("sun.jvm.hotspot.loadLibrary.DEBUG") != null;
+
+ {
+ // First place to search is co-located with sawindbg.dll in
+ // $JAVA_HOME/jre/bin (java.home property is set to $JAVA_HOME/jre):
+ searchList.add(System.getProperty("java.home") + File.separator + "bin");
+ sawindbgPath = (String) searchList.get(0) + File.separator +
+ "sawindbg.dll";
+
+ // second place to search is specified by an environment variable:
+ String DTFWHome = System.getenv("DEBUGGINGTOOLSFORWINDOWS");
+ if (DTFWHome != null) {
+ searchList.add(DTFWHome);
+ }
+
+ // 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";
+ 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");
}
- {
- String dbghelp = DTFWHome + File.separator + "dbghelp.dll";
- String dbgeng = DTFWHome + File.separator + "dbgeng.dll";
- File fhelp = new File(dbghelp);
- File feng = new File(dbgeng);
- if (fhelp.exists() && feng.exists()) {
- // found both, we are happy.
- // NOTE: The order of loads is important! If we load dbgeng.dll
- // first, then the dependency - dbghelp.dll - will be loaded
- // from usual DLL search thereby defeating the purpose!
- System.load(dbghelp);
- System.load(dbgeng);
- } else if (! fhelp.exists() && ! feng.exists()) {
- // neither exist. We will ignore this dir and assume
- // they are in the system dir.
- DTFWHome = null;
- } else {
- // one exists but not the other
- //System.err.println("Error: Both files dbghelp.dll and dbgeng.dll "
- // "must exist in directory " + DTFWHome);
- throw new UnsatisfiedLinkError("Both files dbghelp.dll and " +
- "dbgeng.dll must exist in " +
- "directory " + DTFWHome);
+ 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 (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.");
+
+ if (dbgengPath == null || dbghelpPath == null) {
+ // at least one of the files wasn't found anywhere we searched
+ String mesg = null;
+
+ if (dbgengPath == null && dbghelpPath == null) {
+ mesg = "dbgeng.dll and dbghelp.dll cannot be found. ";
+ } else if (dbgengPath == null) {
+ mesg = "dbgeng.dll cannot be found (dbghelp.dll was found). ";
+ } else {
+ mesg = "dbghelp.dll cannot be found (dbgeng.dll was found). ";
}
+ throw new UnsatisfiedLinkError(mesg +
+ "Please search microsoft.com for 'Debugging Tools For Windows', " +
+ "and either download it to the default location, or download it " +
+ "to a custom location and set environment variable " +
+ "'DEBUGGINGTOOLSFORWINDOWS' to the pathname of that location.");
}
+ // NOTE: The order of loads is important! If we load dbgeng.dll
+ // first, then the dependency - dbghelp.dll - will be loaded
+ // from usual DLL search thereby defeating the purpose!
+ if (loadLibraryDEBUG) {
+ System.err.println("DEBUG: loading '" + dbghelpPath + "'.");
+ }
+ System.load(dbghelpPath);
+ if (loadLibraryDEBUG) {
+ System.err.println("DEBUG: loading '" + dbgengPath + "'.");
+ }
+ System.load(dbgengPath);
+
// Now, load sawindbg.dll
- System.loadLibrary("sawindbg");
+ if (loadLibraryDEBUG) {
+ System.err.println("DEBUG: loading '" + sawindbgPath + "'.");
+ }
+ System.load(sawindbgPath);
+
// where do I find '.exe', '.dll' files?
imagePath = System.getProperty("sun.jvm.hotspot.debugger.windbg.imagePath");
if (imagePath == null) {
diff --git a/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java b/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java
index d7101696c..979d80b30 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java
@@ -30,6 +30,7 @@ import sun.jvm.hotspot.asm.*;
import sun.jvm.hotspot.asm.sparc.*;
import sun.jvm.hotspot.asm.x86.*;
import sun.jvm.hotspot.asm.ia64.*;
+import sun.jvm.hotspot.asm.amd64.*;
import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.compiler.*;
import sun.jvm.hotspot.debugger.*;
@@ -198,6 +199,8 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
cpuHelper = new SPARCHelper();
} else if (cpu.equals("x86")) {
cpuHelper = new X86Helper();
+ } else if (cpu.equals("amd64")) {
+ cpuHelper = new AMD64Helper();
} else if (cpu.equals("ia64")) {
cpuHelper = new IA64Helper();
} else {
diff --git a/make/jprt.properties b/make/jprt.properties
index 132331e10..c8bbb3c6c 100644
--- a/make/jprt.properties
+++ b/make/jprt.properties
@@ -150,6 +150,7 @@ jprt.build.targets= \
jprt.my.solaris.sparc.test.targets= \
${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-{c1|c2}-runThese, \
${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_ParOldGC, \
${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_ParallelGC, \
${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}-{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-c2-runThese, \
${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_ParOldGC, \
${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_ParallelGC, \
${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}-{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-c2-runThese, \
${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_ParOldGC, \
${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_ParallelGC, \
${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}-{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-{c1|c2}-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_ParOldGC, \
${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_CMS, \
${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}-{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-c1-runThese_Xcomp, \
${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_ParOldGC, \
${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_CMS, \
${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}-{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-GCBasher_default, \
${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_ParOldGC, \
${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_G1, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-jbb_ParOldGC
jprt.my.windows.i586.test.targets = \
${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-{c1|c2}-runThese, \
${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_ParOldGC, \
${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_CMS, \
${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}-{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-c2-runThese, \
${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_ParOldGC, \
${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_ParallelGC, \
${jprt.my.windows.x64}-product-c2-jbb_G1, \
diff --git a/make/solaris/makefiles/buildtree.make b/make/solaris/makefiles/buildtree.make
index 9a1e5fd96..08224ef11 100644
--- a/make/solaris/makefiles/buildtree.make
+++ b/make/solaris/makefiles/buildtree.make
@@ -61,7 +61,7 @@ include $(GAMMADIR)/make/scm.make
QUIETLY$(MAKE_VERBOSE) = @
# For now, until the compiler is less wobbly:
-TESTFLAGS = -Xbatch -showversion
+TESTFLAGS = -Xbatch -Xmx32m -showversion
### maye ARCH_XXX instead?
ifdef USE_GCC
diff --git a/make/solaris/makefiles/vm.make b/make/solaris/makefiles/vm.make
index 93d8396fa..9728b1dc4 100644
--- a/make/solaris/makefiles/vm.make
+++ b/make/solaris/makefiles/vm.make
@@ -119,6 +119,10 @@ else
LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle
endif # sparcWorks
+ifeq ("${Platform_arch}", "sparc")
+LIBS += -lkstat
+endif
+
# By default, link the *.o into the library, not the executable.
LINK_INTO$(LINK_INTO) = LIBJVM
diff --git a/make/windows/makefiles/compile.make b/make/windows/makefiles/compile.make
index 42c1e8ab3..47d924418 100644
--- a/make/windows/makefiles/compile.make
+++ b/make/windows/makefiles/compile.make
@@ -152,7 +152,7 @@ MS_RUNTIME_OPTION = /MTd /D "_DEBUG"
!endif
# Always add the _STATIC_CPPLIB flag
-STATIC_CPPLIB_OPTION = /D _STATIC_CPPLIB
+STATIC_CPPLIB_OPTION = /D _STATIC_CPPLIB /D _DISABLE_DEPRECATE_STATIC_CPPLIB
MS_RUNTIME_OPTION = $(MS_RUNTIME_OPTION) $(STATIC_CPPLIB_OPTION)
CPP_FLAGS=$(CPP_FLAGS) $(MS_RUNTIME_OPTION)
diff --git a/src/cpu/sparc/vm/assembler_sparc.cpp b/src/cpu/sparc/vm/assembler_sparc.cpp
index 8512afcba..f1c390362 100644
--- a/src/cpu/sparc/vm/assembler_sparc.cpp
+++ b/src/cpu/sparc/vm/assembler_sparc.cpp
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "asm/assembler.hpp"
#include "assembler_sparc.inline.hpp"
#include "gc_interface/collectedHeap.inline.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
- if (worst_case) return 7;
- intptr_t iaddr = (intptr_t)a;
- int hi32 = (int)(iaddr >> 32);
- int lo32 = (int)(iaddr);
- int inst_count;
- if (hi32 == 0 && lo32 >= 0)
- inst_count = 1;
- else if (hi32 == -1)
- inst_count = 2;
+ if (worst_case) return 7;
+ intptr_t iaddr = (intptr_t) a;
+ int msb32 = (int) (iaddr >> 32);
+ int lsb32 = (int) (iaddr);
+ int count;
+ if (msb32 == 0 && lsb32 >= 0)
+ count = 1;
+ else if (msb32 == -1)
+ count = 2;
else {
- inst_count = 2;
- if ( hi32 & 0x3ff )
- inst_count++;
- if ( lo32 & 0xFFFFFC00 ) {
- if( (lo32 >> 20) & 0xfff ) inst_count += 2;
- if( (lo32 >> 10) & 0x3ff ) inst_count += 2;
+ count = 2;
+ if (msb32 & 0x3ff)
+ count++;
+ if (lsb32 & 0xFFFFFC00 ) {
+ if ((lsb32 >> 20) & 0xfff) count += 2;
+ if ((lsb32 >> 10) & 0x3ff) count += 2;
}
}
- return BytesPerInstWord * inst_count;
+ return count;
#else
- return BytesPerInstWord;
+ return 1;
#endif
}
-int MacroAssembler::worst_case_size_of_set() {
- return size_of_sethi(NULL, true) + 1;
+int MacroAssembler::worst_case_insts_for_set() {
+ 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) {
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) {
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();
- int hi = (int)(value >> 32);
- int lo = (int)(value & ~0);
+ int hi = (int) (value >> 32);
+ int lo = (int) (value & ~0);
int count = 0;
// (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);
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
bind(do_refill);
ld_ptr(G2_thread, in_bytes(JavaThread::tlab_size_offset()), 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);
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();
}
+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) {
switch (cond) {
// Note some conditions are synonyms for others
diff --git a/src/cpu/sparc/vm/assembler_sparc.hpp b/src/cpu/sparc/vm/assembler_sparc.hpp
index ae4357edd..296305664 100644
--- a/src/cpu/sparc/vm/assembler_sparc.hpp
+++ b/src/cpu/sparc/vm/assembler_sparc.hpp
@@ -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.
*
* 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 patchable_sethi(const AddressLiteral& addrlit, Register d);
- // compute the size of a sethi/set
- static int size_of_sethi( address a, bool worst_case = false );
- static int worst_case_size_of_set();
+ // compute the number of instructions for a sethi/set
+ static int insts_for_sethi( address a, bool worst_case = false );
+ static int worst_case_insts_for_set();
// set may be either setsw or setuw (high 32 bits may be zero or sign)
private:
void internal_set(const AddressLiteral& al, Register d, bool ForceRelocatable);
+ static int insts_for_internal_set(intptr_t value);
public:
void set(const AddressLiteral& addrlit, Register d);
void set(intptr_t value, Register d);
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(intptr_t value, Register d);
void set64(jlong value, Register d, Register tmp);
-
- // Compute size of set64.
- static int size_of_set64(jlong value);
+ static int insts_for_set64(jlong value);
// sign-extend 32 to 64
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
);
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
void lookup_interface_method(Register recv_klass,
diff --git a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp
index 1e02e0a68..15ca82f28 100644
--- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp
+++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp
@@ -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;
switch (condition) {
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();
}
Label skip;
- __ br(acond, false, Assembler::pt, skip);
+#ifdef _LP64
+ if (type == T_INT) {
+ __ 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) {
Register dest = result->as_register();
if (Assembler::is_simm13(opr1->as_jint())) {
@@ -2688,6 +2692,11 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) {
#ifdef _LP64
__ mov(cmp_value_lo, t1);
__ 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
// move high and low halves of long values into single registers
__ 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);
__ srl(new_value_lo, 0, new_value_lo);
__ or3(t2, new_value_lo, t2); // t2 holds 64-bit value to swap
-#endif
// 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);
-
+ // 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) {
Register addr = op->addr()->as_pointer_register();
Register cmp_value = op->cmp_value()->as_register();
diff --git a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp
index 1abbdb51d..8869de5e8 100644
--- a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp
+++ b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp
@@ -662,7 +662,7 @@ void LIRGenerator::do_AttemptUpdate(Intrinsic* x) {
// generate conditional move of boolean result
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 {
ShouldNotReachHere();
}
-
// generate conditional move of boolean result
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.
// Precise card mark since could either be object or array
post_barrier(addr, val.result());
diff --git a/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp b/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp
index 6340156f7..85eb66833 100644
--- a/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp
+++ b/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp
@@ -166,7 +166,7 @@ void C1_MacroAssembler::try_allocate(
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
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
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);
} else {
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(
Register obj, // result: pointer to object after successful allocation
Register t1, // temp register
- Register t2, // temp register
+ Register t2, // temp register, must be a global register for try_allocate
Register t3, // temp register
int hdr_size, // object header size in words
int obj_size, // object size in words
diff --git a/src/cpu/sparc/vm/c1_MacroAssembler_sparc.hpp b/src/cpu/sparc/vm/c1_MacroAssembler_sparc.hpp
index b8b063928..c0178e5e0 100644
--- a/src/cpu/sparc/vm/c1_MacroAssembler_sparc.hpp
+++ b/src/cpu/sparc/vm/c1_MacroAssembler_sparc.hpp
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
diff --git a/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp
index 7dabe35c2..7ce9a73b6 100644
--- a/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp
+++ b/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp
@@ -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.
*
* 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
__ 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);
+
__ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2);
__ verify_oop(O0_obj);
__ mov(O0, I0);
@@ -459,6 +461,8 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
// get the instance 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);
+ __ incr_allocated_bytes(G1_obj_size, 0, G3_t1);
+
__ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2);
__ verify_oop(O0_obj);
__ mov(O0, I0);
@@ -573,6 +577,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ 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
+ __ incr_allocated_bytes(G1_arr_size, 0, G3_t1);
__ initialize_header(O0_obj, G5_klass, G4_length, G3_t1, O1_t2);
__ ldub(klass_lh, G3_t1, klass_lh_header_size_offset);
diff --git a/src/cpu/sparc/vm/methodHandles_sparc.cpp b/src/cpu/sparc/vm/methodHandles_sparc.cpp
index 699f9151b..2fb2e56d8 100644
--- a/src/cpu/sparc/vm/methodHandles_sparc.cpp
+++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp
@@ -395,18 +395,23 @@ int MethodHandles::adapter_conversion_ops_supported_mask() {
//
// Generate an "entry" field for a method handle.
// 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,
// as set up by generate_method_handle_interpreter_entry():
// - G5: garbage temp (was MethodHandle.invoke methodOop, unused)
// - G3: receiver method handle
// - O5_savedSP: sender SP (must preserve)
- Register O0_argslot = O0;
- Register O1_scratch = O1;
- Register O2_scratch = O2;
- Register O3_scratch = O3;
- Register G5_index = G5;
+ const Register O0_argslot = O0;
+ const Register O1_scratch = O1;
+ const Register O2_scratch = O2;
+ const Register O3_scratch = O3;
+ 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");
@@ -439,48 +444,36 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
case _raise_exception:
{
// Not a real MH entry, but rather shared code for raising an
- // exception. Extra local arguments are passed in scratch
- // registers, as required type in O3, failing object (or NULL)
- // in O2, failing bytecode type in O1.
+ // exception. Since we use a C2I adapter to set up the
+ // interpreter state, arguments are expected in compiler
+ // 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.
- // Push arguments as if coming from the interpreter.
- 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;
+ Label L_no_method;
// FIXME: fill in _raise_exception_method with a suitable sun.dyn method
__ set(AddressLiteral((address) &_raise_exception_method), G5_method);
__ ld_ptr(Address(G5_method, 0), G5_method);
__ tst(G5_method);
- __ brx(Assembler::zero, false, Assembler::pn, no_method);
+ __ brx(Assembler::zero, false, Assembler::pn, L_no_method);
__ delayed()->nop();
- int jobject_oop_offset = 0;
+ const int jobject_oop_offset = 0;
__ ld_ptr(Address(G5_method, jobject_oop_offset), G5_method);
__ tst(G5_method);
- __ brx(Assembler::zero, false, Assembler::pn, no_method);
+ __ brx(Assembler::zero, false, Assembler::pn, L_no_method);
__ delayed()->nop();
__ verify_oop(G5_method);
- __ jump_indirect_to(G5_method_fie, O1_scratch);
+ __ jump_to(AddressLiteral(c2i_entry), O3_scratch);
__ delayed()->nop();
// 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.
- __ bind(no_method);
- __ unimplemented("_raise_exception no method");
+ __ bind(L_no_method);
+ __ unimplemented("call throw_WrongMethodType_entry");
}
break;
@@ -570,10 +563,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
// Throw an exception.
// For historical reasons, it will be IncompatibleClassChangeError.
__ unimplemented("not tested yet");
- __ ld_ptr(Address(O1_intf, java_mirror_offset), O3_scratch); // required interface
- __ mov(O0_klass, O2_scratch); // bad receiver
- __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O0_argslot);
- __ delayed()->mov(Bytecodes::_invokeinterface, O1_scratch); // who is complaining?
+ __ ld_ptr(Address(O1_intf, java_mirror_offset), O2_required); // required interface
+ __ mov( O0_klass, O1_actual); // bad receiver
+ __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O3_scratch);
+ __ delayed()->mov(Bytecodes::_invokeinterface, O0_code); // who is complaining?
}
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);
// If we get here, the type check failed!
- __ ldsw(G3_amh_vmargslot, O0_argslot); // reload argslot field
- __ load_heap_oop(G3_amh_argument, O3_scratch); // required class
- __ ld_ptr(vmarg, O2_scratch); // bad object
- __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O0_argslot);
- __ delayed()->mov(Bytecodes::_checkcast, O1_scratch); // who is complaining?
+ __ load_heap_oop(G3_amh_argument, O2_required); // required class
+ __ ld_ptr( vmarg, O1_actual); // bad object
+ __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O3_scratch);
+ __ delayed()->mov(Bytecodes::_checkcast, O0_code); // who is complaining?
__ bind(done);
// Get the new MH:
diff --git a/src/cpu/sparc/vm/sparc.ad b/src/cpu/sparc/vm/sparc.ad
index 018fe70b9..25117f205 100644
--- a/src/cpu/sparc/vm/sparc.ad
+++ b/src/cpu/sparc/vm/sparc.ad
@@ -1086,9 +1086,9 @@ void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
uint MachConstantBaseNode::size(PhaseRegAlloc*) const {
if (UseRDPCForConstantTableBase) {
// 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 {
- 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 {
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);
%}
-// Pointer Immediate: 32 or 64-bit
+#ifdef _LP64
+// Pointer Immediate: 64-bit
operand immP_set() %{
- predicate(!VM_Version::is_niagara1_plus());
+ predicate(!VM_Version::is_niagara_plus());
match(ConP);
op_cost(5);
@@ -3564,10 +3565,21 @@ operand immP_set() %{
interface(CONST_INTER);
%}
-// Pointer Immediate: 32 or 64-bit
+// Pointer Immediate: 64-bit
// From Niagara2 processors on a load should be better than materializing.
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);
+
+ op_cost(5);
+ // formats are generated automatically for constants and base registers
+ format %{ %}
+ 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);
@@ -3575,6 +3587,7 @@ operand immP_load() %{
format %{ %}
interface(CONST_INTER);
%}
+#endif
operand immP13() %{
predicate((-4096 < n->get_ptr()) && (n->get_ptr() <= 4095));
@@ -3673,7 +3686,7 @@ operand immL_32bits() %{
// Long Immediate: cheap (materialize in <= 3 instructions)
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);
op_cost(0);
@@ -3683,7 +3696,7 @@ operand immL_cheap() %{
// Long Immediate: expensive (materialize in > 3 instructions)
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);
op_cost(0);
@@ -6094,8 +6107,18 @@ instruct loadConP_load(iRegP dst, immP_load con) %{
ins_cost(MEMORY_REF_COST);
format %{ "LD [$constanttablebase + $constantoffset],$dst\t! load from constant table: ptr=$con" %}
ins_encode %{
- RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset($con), $dst$$Register);
- __ ld_ptr($constanttablebase, con_offset, $dst$$Register);
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset($con), $dst$$Register);
+ __ ld_ptr($constanttablebase, con_offset, $dst$$Register);
+ %}
+ 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);
%}
diff --git a/src/cpu/sparc/vm/templateTable_sparc.cpp b/src/cpu/sparc/vm/templateTable_sparc.cpp
index 896372237..6bfaccd64 100644
--- a/src/cpu/sparc/vm/templateTable_sparc.cpp
+++ b/src/cpu/sparc/vm/templateTable_sparc.cpp
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -3393,21 +3393,21 @@ void TemplateTable::_new() {
__ delayed()->st_ptr(RnewTopValue, G2_thread, in_bytes(JavaThread::tlab_top_offset()));
if (allow_shared_alloc) {
- // Check if tlab should be discarded (refill_waste_limit >= free)
- __ ld_ptr(G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset()), RtlabWasteLimitValue);
- __ sub(RendValue, RoldTopValue, RfreeValue);
+ // Check if tlab should be discarded (refill_waste_limit >= free)
+ __ ld_ptr(G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset()), RtlabWasteLimitValue);
+ __ sub(RendValue, RoldTopValue, RfreeValue);
#ifdef _LP64
- __ srlx(RfreeValue, LogHeapWordSize, RfreeValue);
+ __ srlx(RfreeValue, LogHeapWordSize, RfreeValue);
#else
- __ srl(RfreeValue, LogHeapWordSize, RfreeValue);
+ __ srl(RfreeValue, LogHeapWordSize, RfreeValue);
#endif
- __ cmp(RtlabWasteLimitValue, RfreeValue);
- __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, slow_case); // tlab waste is small
- __ delayed()->nop();
+ __ cmp(RtlabWasteLimitValue, RfreeValue);
+ __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, slow_case); // tlab waste is small
+ __ delayed()->nop();
- // increment waste limit to prevent getting stuck on this slow path
- __ add(RtlabWasteLimitValue, ThreadLocalAllocBuffer::refill_waste_limit_increment(), RtlabWasteLimitValue);
- __ st_ptr(RtlabWasteLimitValue, G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset()));
+ // increment waste limit to prevent getting stuck on this slow path
+ __ add(RtlabWasteLimitValue, ThreadLocalAllocBuffer::refill_waste_limit_increment(), RtlabWasteLimitValue);
+ __ st_ptr(RtlabWasteLimitValue, G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset()));
} else {
// No allocation in the shared eden.
__ br(Assembler::always, false, Assembler::pt, slow_case);
@@ -3445,6 +3445,9 @@ void TemplateTable::_new() {
__ cmp(RoldTopValue, RnewTopValue);
__ brx(Assembler::notEqual, false, Assembler::pn, retry);
__ delayed()->nop();
+
+ // bump total bytes allocated by this thread
+ __ incr_allocated_bytes(Roffset, 0, G1_scratch);
}
if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) {
diff --git a/src/cpu/sparc/vm/vm_version_sparc.cpp b/src/cpu/sparc/vm/vm_version_sparc.cpp
index 9e1928619..6db8c7ad1 100644
--- a/src/cpu/sparc/vm/vm_version_sparc.cpp
+++ b/src/cpu/sparc/vm/vm_version_sparc.cpp
@@ -38,12 +38,6 @@
int VM_Version::_features = VM_Version::unknown_m;
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() {
_features = determine_features();
PrefetchCopyIntervalInBytes = prefetch_copy_interval_in_bytes();
@@ -69,11 +63,21 @@ void VM_Version::initialize() {
_supports_cx8 = has_v9();
- if (is_niagara1()) {
+ if (is_niagara()) {
// Indirect branch is the same cost as direct
if (FLAG_IS_DEFAULT(UseInlineCaches)) {
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
// 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.
@@ -89,7 +93,7 @@ void VM_Version::initialize() {
if (FLAG_IS_DEFAULT(InteriorEntryAlignment)) {
FLAG_SET_DEFAULT(InteriorEntryAlignment, 4);
}
- if (is_niagara1_plus()) {
+ if (is_niagara_plus()) {
if (has_blk_init() && AllocatePrefetchStyle > 0 &&
FLAG_IS_DEFAULT(AllocatePrefetchStyle)) {
// Use BIS instruction for allocation prefetch.
@@ -105,15 +109,6 @@ void VM_Version::initialize() {
}
}
#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.
@@ -129,17 +124,18 @@ void VM_Version::initialize() {
#endif
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_v9() ? ", has_v9" : ""),
(has_hardware_popc() ? ", popc" : ""),
(has_vis1() ? ", has_vis1" : ""),
(has_vis2() ? ", has_vis2" : ""),
+ (has_vis3() ? ", has_vis3" : ""),
(has_blk_init() ? ", has_blk_init" : ""),
(is_ultra3() ? ", is_ultra3" : ""),
(is_sun4v() ? ", is_sun4v" : ""),
- (is_niagara1() ? ", is_niagara1" : ""),
- (is_niagara1_plus() ? ", is_niagara1_plus" : ""),
+ (is_niagara() ? ", is_niagara" : ""),
+ (is_niagara_plus() ? ", is_niagara_plus" : ""),
(is_sparc64() ? ", is_sparc64" : ""),
(!has_hardware_mul32() ? ", no-mul32" : ""),
(!has_hardware_div32() ? ", no-div32" : ""),
@@ -190,17 +186,18 @@ int VM_Version::determine_features() {
warning("Cannot recognize SPARC version. Default to V9");
}
- if (UseNiagaraInstrs) {
- if (is_niagara1(features)) {
+ assert(is_T_family(features) == is_niagara(features), "Niagara should be T series");
+ if (UseNiagaraInstrs) { // Force code generation for Niagara
+ if (is_T_family(features)) {
// Happy to accomodate...
} else {
NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Version is Forced-Niagara");)
- features = niagara1_m;
+ features |= T_family_m;
}
} 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");)
- features &= ~niagara1_unique_m;
+ features &= ~(T_family_m | T1_model_m);
} else {
// Happy to accomodate...
}
@@ -222,7 +219,7 @@ void VM_Version::revert() {
unsigned int VM_Version::calc_parallel_worker_threads() {
unsigned int result;
- if (is_niagara1_plus()) {
+ if (is_niagara_plus()) {
result = nof_parallel_worker_threads(5, 16, 8);
} else {
result = nof_parallel_worker_threads(5, 8, 8);
diff --git a/src/cpu/sparc/vm/vm_version_sparc.hpp b/src/cpu/sparc/vm/vm_version_sparc.hpp
index 5ae1fcbc3..c83d2de99 100644
--- a/src/cpu/sparc/vm/vm_version_sparc.hpp
+++ b/src/cpu/sparc/vm/vm_version_sparc.hpp
@@ -41,7 +41,12 @@ protected:
vis2_instructions = 7,
sun4v_instructions = 8,
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 {
@@ -59,6 +64,11 @@ protected:
sun4v_m = 1 << sun4v_instructions,
blk_init_instructions_m = 1 << blk_init_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_v9_m = generic_v8_m | v9_instructions_m,
@@ -76,8 +86,13 @@ protected:
static int determine_features();
static int platform_features(int features);
- static bool is_niagara1(int features) { return (features & sun4v_m) != 0; }
- static bool is_sparc64(int features) { return (features & fmaf_instructions_m) != 0; }
+ // Returns true if the platform is in the niagara line (T series)
+ 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; }
@@ -94,6 +109,7 @@ public:
static bool has_hardware_popc() { return (_features & hardware_popc_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_vis3() { return (_features & vis3_instructions_m) != 0; }
static bool has_blk_init() { return (_features & blk_init_instructions_m) != 0; }
static bool supports_compare_and_exchange()
@@ -101,14 +117,14 @@ public:
static bool is_ultra3() { return (_features & ultra3_m) == ultra3_m; }
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 and
- // newer than the niagara1.
- static bool is_niagara1_plus();
- static bool is_sparc64() { return is_sparc64(_features); }
-
- static bool has_fast_fxtof() { return has_v9() && !is_ultra3(); }
- static bool has_fast_idiv() { return is_niagara1_plus() || is_sparc64(); }
+ // Returns true if the platform is in the niagara line (T series)
+ // and newer than the niagara1.
+ static bool is_niagara_plus() { return is_T_family(_features) && !is_T1_model(_features); }
+ // Fujitsu SPARC64
+ static bool is_sparc64() { return (_features & sparc64_family_m) != 0; }
+
+ static bool has_fast_fxtof() { return is_niagara() || is_sparc64() || has_v9() && !is_ultra3(); }
+ static bool has_fast_idiv() { return is_niagara_plus() || is_sparc64(); }
static const char* cpu_features() { return _features_str; }
diff --git a/src/cpu/x86/vm/assembler_x86.cpp b/src/cpu/x86/vm/assembler_x86.cpp
index 85dc5411f..4c87f23cd 100644
--- a/src/cpu/x86/vm/assembler_x86.cpp
+++ b/src/cpu/x86/vm/assembler_x86.cpp
@@ -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.
*
* 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) {
prefix(dst);
@@ -2195,9 +2208,7 @@ void Assembler::notl(Register dst) {
void Assembler::orl(Address dst, int32_t imm32) {
InstructionMark im(this);
prefix(dst);
- emit_byte(0x81);
- emit_operand(rcx, dst, 4);
- emit_long(imm32);
+ emit_arith_operand(0x81, rcx, dst, 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);
}
-
void Assembler::orl(Register dst, Address src) {
InstructionMark im(this);
prefix(src, dst);
@@ -2213,7 +2223,6 @@ void Assembler::orl(Register dst, Address src) {
emit_operand(dst, src);
}
-
void Assembler::orl(Register dst, Register src) {
(void) prefix_and_encode(dst->encoding(), src->encoding());
emit_arith(0x0B, 0xC0, dst, src);
@@ -2692,20 +2701,7 @@ void Assembler::stmxcsr( Address dst) {
void Assembler::subl(Address dst, int32_t imm32) {
InstructionMark im(this);
prefix(dst);
- if (is8bit(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);
+ emit_arith_operand(0x81, rbp, dst, imm32);
}
void Assembler::subl(Address dst, Register src) {
@@ -2715,6 +2711,11 @@ void Assembler::subl(Address dst, Register src) {
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) {
InstructionMark im(this);
prefix(src, dst);
@@ -4333,6 +4334,7 @@ void Assembler::sarq(Register dst) {
emit_byte(0xD3);
emit_byte(0xF8 | encode);
}
+
void Assembler::sbbq(Address dst, int32_t imm32) {
InstructionMark im(this);
prefixq(dst);
@@ -4392,20 +4394,7 @@ void Assembler::shrq(Register dst) {
void Assembler::subq(Address dst, int32_t imm32) {
InstructionMark im(this);
prefixq(dst);
- if (is8bit(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);
+ emit_arith_operand(0x81, rbp, dst, imm32);
}
void Assembler::subq(Address dst, Register src) {
@@ -4415,6 +4404,11 @@ void Assembler::subq(Address dst, Register src) {
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) {
InstructionMark im(this);
prefixq(src, dst);
@@ -7136,9 +7130,9 @@ void MacroAssembler::tlab_allocate(Register obj,
}
// Preserves rbx, and rdx.
-void MacroAssembler::tlab_refill(Label& retry,
- Label& try_eden,
- Label& slow_case) {
+Register MacroAssembler::tlab_refill(Label& retry,
+ Label& try_eden,
+ Label& slow_case) {
Register top = rax;
Register t1 = rcx;
Register t2 = rsi;
@@ -7185,7 +7179,7 @@ void MacroAssembler::tlab_refill(Label& retry,
// if tlab is currently allocated (top or end != null) then
// fill [top, end + alignment_reserve) with array object
- testptr (top, top);
+ testptr(top, top);
jcc(Assembler::zero, do_refill);
// set up the mark word
@@ -7197,16 +7191,20 @@ void MacroAssembler::tlab_refill(Label& retry,
movl(Address(top, arrayOopDesc::length_offset_in_bytes()), t1);
// set klass to intArrayKlass
// 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
// klass field is not null.
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
bind(do_refill);
movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_size_offset())));
shlptr(t1, LogHeapWordSize);
- // add object_size ??
+ // allocate new tlab, address returned in top
eden_allocate(top, t1, 0, t2, slow_case);
// 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);
verify_tlab();
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;
diff --git a/src/cpu/x86/vm/assembler_x86.hpp b/src/cpu/x86/vm/assembler_x86.hpp
index b9fcc2eff..a1a8a96de 100644
--- a/src/cpu/x86/vm/assembler_x86.hpp
+++ b/src/cpu/x86/vm/assembler_x86.hpp
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -674,12 +674,14 @@ private:
// Utilities
#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; }
#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; }
-#endif // LP64
+#endif // _LP64
// Generic instructions
// Does 32bit or 64bit as needed for the platform. In some sense these
@@ -705,7 +707,6 @@ private:
void push(void* v);
void pop(void* v);
-
// These do register sized moves/scans
void rep_mov();
void rep_set();
@@ -716,6 +717,8 @@ private:
// 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, Address src);
void adcl(Register dst, Register src);
@@ -724,7 +727,6 @@ private:
void adcq(Register dst, Address src);
void adcq(Register dst, Register src);
-
void addl(Address dst, int32_t imm32);
void addl(Address dst, Register src);
void addl(Register dst, int32_t imm32);
@@ -737,7 +739,6 @@ private:
void addq(Register dst, Address src);
void addq(Register dst, Register src);
-
void addr_nop_4();
void addr_nop_5();
void addr_nop_7();
@@ -759,7 +760,6 @@ private:
void andq(Register dst, Address src);
void andq(Register dst, Register src);
-
// Bitwise Logical AND of Packed Double-Precision Floating-Point Values
void andpd(XMMRegister dst, Address src);
void andpd(XMMRegister dst, XMMRegister src);
@@ -1151,7 +1151,7 @@ private:
#ifdef _LP64
void movq(Register dst, Register src);
void movq(Register dst, Address src);
- void movq(Address dst, Register src);
+ void movq(Address dst, Register src);
#endif
void movq(Address dst, MMXRegister src );
@@ -1177,7 +1177,7 @@ private:
void movsbq(Register dst, Register src);
// Move signed 32bit immediate to 64bit extending sign
- void movslq(Address dst, int32_t imm64);
+ void movslq(Address dst, int32_t imm64);
void movslq(Register dst, int32_t imm64);
void movslq(Register dst, Address src);
@@ -1857,7 +1857,10 @@ class MacroAssembler: public Assembler {
Register t2, // temp register
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
void lookup_interface_method(Register recv_klass,
@@ -2180,9 +2183,9 @@ public:
void divss(XMMRegister dst, Address src) { Assembler::divss(dst, src); }
void divss(XMMRegister dst, AddressLiteral src) { Assembler::divss(dst, as_Address(src)); }
- void movsd(XMMRegister dst, XMMRegister src) { Assembler::movsd(dst, src); }
- void movsd(Address dst, XMMRegister src) { Assembler::movsd(dst, src); }
- void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); }
+ void movsd(XMMRegister dst, XMMRegister src) { Assembler::movsd(dst, src); }
+ void movsd(Address dst, XMMRegister src) { Assembler::movsd(dst, src); }
+ void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); }
void movsd(XMMRegister dst, AddressLiteral src) { Assembler::movsd(dst, as_Address(src)); }
void mulsd(XMMRegister dst, XMMRegister src) { Assembler::mulsd(dst, src); }
diff --git a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
index 724d8411b..f3ba0a2ce 100644
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
+++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
@@ -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;
switch (condition) {
case lir_cond_equal: acond = Assembler::equal; ncond = Assembler::notEqual; break;
diff --git a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
index d792a0f62..cdea66f38 100644
--- a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
+++ b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
@@ -741,7 +741,7 @@ void LIRGenerator::do_AttemptUpdate(Intrinsic* x) {
// generate conditional move of boolean result
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
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.
// Seems to be precise
post_barrier(addr, val.result());
diff --git a/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp b/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp
index 48d117b3f..d386a99a0 100644
--- a/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp
+++ b/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp
@@ -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.
*
* 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);
} else {
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) {
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");
try_allocate(obj, noreg, object_size * BytesPerWord, t1, t2, slow_case);
diff --git a/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/src/cpu/x86/vm/c1_Runtime1_x86.cpp
index ce51fea3a..0a5680425 100644
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp
@@ -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.
*
* 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_not_null_oop(exception_oop);
-
oop_maps = new OopMapSet();
OopMap* oop_map = generate_oop_map(sasm, 1);
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
// refilling the TLAB or allocating directly from 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);
// 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()));
+
__ tlab_allocate(obj, obj_size, 0, t1, t2, slow_path);
+
__ initialize_object(obj, klass, obj_size, 0, t1, t2);
__ verify_oop(obj);
__ pop(rbx);
@@ -1053,7 +1055,10 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ bind(try_eden);
// 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()));
+
__ 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);
__ verify_oop(obj);
__ 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
// refilling the TLAB or allocating directly from 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);
// 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()));
// since size is postive movl does right thing on 64bit
__ movl(arr_size, length);
@@ -1175,7 +1181,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ bind(try_eden);
// 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()));
// since size is postive movl does right thing on 64bit
__ movl(arr_size, length);
@@ -1188,6 +1194,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ andptr(arr_size, ~MinObjAlignmentInBytesMask);
__ 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);
__ movb(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes() + (Klass::_lh_header_size_shift / BitsPerByte)));
diff --git a/src/cpu/x86/vm/methodHandles_x86.cpp b/src/cpu/x86/vm/methodHandles_x86.cpp
index 5c707fec0..f92beb483 100644
--- a/src/cpu/x86/vm/methodHandles_x86.cpp
+++ b/src/cpu/x86/vm/methodHandles_x86.cpp
@@ -385,9 +385,12 @@ int MethodHandles::adapter_conversion_ops_supported_mask() {
// FIXME: MethodHandlesTest gets a crash if we enable OP_SPREAD_ARGS.
}
+//------------------------------------------------------------------------------
+// MethodHandles::generate_method_handle_stub
+//
// Generate an "entry" field for a method handle.
// 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,
// as set up by generate_method_handle_interpreter_entry():
// - 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)
// - rdx: garbage temp, can blow away
- Register rcx_recv = rcx;
- Register rax_argslot = rax;
- Register rbx_temp = rbx;
- Register rdx_temp = rdx;
+ const Register rcx_recv = rcx;
+ const Register rax_argslot = rax;
+ const Register rbx_temp = rbx;
+ const Register rdx_temp = rdx;
// This guy is set up by prepare_to_jump_from_interpreted (from interpreted 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");
@@ -437,47 +447,41 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
switch ((int) ek) {
case _raise_exception:
{
- // Not a real MH entry, but rather shared code for raising an exception.
- // Extra local arguments are pushed on stack, as required type at TOS+8,
- // failing object (or NULL) at TOS+4, failing bytecode type at TOS.
- // Beyond those local arguments are the PC, of course.
- Register rdx_code = rdx_temp;
- Register rcx_fail = rcx_recv;
- Register rax_want = rax_argslot;
- Register rdi_pc = rdi;
- __ pop(rdx_code); // TOS+0
- __ pop(rcx_fail); // TOS+4
- __ pop(rax_want); // TOS+8
- __ pop(rdi_pc); // caller PC
-
- __ 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);
+ // Not a real MH entry, but rather shared code for raising an
+ // exception. Since we use a C2I adapter to set up the
+ // interpreter state, arguments are expected in compiler
+ // argument registers.
+ methodHandle mh(raise_exception_method());
+ address c2i_entry = methodOopDesc::make_adapters(mh, CHECK);
+
+ const Register rdi_pc = rax;
+ __ pop(rdi_pc); // caller PC
+ __ mov(rsp, saved_last_sp); // cut the stack back to where the caller started
Register rbx_method = rbx_temp;
- Label no_method;
+ Label L_no_method;
// FIXME: fill in _raise_exception_method with a suitable sun.dyn method
__ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method));
__ testptr(rbx_method, rbx_method);
- __ jccb(Assembler::zero, no_method);
- int jobject_oop_offset = 0;
+ __ jccb(Assembler::zero, L_no_method);
+
+ const int jobject_oop_offset = 0;
__ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject
__ testptr(rbx_method, rbx_method);
- __ jccb(Assembler::zero, no_method);
+ __ jccb(Assembler::zero, L_no_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.
// Do something that is at least causes a valid throw from the interpreter.
- __ bind(no_method);
- __ pop(rax_want);
- __ pop(rcx_fail);
- __ push(rax_want);
- __ push(rcx_fail);
+ __ bind(L_no_method);
+ __ push(rarg2_required);
+ __ push(rarg1_actual);
__ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
}
break;
@@ -572,9 +576,11 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ bind(no_such_interface);
// Throw an exception.
// For historical reasons, it will be IncompatibleClassChangeError.
- __ pushptr(Address(rdx_intf, java_mirror_offset)); // required interface
- __ push(rcx_recv); // bad receiver
- __ push((int)Bytecodes::_invokeinterface); // who is complaining?
+ __ mov(rbx_temp, rcx_recv); // rarg2_required might be RCX
+ assert_different_registers(rarg2_required, rbx_temp);
+ __ 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)));
}
break;
@@ -669,10 +675,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ movl(rax_argslot, rcx_amh_vmargslot); // reload argslot field
__ movptr(rdx_temp, vmarg);
- __ load_heap_oop(rbx_klass, rcx_amh_argument); // required class
- __ push(rbx_klass);
- __ push(rdx_temp); // bad object
- __ push((int)Bytecodes::_checkcast); // who is complaining?
+ assert_different_registers(rarg2_required, rdx_temp);
+ __ load_heap_oop(rarg2_required, rcx_amh_argument); // required class
+ __ mov( rarg1_actual, rdx_temp); // bad object
+ __ movl( rarg0_code, (int) Bytecodes::_checkcast); // who is complaining?
__ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
__ bind(done);
@@ -1189,16 +1195,18 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ bind(bad_array_klass);
UNPUSH_RSI_RDI;
- __ pushptr(Address(rdx_array_klass, java_mirror_offset)); // required type
- __ pushptr(vmarg); // bad array
- __ push((int)Bytecodes::_aaload); // who is complaining?
+ assert(!vmarg.uses(rarg2_required), "must be different registers");
+ __ movptr(rarg2_required, Address(rdx_array_klass, java_mirror_offset)); // required type
+ __ movptr(rarg1_actual, vmarg); // bad array
+ __ movl( rarg0_code, (int) Bytecodes::_aaload); // who is complaining?
__ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
__ bind(bad_array_length);
UNPUSH_RSI_RDI;
- __ push(rcx_recv); // AMH requiring a certain length
- __ pushptr(vmarg); // bad array
- __ push((int)Bytecodes::_arraylength); // who is complaining?
+ assert(!vmarg.uses(rarg2_required), "must be different registers");
+ __ mov (rarg2_required, rcx_recv); // AMH requiring a certain length
+ __ movptr(rarg1_actual, vmarg); // bad array
+ __ movl( rarg0_code, (int) Bytecodes::_arraylength); // who is complaining?
__ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
#undef UNPUSH_RSI_RDI
diff --git a/src/cpu/x86/vm/templateTable_x86_32.cpp b/src/cpu/x86/vm/templateTable_x86_32.cpp
index 898069bc9..345b5f62c 100644
--- a/src/cpu/x86/vm/templateTable_x86_32.cpp
+++ b/src/cpu/x86/vm/templateTable_x86_32.cpp
@@ -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.
*
* 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 =
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);
+ }
+
+ if (UseTLAB) {
__ movptr(rax, Address(thread, in_bytes(JavaThread::tlab_top_offset())));
__ lea(rbx, Address(rax, rdx, Address::times_1));
__ 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
__ jcc(Assembler::notEqual, retry);
+
+ __ incr_allocated_bytes(thread, rdx, 0);
}
if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) {
@@ -3256,12 +3260,12 @@ void TemplateTable::_new() {
__ decrement(rdx, sizeof(oopDesc));
__ jcc(Assembler::zero, initialize_header);
- // Initialize topmost object field, divide rdx by 8, check if odd and
- // test if zero.
+ // Initialize topmost object field, divide rdx by 8, check if odd and
+ // test if zero.
__ xorl(rcx, rcx); // use zero reg to clear memory (shorter code)
__ shrl(rdx, LogBytesPerLong); // divide by 2*oopSize and set carry flag if odd
- // rdx must have been multiple of 8
+ // rdx must have been multiple of 8
#ifdef ASSERT
// make sure rdx was multiple of 8
Label L;
diff --git a/src/cpu/x86/vm/templateTable_x86_64.cpp b/src/cpu/x86/vm/templateTable_x86_64.cpp
index a396e88da..cd45253d5 100644
--- a/src/cpu/x86/vm/templateTable_x86_64.cpp
+++ b/src/cpu/x86/vm/templateTable_x86_64.cpp
@@ -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.
*
* 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
__ jcc(Assembler::notEqual, retry);
+
+ __ incr_allocated_bytes(r15_thread, rdx, 0);
}
if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) {
diff --git a/src/os/linux/vm/perfMemory_linux.cpp b/src/os/linux/vm/perfMemory_linux.cpp
index db5340f9d..1cd430cfb 100644
--- a/src/os/linux/vm/perfMemory_linux.cpp
+++ b/src/os/linux/vm/perfMemory_linux.cpp
@@ -635,7 +635,29 @@ static int create_sharedmem_resources(const char* dirname, const char* filename,
return -1;
}
- return fd;
+ // Verify that we have enough disk space for this file.
+ // We'll get random SIGBUS crashes on memory accesses if
+ // we don't.
+
+ for (size_t seekpos = 0; seekpos < size; seekpos += os::vm_page_size()) {
+ int zero_int = 0;
+ result = (int)os::seek_to_file_offset(fd, (jlong)(seekpos));
+ if (result == -1 ) break;
+ RESTARTABLE(::write(fd, &zero_int, 1), result);
+ if (result != 1) {
+ if (errno == ENOSPC) {
+ warning("Insufficient space for shared memory file:\n %s\nTry using the -Djava.io.tmpdir= option to select an alternate temp location.\n", filename);
+ }
+ break;
+ }
+ }
+
+ if (result != -1) {
+ return fd;
+ } else {
+ RESTARTABLE(::close(fd), result);
+ return -1;
+ }
}
// open the shared memory file for the given user and vmid. returns
diff --git a/src/os/posix/launcher/java_md.c b/src/os/posix/launcher/java_md.c
index 78a1ca33a..3ee0f20a7 100644
--- a/src/os/posix/launcher/java_md.c
+++ b/src/os/posix/launcher/java_md.c
@@ -28,7 +28,6 @@
#include <dlfcn.h>
#include <fcntl.h>
#include <inttypes.h>
-#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
diff --git a/src/os/solaris/vm/os_solaris.cpp b/src/os/solaris/vm/os_solaris.cpp
index 014176321..f6f816cf3 100644
--- a/src/os/solaris/vm/os_solaris.cpp
+++ b/src/os/solaris/vm/os_solaris.cpp
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -80,6 +80,7 @@
// put OS-includes here
# include <dlfcn.h>
# include <errno.h>
+# include <exception>
# include <link.h>
# include <poll.h>
# include <pthread.h>
@@ -282,7 +283,7 @@ Thread* ThreadLocalStorage::get_thread_via_cache_slowly(uintptr_t raw_id,
is_error_reported(),
"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;
}
return thread;
@@ -1475,6 +1476,13 @@ sigset_t* os::Solaris::allowdebug_blocked_signals() {
return &allowdebug_blocked_sigs;
}
+
+void _handle_uncaught_cxx_exception() {
+ VMError err("An uncaught C++ exception");
+ err.report_and_die();
+}
+
+
// First crack at OS-specific initialization, from inside the new thread.
void os::initialize_thread() {
int r = thr_main() ;
@@ -1564,6 +1572,7 @@ void os::initialize_thread() {
// use the dynamic check for T2 libthread.
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) {
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
"%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);
oflag = oflag & ~O_DELETE;
- fd = ::open(path, oflag, mode);
+ fd = ::open64(path, oflag, mode);
if (fd == -1) return -1;
//If the open succeeded, the file might still be a directory
diff --git a/src/os/solaris/vm/thread_solaris.inline.hpp b/src/os/solaris/vm/thread_solaris.inline.hpp
index 94c51676d..903be9ddc 100644
--- a/src/os/solaris/vm/thread_solaris.inline.hpp
+++ b/src/os/solaris/vm/thread_solaris.inline.hpp
@@ -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.
*
* 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();
int ix = pd_cache_index(raw);
- Thread *Candidate = ThreadLocalStorage::_get_thread_cache[ix];
- if (Candidate->_self_raw_id == raw) {
+ Thread* candidate = ThreadLocalStorage::_get_thread_cache[ix];
+ if (candidate->self_raw_id() == raw) {
// hit
- return Candidate;
+ return candidate;
} else {
return ThreadLocalStorage::get_thread_via_cache_slowly(raw, ix);
}
diff --git a/src/os/windows/vm/os_windows.cpp b/src/os/windows/vm/os_windows.cpp
index 496a7ec80..0422063c5 100644
--- a/src/os/windows/vm/os_windows.cpp
+++ b/src/os/windows/vm/os_windows.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * CopyrighT (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -2004,6 +2004,16 @@ struct siglabel {
int number;
};
+// All Visual C++ exceptions thrown from code generated by the Microsoft Visual
+// C++ compiler contain this error code. Because this is a compiler-generated
+// error, the code is not listed in the Win32 API header files.
+// The code is actually a cryptic mnemonic device, with the initial "E"
+// standing for "exception" and the final 3 bytes (0x6D7363) representing the
+// ASCII values of "msc".
+
+#define EXCEPTION_UNCAUGHT_CXX_EXCEPTION 0xE06D7363
+
+
struct siglabel exceptlabels[] = {
def_excpt(EXCEPTION_ACCESS_VIOLATION),
def_excpt(EXCEPTION_DATATYPE_MISALIGNMENT),
@@ -2028,6 +2038,7 @@ struct siglabel exceptlabels[] = {
def_excpt(EXCEPTION_INVALID_DISPOSITION),
def_excpt(EXCEPTION_GUARD_PAGE),
def_excpt(EXCEPTION_INVALID_HANDLE),
+ def_excpt(EXCEPTION_UNCAUGHT_CXX_EXCEPTION),
NULL, 0
};
@@ -2261,7 +2272,6 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
}
}
-
if (t != NULL && t->is_Java_thread()) {
JavaThread* thread = (JavaThread*) t;
bool in_java = thread->thread_state() == _thread_in_Java;
@@ -2465,8 +2475,9 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
} // switch
}
#ifndef _WIN64
- if ((thread->thread_state() == _thread_in_Java) ||
- (thread->thread_state() == _thread_in_native) )
+ if (((thread->thread_state() == _thread_in_Java) ||
+ (thread->thread_state() == _thread_in_native)) &&
+ exception_code != EXCEPTION_UNCAUGHT_CXX_EXCEPTION)
{
LONG result=Handle_FLT_Exception(exceptionInfo);
if (result==EXCEPTION_CONTINUE_EXECUTION) return result;
@@ -2490,6 +2501,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
case EXCEPTION_ILLEGAL_INSTRUCTION_2:
case EXCEPTION_INT_OVERFLOW:
case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ case EXCEPTION_UNCAUGHT_CXX_EXCEPTION:
{ report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord,
exceptionInfo->ContextRecord);
}
diff --git a/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp b/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp
index 889f7549f..3b83be3eb 100644
--- a/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp
+++ b/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp
@@ -585,6 +585,13 @@ int JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, int abort_
sigaddset(&newset, sig);
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);
err.report_and_die();
diff --git a/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp b/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp
index 982f987c3..855e9a965 100644
--- a/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp
+++ b/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp
@@ -29,6 +29,7 @@
# include <sys/auxv.h>
# include <sys/auxv_SPARC.h>
# include <sys/systeminfo.h>
+# include <kstat.h>
// We need to keep these here as long as we have to build on Solaris
// versions before 10.
@@ -96,11 +97,23 @@ int VM_Version::platform_features(int features) {
#ifndef AV_SPARC_ASI_BLK_INIT
#define AV_SPARC_ASI_BLK_INIT 0x0080 /* ASI_BLK_INIT_xxx ASI */
#endif
+ if (av & AV_SPARC_ASI_BLK_INIT) features |= blk_init_instructions_m;
+
#ifndef AV_SPARC_FMAF
-#define AV_SPARC_FMAF 0x0100 /* Sparc64 Fused Multiply-Add */
+#define AV_SPARC_FMAF 0x0100 /* Fused Multiply-Add */
#endif
- if (av & AV_SPARC_ASI_BLK_INIT) features |= blk_init_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 {
// getisax(2) failed, use the old legacy code.
#ifndef PRODUCT
@@ -140,5 +153,59 @@ int VM_Version::platform_features(int features) {
// Determine the machine type.
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;
}
diff --git a/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp
index 91c7e75a0..d9bb0eb58 100644
--- a/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp
+++ b/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp
@@ -742,6 +742,13 @@ int JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, int abort_
sigaddset(&newset, sig);
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);
err.report_and_die();
diff --git a/src/share/vm/adlc/dict2.cpp b/src/share/vm/adlc/dict2.cpp
index c9423df2e..22ec13d2c 100644
--- a/src/share/vm/adlc/dict2.cpp
+++ b/src/share/vm/adlc/dict2.cpp
@@ -34,7 +34,7 @@
#define MAXID 20
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 short xsum[MAXID + 1];
+static short xsum[MAXID];
//------------------------------bucket---------------------------------------
class bucket {
@@ -66,7 +66,7 @@ void Dict::init() {
// Precompute table of null character hashes
if( !initflag ) { // Not initializated yet?
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];
}
initflag = 1; // Never again
@@ -291,7 +291,7 @@ int hashstr(const void *t) {
c = (c<<1)+1; // Characters are always odd!
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
}
diff --git a/src/share/vm/c1/c1_Compilation.cpp b/src/share/vm/c1/c1_Compilation.cpp
index 9b55f915e..88dc8c7d0 100644
--- a/src/share/vm/c1/c1_Compilation.cpp
+++ b/src/share/vm/c1/c1_Compilation.cpp
@@ -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:
int locs_buffer_size = 20 * (relocInfo::length_limit + sizeof(relocInfo));
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));
code->initialize_consts_size(Compilation::desired_max_constant_size());
// Call stubs + two deopt handlers (regular and MH) + exception handler
- code->initialize_stubs_size((call_stub_estimate * LIR_Assembler::call_stub_size) +
- LIR_Assembler::exception_handler_size +
- 2 * LIR_Assembler::deopt_handler_size);
+ int stub_size = (call_stub_estimate * LIR_Assembler::call_stub_size) +
+ LIR_Assembler::exception_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() {
// 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());
_masm = new C1_MacroAssembler(code());
diff --git a/src/share/vm/c1/c1_Compilation.hpp b/src/share/vm/c1/c1_Compilation.hpp
index 1ded2b84a..0d0fe1d30 100644
--- a/src/share/vm/c1/c1_Compilation.hpp
+++ b/src/share/vm/c1/c1_Compilation.hpp
@@ -192,7 +192,7 @@ class Compilation: public StackObj {
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
static void print_timers();
diff --git a/src/share/vm/c1/c1_FrameMap.cpp b/src/share/vm/c1/c1_FrameMap.cpp
index 75975bb2b..5b10b966d 100644
--- a/src/share/vm/c1/c1_FrameMap.cpp
+++ b/src/share/vm/c1/c1_FrameMap.cpp
@@ -92,7 +92,7 @@ CallingConvention* FrameMap::java_calling_convention(const BasicTypeArray* signa
if (opr->is_address()) {
LIR_Address* addr = opr->as_address_ptr();
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];
}
@@ -143,7 +143,7 @@ CallingConvention* FrameMap::c_calling_convention(const BasicTypeArray* signatur
args->append(opr);
if (opr->is_address()) {
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];
}
diff --git a/src/share/vm/c1/c1_LIR.hpp b/src/share/vm/c1/c1_LIR.hpp
index 7a3574cfa..50bf4c4e9 100644
--- a/src/share/vm/c1/c1_LIR.hpp
+++ b/src/share/vm/c1/c1_LIR.hpp
@@ -1568,15 +1568,16 @@ class LIR_Op2: public LIR_Op {
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)
, _opr1(opr1)
, _opr2(opr2)
- , _type(T_ILLEGAL)
+ , _type(type)
, _condition(condition)
, _fpu_stack_size(0)
, _tmp(LIR_OprFact::illegalOpr) {
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,
@@ -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_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) {
- append(new LIR_Op2(lir_cmove, condition, src1, src2, 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, type));
}
void cas_long(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value,
diff --git a/src/share/vm/c1/c1_LIRAssembler.cpp b/src/share/vm/c1/c1_LIRAssembler.cpp
index c42281997..1b57ea2f0 100644
--- a/src/share/vm/c1/c1_LIRAssembler.cpp
+++ b/src/share/vm/c1/c1_LIRAssembler.cpp
@@ -685,7 +685,7 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) {
break;
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;
case lir_shl:
diff --git a/src/share/vm/c1/c1_LIRAssembler.hpp b/src/share/vm/c1/c1_LIRAssembler.hpp
index 24f62862c..bb18c253e 100644
--- a/src/share/vm/c1/c1_LIRAssembler.hpp
+++ b/src/share/vm/c1/c1_LIRAssembler.hpp
@@ -217,7 +217,7 @@ class LIR_Assembler: public CompilationResourceObj {
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_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 ic_call( LIR_OpJavaCall* op);
diff --git a/src/share/vm/c1/c1_LIRGenerator.cpp b/src/share/vm/c1/c1_LIRGenerator.cpp
index 56b22f686..8dc579d0d 100644
--- a/src/share/vm/c1/c1_LIRGenerator.cpp
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp
@@ -856,7 +856,7 @@ void LIRGenerator::profile_branch(If* if_instr, If::Condition cond) {
__ cmove(lir_cond(cond),
LIR_OprFact::intptrConst(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.
LIR_Opr data_reg = new_pointer_register();
@@ -2591,7 +2591,7 @@ void LIRGenerator::do_IfOp(IfOp* x) {
LIR_Opr reg = rlock_result(x);
__ 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()));
}
diff --git a/src/share/vm/c1/c1_LinearScan.cpp b/src/share/vm/c1/c1_LinearScan.cpp
index fe118944a..7419f9e8f 100644
--- a/src/share/vm/c1/c1_LinearScan.cpp
+++ b/src/share/vm/c1/c1_LinearScan.cpp
@@ -90,6 +90,7 @@ LinearScan::LinearScan(IR* ir, LIRGenerator* gen, FrameMap* frame_map)
, _intervals(0) // initialized later with correct length
, _new_intervals_from_allocation(new IntervalList())
, _sorted_intervals(NULL)
+ , _needs_full_resort(false)
, _lir_ops(0) // initialized later with correct length
, _block_of_op(0) // initialized later with correct length
, _has_info(0)
@@ -1520,6 +1521,14 @@ void LinearScan::create_unhandled_lists(Interval** list1, Interval** list2, bool
void LinearScan::sort_intervals_before_allocation() {
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;
int unsorted_len = unsorted_list->length();
int sorted_len = 0;
@@ -1559,11 +1568,18 @@ void LinearScan::sort_intervals_before_allocation() {
}
}
_sorted_intervals = sorted_list;
+ assert(is_sorted(_sorted_intervals), "intervals unsorted");
}
void LinearScan::sort_intervals_after_allocation() {
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;
IntervalList* new_list = _new_intervals_from_allocation;
int old_len = old_list->length();
@@ -1571,6 +1587,7 @@ void LinearScan::sort_intervals_after_allocation() {
if (new_len == 0) {
// no intervals have been added during allocation, so sorted list is already up to date
+ assert(is_sorted(_sorted_intervals), "intervals unsorted");
return;
}
@@ -1593,6 +1610,7 @@ void LinearScan::sort_intervals_after_allocation() {
}
_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->assign_reg(reg, regHi);
append_interval(interval);
+ } else {
+ _needs_full_resort = true;
}
assert(interval->from() == from_op_id, "must be true now");
@@ -4492,7 +4512,8 @@ void Interval::print(outputStream* out) const {
}
} else {
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);
}
}
diff --git a/src/share/vm/c1/c1_LinearScan.hpp b/src/share/vm/c1/c1_LinearScan.hpp
index 97f4043c1..018570f9c 100644
--- a/src/share/vm/c1/c1_LinearScan.hpp
+++ b/src/share/vm/c1/c1_LinearScan.hpp
@@ -148,6 +148,7 @@ class LinearScan : public CompilationResourceObj {
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
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
BlockBeginArray _block_of_op; // mapping from LIR_Op id to the BlockBegin containing this instruction
diff --git a/src/share/vm/classfile/classFileParser.cpp b/src/share/vm/classfile/classFileParser.cpp
index 3712c8ae4..3779fc7d6 100644
--- a/src/share/vm/classfile/classFileParser.cpp
+++ b/src/share/vm/classfile/classFileParser.cpp
@@ -2386,19 +2386,21 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(constantPoolHa
valid_cp_range(bootstrap_method_index, cp_size) &&
cp->tag_at(bootstrap_method_index).is_method_handle(),
"bootstrap_method_index %u has bad constant type in class file %s",
+ bootstrap_method_index,
CHECK);
operands->short_at_put(operand_fill_index++, bootstrap_method_index);
operands->short_at_put(operand_fill_index++, argument_count);
cfs->guarantee_more(sizeof(u2) * argument_count, CHECK); // argv[argc]
for (int j = 0; j < argument_count; j++) {
- u2 arg_index = cfs->get_u2_fast();
+ u2 argument_index = cfs->get_u2_fast();
check_property(
- valid_cp_range(arg_index, cp_size) &&
- cp->tag_at(arg_index).is_loadable_constant(),
+ valid_cp_range(argument_index, cp_size) &&
+ cp->tag_at(argument_index).is_loadable_constant(),
"argument_index %u has bad constant type in class file %s",
+ argument_index,
CHECK);
- operands->short_at_put(operand_fill_index++, arg_index);
+ operands->short_at_put(operand_fill_index++, argument_index);
}
}
diff --git a/src/share/vm/code/codeCache.cpp b/src/share/vm/code/codeCache.cpp
index f7e09b258..db35aea6e 100644
--- a/src/share/vm/code/codeCache.cpp
+++ b/src/share/vm/code/codeCache.cpp
@@ -939,7 +939,9 @@ void CodeCache::print_bounds(outputStream* st) {
_heap->high(),
_heap->high_boundary());
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_adapters(), CodeCache::unallocated_capacity());
+ CodeCache::nof_adapters(), CodeCache::unallocated_capacity(),
+ CodeCache::largest_free_block());
}
diff --git a/src/share/vm/code/codeCache.hpp b/src/share/vm/code/codeCache.hpp
index acb288efe..df8de7f3f 100644
--- a/src/share/vm/code/codeCache.hpp
+++ b/src/share/vm/code/codeCache.hpp
@@ -158,6 +158,7 @@ class CodeCache : AllStatic {
static size_t capacity() { return _heap->capacity(); }
static size_t max_capacity() { return _heap->max_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_cache_clean() { return _needs_cache_clean; }
diff --git a/src/share/vm/code/nmethod.cpp b/src/share/vm/code/nmethod.cpp
index e6cc51aab..98bad3ca0 100644
--- a/src/share/vm/code/nmethod.cpp
+++ b/src/share/vm/code/nmethod.cpp
@@ -811,9 +811,11 @@ nmethod::nmethod(
_stub_offset = content_offset() + code_buffer->total_offset_of(code_buffer->stubs());
// 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);
_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);
} else {
_deoptimize_mh_offset = -1;
@@ -1909,6 +1911,7 @@ void nmethod::copy_scopes_pcs(PcDesc* pcs, int count) {
break;
}
}
+ assert(has_method_handle_invokes() == (_deoptimize_mh_offset != -1), "must have deopt mh handler");
int size = count * sizeof(PcDesc);
assert(scopes_pcs_size() >= size, "oob");
diff --git a/src/share/vm/compiler/abstractCompiler.cpp b/src/share/vm/compiler/abstractCompiler.cpp
index 5594d1afa..942c168e5 100644
--- a/src/share/vm/compiler/abstractCompiler.cpp
+++ b/src/share/vm/compiler/abstractCompiler.cpp
@@ -33,6 +33,7 @@ void AbstractCompiler::initialize_runtimes(initializer f, volatile int* state) {
bool do_initialization = false;
{
ThreadInVMfromNative tv(thread);
+ ResetNoHandleMark rnhm;
MutexLocker only_one(CompileThread_lock, thread);
if ( *state == uninitialized) {
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
ThreadInVMfromNative tv(thread);
+ ResetNoHandleMark rnhm;
MutexLocker only_one(CompileThread_lock, thread);
assert(*state == initializing, "wrong state");
*state = initialized;
diff --git a/src/share/vm/compiler/compilerOracle.cpp b/src/share/vm/compiler/compilerOracle.cpp
index 3bc679fdd..314648961 100644
--- a/src/share/vm/compiler/compilerOracle.cpp
+++ b/src/share/vm/compiler/compilerOracle.cpp
@@ -332,7 +332,7 @@ static OracleCommand parse_command_name(const char * line, int* bytes_read) {
"command_names size mismatch");
*bytes_read = 0;
- char command[32];
+ char command[33];
int result = sscanf(line, "%32[a-z]%n", command, bytes_read);
for (uint i = 0; i < ARRAY_SIZE(command_names); i++) {
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);
line += bytes_read;
+ if (command == UnknownCommand) {
+ tty->print_cr("CompilerOracle: unrecognized line");
+ tty->print_cr(" \"%s\"", original_line);
+ return;
+ }
+
if (command == QuietCommand) {
_quiet = true;
return;
@@ -498,7 +504,7 @@ void CompilerOracle::parse_from_line(char* line) {
line += bytes_read;
// there might be a signature following the method.
// 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] = '(';
line += bytes_read;
signature = oopFactory::new_symbol_handle(sig, CHECK);
diff --git a/src/share/vm/gc_interface/collectedHeap.inline.hpp b/src/share/vm/gc_interface/collectedHeap.inline.hpp
index c9f5f0111..73f54d981 100644
--- a/src/share/vm/gc_interface/collectedHeap.inline.hpp
+++ b/src/share/vm/gc_interface/collectedHeap.inline.hpp
@@ -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.
*
* 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));
assert(!HAS_PENDING_EXCEPTION,
"Unexpected exception, will result in uninitialized storage");
+ THREAD->incr_allocated_bytes(size * HeapWordSize);
return result;
}
diff --git a/src/share/vm/memory/heap.cpp b/src/share/vm/memory/heap.cpp
index b6d6484f0..94676f78d 100644
--- a/src/share/vm/memory/heap.cpp
+++ b/src/share/vm/memory/heap.cpp
@@ -315,6 +315,15 @@ size_t CodeHeap::allocated_capacity() const {
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
FreeBlock *CodeHeap::following_block(FreeBlock *b) {
diff --git a/src/share/vm/memory/heap.hpp b/src/share/vm/memory/heap.hpp
index 95199aac9..4f592a20c 100644
--- a/src/share/vm/memory/heap.hpp
+++ b/src/share/vm/memory/heap.hpp
@@ -161,6 +161,7 @@ class CodeHeap : public CHeapObj {
size_t max_capacity() const;
size_t allocated_capacity() const;
size_t unallocated_capacity() const { return max_capacity() - allocated_capacity(); }
+ size_t largest_free_block() const;
// Debugging
void verify();
diff --git a/src/share/vm/memory/threadLocalAllocBuffer.cpp b/src/share/vm/memory/threadLocalAllocBuffer.cpp
index f3eec576c..74f2c44d4 100644
--- a/src/share/vm/memory/threadLocalAllocBuffer.cpp
+++ b/src/share/vm/memory/threadLocalAllocBuffer.cpp
@@ -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.
*
* 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) {
if (end() != NULL) {
invariants();
+
+ if (retire) {
+ myThread()->incr_allocated_bytes(used_bytes());
+ }
+
CollectedHeap::fill_with_object(top(), hard_end(), retire);
if (retire || ZeroTLAB) { // "Reset" the TLAB
diff --git a/src/share/vm/memory/threadLocalAllocBuffer.hpp b/src/share/vm/memory/threadLocalAllocBuffer.hpp
index 2d091f693..4b88835db 100644
--- a/src/share/vm/memory/threadLocalAllocBuffer.hpp
+++ b/src/share/vm/memory/threadLocalAllocBuffer.hpp
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -112,6 +112,8 @@ public:
HeapWord* top() const { return _top; }
HeapWord* pf_top() const { return _pf_top; }
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()); }
// Don't discard tlab if remaining space is larger than this.
size_t refill_waste_limit() const { return _refill_waste_limit; }
diff --git a/src/share/vm/memory/universe.cpp b/src/share/vm/memory/universe.cpp
index 9909e8035..9d5af98fd 100644
--- a/src/share/vm/memory/universe.cpp
+++ b/src/share/vm/memory/universe.cpp
@@ -934,7 +934,8 @@ jint Universe::initialize_heap() {
// See needs_explicit_null_check.
// Only set the heap base for compressed oops because it indicates
// compressed oops for pstack code.
- if (PrintCompressedOopsMode) {
+ bool verbose = PrintCompressedOopsMode || (PrintMiscellaneous && Verbose);
+ if (verbose) {
tty->cr();
tty->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB",
Universe::heap()->base(), Universe::heap()->reserved_region().byte_size()/M);
@@ -943,12 +944,12 @@ jint Universe::initialize_heap() {
// Can't reserve heap below 32Gb.
Universe::set_narrow_oop_base(Universe::heap()->base() - os::vm_page_size());
Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
- if (PrintCompressedOopsMode) {
+ if (verbose) {
tty->print(", Compressed Oops with base: "PTR_FORMAT, Universe::narrow_oop_base());
}
} else {
Universe::set_narrow_oop_base(0);
- if (PrintCompressedOopsMode) {
+ if (verbose) {
tty->print(", zero based Compressed Oops");
}
#ifdef _WIN64
@@ -963,12 +964,12 @@ jint Universe::initialize_heap() {
Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
} else {
Universe::set_narrow_oop_shift(0);
- if (PrintCompressedOopsMode) {
+ if (verbose) {
tty->print(", 32-bits Oops");
}
}
}
- if (PrintCompressedOopsMode) {
+ if (verbose) {
tty->cr();
tty->cr();
}
diff --git a/src/share/vm/opto/compile.cpp b/src/share/vm/opto/compile.cpp
index 0ca15e168..cad5224e6 100644
--- a/src/share/vm/opto/compile.cpp
+++ b/src/share/vm/opto/compile.cpp
@@ -444,22 +444,32 @@ 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) {
- if (scratch_buffer_blob() != NULL) return;
-
- // Construct a temporary CodeBuffer to have it construct a BufferBlob
- // Cache this BufferBlob for this compile.
- ResourceMark rm;
- _scratch_const_size = const_size;
- int size = (MAX_inst_size + MAX_stubs_size + _scratch_const_size);
- BufferBlob* blob = BufferBlob::create("Compile::scratch_buffer", size);
- // Record the buffer blob for next time.
- set_scratch_buffer_blob(blob);
- // Have we run out of code space?
- if (scratch_buffer_blob() == NULL) {
- // Let CompilerBroker disable further compilations.
- record_failure("Not enough space for scratch buffer in CodeCache");
- 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);
+ }
+
+ ResourceMark rm;
+ _scratch_const_size = const_size;
+ int size = (MAX_inst_size + MAX_stubs_size + _scratch_const_size);
+ blob = BufferBlob::create("Compile::scratch_buffer", size);
+ // Record the buffer blob for next time.
+ set_scratch_buffer_blob(blob);
+ // Have we run out of code space?
+ if (scratch_buffer_blob() == NULL) {
+ // Let CompilerBroker disable further compilations.
+ record_failure("Not enough space for scratch buffer in CodeCache");
+ return;
+ }
}
// Initialize the relocation buffers
@@ -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-------------------------------------
// Helper function that computes size by emitting code
uint Compile::scratch_emit_size(const Node* n) {
diff --git a/src/share/vm/opto/escape.cpp b/src/share/vm/opto/escape.cpp
index c53c4ae6e..62db164b5 100644
--- a/src/share/vm/opto/escape.cpp
+++ b/src/share/vm/opto/escape.cpp
@@ -1609,10 +1609,11 @@ bool ConnectionGraph::compute_escape() {
//
// Normally only 1-3 passes needed to build
// 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.
-#define CG_BUILD_ITER_LIMIT 10
+#define CG_BUILD_ITER_LIMIT 20
uint length = worklist.length();
int iterations = 0;
diff --git a/src/share/vm/opto/macro.cpp b/src/share/vm/opto/macro.cpp
index 3c95bf0ea..465c8babd 100644
--- a/src/share/vm/opto/macro.cpp
+++ b/src/share/vm/opto/macro.cpp
@@ -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.
*
* 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
// 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
- // 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
// this will require extensive changes to the loop optimization in order to
// prevent a degradation of the optimization.
@@ -1167,24 +1167,24 @@ void PhaseMacroExpand::expand_allocate_common(
// allocate the Region and Phi nodes for the result
result_region = new (C, 3) RegionNode(3);
- 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_i_o = new (C, 3) PhiNode( result_region, Type::ABIO ); // I/O is used for Prefetch
+ 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_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.
enum { fall_in_path = 1, contended_loopback_path = 2 };
Node *contended_region;
Node *contended_phi_rawmem;
- if( UseTLAB ) {
+ if (UseTLAB) {
contended_region = toobig_false;
contended_phi_rawmem = mem;
} else {
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
// loop-back merge point.
- contended_region ->init_req( fall_in_path, toobig_false );
- contended_phi_rawmem->init_req( fall_in_path, mem );
+ contended_region ->init_req(fall_in_path, toobig_false);
+ contended_phi_rawmem->init_req(fall_in_path, mem);
transform_later(contended_region);
transform_later(contended_phi_rawmem);
}
@@ -1192,78 +1192,101 @@ void PhaseMacroExpand::expand_allocate_common(
// Load(-locked) the heap top.
// See note above concerning the control input when using a TLAB
Node *old_eden_top = UseTLAB
- ? 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) LoadPNode (ctrl, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM)
+ : new (C, 3) LoadPLockedNode(contended_region, contended_phi_rawmem, eden_top_adr);
transform_later(old_eden_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);
// 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);
- 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);
- 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);
// 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);
- if( initial_slow_test ) {
- slow_region ->init_req( need_gc_path, needgc_true );
+ if (initial_slow_test) {
+ slow_region->init_req(need_gc_path, needgc_true);
// This completes all paths into the slow merge point
transform_later(slow_region);
} else { // No initial slow path needed!
// Just fall from the need-GC path straight into the VM call.
- slow_region = needgc_true;
+ slow_region = needgc_true;
}
// 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);
// 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.
- 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,
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.
// StorePConditional produces flags for a test PLUS a modified raw
// memory state.
- Node *store_eden_top;
- Node *fast_oop_ctrl;
- if( UseTLAB ) {
- store_eden_top = new (C, 4) StorePNode( needgc_false, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, new_eden_top );
+ if (UseTLAB) {
+ Node* store_eden_top =
+ new (C, 4) StorePNode(needgc_false, contended_phi_rawmem, eden_top_adr,
+ TypeRawPtr::BOTTOM, new_eden_top);
transform_later(store_eden_top);
fast_oop_ctrl = needgc_false; // No contention, so this is the fast path
+ fast_oop_rawmem = store_eden_top;
} 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);
- 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);
store_eden_top = new (C, 1) SCMemProjNode(store_eden_top);
transform_later(store_eden_top);
// 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);
- Node *contention_true = new (C, 1) IfTrueNode( contention_iff );
+ Node *contention_true = new (C, 1) IfTrueNode(contention_iff);
transform_later(contention_true);
// If contention, loopback and try again.
- contended_region->init_req( contended_loopback_path, contention_true );
- contended_phi_rawmem->init_req( contended_loopback_path, store_eden_top );
+ contended_region->init_req(contended_loopback_path, contention_true);
+ contended_phi_rawmem->init_req(contended_loopback_path, store_eden_top);
// 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);
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_ctrl, fast_oop_rawmem, fast_oop,
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+1, fast_oop);
- call->init_req( TypeFunc::Control, fast_oop_ctrl );
- call->init_req( TypeFunc::I_O , top() ) ; // does no i/o
- call->init_req( TypeFunc::Memory , fast_oop_rawmem );
- call->init_req( TypeFunc::ReturnAdr, alloc->in(TypeFunc::ReturnAdr) );
- call->init_req( TypeFunc::FramePtr, alloc->in(TypeFunc::FramePtr) );
+ call->init_req(TypeFunc::Control, fast_oop_ctrl);
+ call->init_req(TypeFunc::I_O , top()); // does no i/o
+ call->init_req(TypeFunc::Memory , fast_oop_rawmem);
+ call->init_req(TypeFunc::ReturnAdr, alloc->in(TypeFunc::ReturnAdr));
+ call->init_req(TypeFunc::FramePtr, alloc->in(TypeFunc::FramePtr));
transform_later(call);
fast_oop_ctrl = new (C, 1) ProjNode(call,TypeFunc::Control);
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
- result_region ->init_req( fast_result_path, fast_oop_ctrl );
- result_phi_rawoop->init_req( fast_result_path, fast_oop );
- result_phi_i_o ->init_req( fast_result_path, i_o );
- result_phi_rawmem->init_req( fast_result_path, fast_oop_rawmem );
+ result_region ->init_req(fast_result_path, fast_oop_ctrl);
+ result_phi_rawoop->init_req(fast_result_path, fast_oop);
+ result_phi_i_o ->init_req(fast_result_path, i_o);
+ result_phi_rawmem->init_req(fast_result_path, fast_oop_rawmem);
} else {
slow_region = ctrl;
}
diff --git a/src/share/vm/opto/output.cpp b/src/share/vm/opto/output.cpp
index e2ddd974f..de2942316 100644
--- a/src/share/vm/opto/output.cpp
+++ b/src/share/vm/opto/output.cpp
@@ -1746,9 +1746,6 @@ void Compile::ScheduleAndBundle() {
// Walk backwards over each basic block, computing the needed alignment
// Walk over all the basic blocks
scheduling.DoScheduling();
-
- // Clear the BufferBlob used for scheduling.
- clear_scratch_buffer_blob();
}
//------------------------------ComputeLocalLatenciesForward-------------------
diff --git a/src/share/vm/opto/stringopts.cpp b/src/share/vm/opto/stringopts.cpp
index 93516d5d0..658fc05b1 100644
--- a/src/share/vm/opto/stringopts.cpp
+++ b/src/share/vm/opto/stringopts.cpp
@@ -59,7 +59,8 @@ class StringConcat : public ResourceObj {
enum {
StringMode,
IntMode,
- CharMode
+ CharMode,
+ StringNullCheckMode
};
StringConcat(PhaseStringOpts* stringopts, CallStaticJavaNode* end):
@@ -114,6 +115,9 @@ class StringConcat : public ResourceObj {
void push_string(Node* value) {
push(value, StringMode);
}
+ void push_string_null_check(Node* value) {
+ push(value, StringNullCheckMode);
+ }
void push_int(Node* value) {
push(value, IntMode);
}
@@ -416,7 +420,19 @@ StringConcat* PhaseStringOpts::build_candidate(CallStaticJavaNode* call) {
if (sig == ciSymbol::string_void_signature()) {
// StringBuilder(String) so pick this up as the first argument
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
// array so just treat it like the void version.
@@ -436,7 +452,7 @@ StringConcat* PhaseStringOpts::build_candidate(CallStaticJavaNode* call) {
#ifndef PRODUCT
if (PrintOptimizeStringConcat) {
tty->print("giving up because couldn't find constructor ");
- alloc->jvms()->dump_spec(tty);
+ alloc->jvms()->dump_spec(tty); tty->cr();
}
#endif
break;
@@ -1269,6 +1285,25 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
string_sizes->init_req(argi, string_size);
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: {
const Type* type = kit.gvn().type(arg);
if (type == TypePtr::NULL_PTR) {
@@ -1328,6 +1363,7 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
// Hook
PreserveJVMState pjvms(&kit);
kit.set_control(overflow);
+ C->record_for_igvn(overflow);
kit.uncommon_trap(Deoptimization::Reason_intrinsic,
Deoptimization::Action_make_not_entrant);
}
@@ -1363,6 +1399,7 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
start = end;
break;
}
+ case StringConcat::StringNullCheckMode:
case StringConcat::StringMode: {
start = copy_string(kit, arg, char_array, start);
break;
diff --git a/src/share/vm/prims/jvmti.xml b/src/share/vm/prims/jvmti.xml
index 672a59380..9e24fb64b 100644
--- a/src/share/vm/prims/jvmti.xml
+++ b/src/share/vm/prims/jvmti.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<?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.
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.
</description>
</param>
- <param id="value">
+ <param id="value_ptr">
<inbuf>
<char/>
<nullok>
diff --git a/src/share/vm/prims/jvmtiEnv.cpp b/src/share/vm/prims/jvmtiEnv.cpp
index 26f2511f9..5df7396bd 100644
--- a/src/share/vm/prims/jvmtiEnv.cpp
+++ b/src/share/vm/prims/jvmtiEnv.cpp
@@ -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.
*
* 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
// value - pre-checked for NULL
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();
// rm object is created to clean up the javaVFrame created in
// 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) {
return err;
} else {
- *value = op.value().l;
+ *value_ptr = op.value().l;
return JVMTI_ERROR_NONE;
}
} /* end GetLocalInstance */
@@ -3440,12 +3440,12 @@ JvmtiEnv::GetSystemProperty(const char* property, char** value_ptr) {
// property - pre-checked for NULL
// value - NULL is a valid value, must be checked
jvmtiError
-JvmtiEnv::SetSystemProperty(const char* property, const char* value) {
+JvmtiEnv::SetSystemProperty(const char* property, const char* value_ptr) {
jvmtiError err =JVMTI_ERROR_NOT_AVAILABLE;
for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
if (strcmp(property, p->key()) == 0) {
- if (p->set_value((char *)value)) {
+ if (p->set_value((char *)value_ptr)) {
err = JVMTI_ERROR_NONE;
}
}
diff --git a/src/share/vm/prims/methodHandles.cpp b/src/share/vm/prims/methodHandles.cpp
index 6c3318656..1b2c3c60d 100644
--- a/src/share/vm/prims/methodHandles.cpp
+++ b/src/share/vm/prims/methodHandles.cpp
@@ -111,7 +111,7 @@ bool MethodHandles::spot_check_entry_names() {
//------------------------------------------------------------------------------
// MethodHandles::generate_adapters
//
-void MethodHandles::generate_adapters() {
+void MethodHandles::generate_adapters(TRAPS) {
if (!EnableMethodHandles || SystemDictionary::MethodHandle_klass() == NULL) return;
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");
CodeBuffer code(_adapter_code);
MethodHandlesAdapterGenerator g(&code);
- g.generate();
+ g.generate(CHECK);
}
//------------------------------------------------------------------------------
// MethodHandlesAdapterGenerator::generate
//
-void MethodHandlesAdapterGenerator::generate() {
+void MethodHandlesAdapterGenerator::generate(TRAPS) {
// Generate generic method handle adapters.
for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST;
ek < MethodHandles::_EK_LIMIT;
ek = MethodHandles::EntryKind(1 + (int)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);
}
}
+
+ // Generate method handles adapters if enabled.
+ if (MethodHandles::enabled()) {
+ MethodHandles::generate_adapters(CHECK);
+ }
}
JVM_END
diff --git a/src/share/vm/prims/methodHandles.hpp b/src/share/vm/prims/methodHandles.hpp
index 351dc33f6..f66f0e026 100644
--- a/src/share/vm/prims/methodHandles.hpp
+++ b/src/share/vm/prims/methodHandles.hpp
@@ -294,11 +294,11 @@ class MethodHandles: AllStatic {
enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
// Generate MethodHandles adapters.
- static void generate_adapters();
+ static void generate_adapters(TRAPS);
// Called from InterpreterGenerator and MethodHandlesAdapterGenerator.
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
static int argument_slot(oop method_type, int arg);
@@ -530,7 +530,7 @@ class MethodHandlesAdapterGenerator : public StubCodeGenerator {
public:
MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code) {}
- void generate();
+ void generate(TRAPS);
};
#endif // SHARE_VM_PRIMS_METHODHANDLES_HPP
diff --git a/src/share/vm/runtime/arguments.cpp b/src/share/vm/runtime/arguments.cpp
index 0a3f9207f..09b41b5b0 100644
--- a/src/share/vm/runtime/arguments.cpp
+++ b/src/share/vm/runtime/arguments.cpp
@@ -2297,14 +2297,15 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
} else if (match_option(option, "-Xoss", &tail)) {
// HotSpot does not have separate native and Java stacks, ignore silently for compatibility
// -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;
ArgsRange errcode = parse_memory_size(tail, &long_ReservedCodeCacheSize,
(size_t)InitialCodeCacheSize);
if (errcode != arg_in_range) {
jio_fprintf(defaultStream::error_stream(),
- "Invalid maximum code cache size: %s\n",
- option->optionString);
+ "Invalid maximum code cache size: %s. Should be greater than InitialCodeCacheSize=%dK\n",
+ option->optionString, InitialCodeCacheSize/K);
describe_range_error(errcode);
return JNI_EINVAL;
}
diff --git a/src/share/vm/runtime/init.cpp b/src/share/vm/runtime/init.cpp
index 7c1904693..1f09c3683 100644
--- a/src/share/vm/runtime/init.cpp
+++ b/src/share/vm/runtime/init.cpp
@@ -125,9 +125,6 @@ jint init_globals() {
javaClasses_init(); // must happen after vtable initialization
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
// here because the main thread isn't yet a JavaThread, so
// its TLAB may not be made parseable from the usual interfaces.
diff --git a/src/share/vm/runtime/java.cpp b/src/share/vm/runtime/java.cpp
index 6abdd64d5..f6b20a7b7 100644
--- a/src/share/vm/runtime/java.cpp
+++ b/src/share/vm/runtime/java.cpp
@@ -515,8 +515,8 @@ void before_exit(JavaThread * thread) {
}
void vm_exit(int code) {
- Thread* thread = ThreadLocalStorage::thread_index() == -1 ? NULL
- : ThreadLocalStorage::get_thread_slow();
+ Thread* thread = ThreadLocalStorage::is_initialized() ?
+ ThreadLocalStorage::get_thread_slow() : NULL;
if (thread == NULL) {
// we have serious problems -- just exit
vm_direct_exit(code);
@@ -553,8 +553,9 @@ void vm_perform_shutdown_actions() {
// Calling 'exit_globals()' will disable thread-local-storage and cause all
// kinds of assertions to trigger in debug mode.
if (is_init_completed()) {
- Thread* thread = Thread::current();
- if (thread->is_Java_thread()) {
+ Thread* thread = ThreadLocalStorage::is_initialized() ?
+ 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
// handlers call back to the VM)
JavaThread* jt = (JavaThread*)thread;
diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp
index c22b2609a..fbb6ca93b 100644
--- a/src/share/vm/runtime/thread.cpp
+++ b/src/share/vm/runtime/thread.cpp
@@ -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.
*
* 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() {
- // stack
- _stack_base = NULL;
- _stack_size = 0;
- _self_raw_id = 0;
- _lgrp_id = -1;
- _osthread = NULL;
+ // stack and get_thread
+ set_stack_base(NULL);
+ set_stack_size(0);
+ set_self_raw_id(0);
+ set_lgrp_id(-1);
// allocated data structures
+ set_osthread(NULL);
set_resource_area(new ResourceArea());
set_handle_area(new HandleArea(NULL));
set_active_handles(NULL);
set_free_handle_block(NULL);
set_last_handle_mark(NULL);
- set_osthread(NULL);
// This initial value ==> never claimed.
_oops_do_parity = 0;
@@ -205,6 +204,7 @@ Thread::Thread() {
NOT_PRODUCT(_skip_gcalot = false;)
CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;)
_jvmti_env_iteration_count = 0;
+ set_allocated_bytes(0);
_vm_operation_started_count = 0;
_vm_operation_completed_count = 0;
_current_pending_monitor = NULL;
@@ -3231,7 +3231,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
warning("java.lang.ArithmeticException has not been initialized");
warning("java.lang.StackOverflowError has not been initialized");
}
- }
+ }
// See : bugid 4211085.
// Background : the static initializer of java.lang.Compiler tries to read
diff --git a/src/share/vm/runtime/thread.hpp b/src/share/vm/runtime/thread.hpp
index b4896512a..a0ca83c56 100644
--- a/src/share/vm/runtime/thread.hpp
+++ b/src/share/vm/runtime/thread.hpp
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -60,7 +60,7 @@ class JvmtiThreadState;
class JvmtiGetLoadedClassesClosure;
class ThreadStatistics;
class ConcurrentLocksDump;
-class ParkEvent ;
+class ParkEvent;
class Parker;
class ciEnv;
@@ -170,7 +170,7 @@ class Thread: public ThreadShadow {
//
// suspend/resume lock: used for self-suspend
- Monitor* _SR_lock;
+ Monitor* _SR_lock;
protected:
enum SuspendFlags {
@@ -194,7 +194,7 @@ class Thread: public ThreadShadow {
public:
void enter_signal_handler() { _num_nested_signal++; }
void leave_signal_handler() { _num_nested_signal--; }
- bool is_inside_signal_handler() const { return _num_nested_signal > 0; }
+ bool is_inside_signal_handler() const { return _num_nested_signal > 0; }
private:
// Debug tracing
@@ -215,7 +215,7 @@ class Thread: public ThreadShadow {
public:
void set_last_handle_mark(HandleMark* mark) { _last_handle_mark = mark; }
- HandleMark* last_handle_mark() const { return _last_handle_mark; }
+ HandleMark* last_handle_mark() const { return _last_handle_mark; }
private:
// debug support for checking if code does allow safepoints or not
@@ -227,11 +227,11 @@ class Thread: public ThreadShadow {
//
// The two classes No_Safepoint_Verifier and No_Allocation_Verifier are used to set these counters.
//
- NOT_PRODUCT(int _allow_safepoint_count;) // If 0, thread allow a safepoint to happen
- debug_only (int _allow_allocation_count;) // If 0, the thread is allowed to allocate oops.
+ NOT_PRODUCT(int _allow_safepoint_count;) // If 0, thread allow a safepoint to happen
+ debug_only (int _allow_allocation_count;) // If 0, the thread is allowed to allocate oops.
// Used by SkipGCALot class.
- NOT_PRODUCT(bool _skip_gcalot;) // Should we elide gc-a-lot?
+ NOT_PRODUCT(bool _skip_gcalot;) // Should we elide gc-a-lot?
// Record when GC is locked out via the GC_locker mechanism
CHECK_UNHANDLED_OOPS_ONLY(int _gc_locked_out_count;)
@@ -242,24 +242,26 @@ class Thread: public ThreadShadow {
friend class ThreadLocalStorage;
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_completed_count; // VM_Operation support
+ int _vm_operation_started_count; // VM_Operation support
+ int _vm_operation_completed_count; // VM_Operation support
- ObjectMonitor* _current_pending_monitor; // ObjectMonitor this thread
- // is waiting to lock
- bool _current_pending_monitor_is_from_java; // locking is from Java code
+ ObjectMonitor* _current_pending_monitor; // ObjectMonitor this thread
+ // is waiting to lock
+ bool _current_pending_monitor_is_from_java; // locking is from Java code
// ObjectMonitor on which this thread called Object.wait()
ObjectMonitor* _current_waiting_monitor;
// Private thread-local objectmonitor list - a simple cache organized as a SLL.
public:
- ObjectMonitor * omFreeList ;
- int omFreeCount ; // length of omFreeList
- int omFreeProvision ; // reload chunk size
- ObjectMonitor * omInUseList; // SLL to track monitors in circulation
+ ObjectMonitor* omFreeList;
+ int omFreeCount; // length of omFreeList
+ int omFreeProvision; // reload chunk size
+ ObjectMonitor* omInUseList; // SLL to track monitors in circulation
int omInUseCount; // length of omInUseList
public:
@@ -280,7 +282,6 @@ class Thread: public ThreadShadow {
// Testers
virtual bool is_VM_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_hidden_from_external_view() const { return false; }
virtual bool is_jvmti_agent_thread() const { return false; }
@@ -344,15 +345,15 @@ class Thread: public ThreadShadow {
// Support for Unhandled Oop detection
#ifdef CHECK_UNHANDLED_OOPS
private:
- UnhandledOops *_unhandled_oops;
+ UnhandledOops* _unhandled_oops;
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.
- void allow_unhandled_oop(oop *op) {
+ void allow_unhandled_oop(oop *op) {
if (CheckUnhandledOops) unhandled_oops()->allow_unhandled_oop(op);
}
// Clear oops at safepoint so crashes point to unhandled oop violator
- void clear_unhandled_oops() {
+ void clear_unhandled_oops() {
if (CheckUnhandledOops) unhandled_oops()->clear_unhandled_oops();
}
bool is_gc_locked_out() { return _gc_locked_out_count > 0; }
@@ -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
int vm_operation_ticket() { return ++_vm_operation_started_count; }
int vm_operation_completed_count() { return _vm_operation_completed_count; }
@@ -489,8 +506,11 @@ public:
return (_stack_base >= adr && adr >= (_stack_base - _stack_size));
}
- int lgrp_id() const { return _lgrp_id; }
- void set_lgrp_id(int value) { _lgrp_id = value; }
+ 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; }
+ void set_lgrp_id(int value) { _lgrp_id = value; }
// Printing
void print_on(outputStream* st) const;
@@ -502,7 +522,7 @@ public:
#ifdef ASSERT
private:
// 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,
// thus the friendship
friend class Mutex;
@@ -511,7 +531,7 @@ public:
public:
void print_owned_locks_on(outputStream* st) const;
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_but_compiled_lock() const;
@@ -538,7 +558,7 @@ public:
static ByteSize stack_size_offset() { return byte_offset_of(Thread, _stack_size ); }
#define TLAB_FIELD_OFFSET(name) \
- static ByteSize tlab_##name##_offset() { return byte_offset_of(Thread, _tlab) + ThreadLocalAllocBuffer::name##_offset(); }
+ static ByteSize tlab_##name##_offset() { return byte_offset_of(Thread, _tlab) + ThreadLocalAllocBuffer::name##_offset(); }
TLAB_FIELD_OFFSET(start)
TLAB_FIELD_OFFSET(end)
@@ -552,6 +572,8 @@ public:
#undef TLAB_FIELD_OFFSET
+ static ByteSize allocated_bytes_offset() { return byte_offset_of(Thread, _allocated_bytes ); }
+
public:
volatile intptr_t _Stalled ;
volatile int _TypeTag ;
diff --git a/src/share/vm/services/jmm.h b/src/share/vm/services/jmm.h
index 8824574c8..df08124e5 100644
--- a/src/share/vm/services/jmm.h
+++ b/src/share/vm/services/jmm.h
@@ -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.
*
* 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 isObjectMonitorUsageSupported : 1;
unsigned int isSynchronizerUsageSupported : 1;
- unsigned int : 24;
+ unsigned int isThreadAllocatedMemorySupported : 1;
+ unsigned int : 23;
} jmmOptionalSupport;
typedef enum {
@@ -105,7 +106,8 @@ typedef enum {
JMM_VERBOSE_GC = 21,
JMM_VERBOSE_CLASS = 22,
JMM_THREAD_CONTENTION_MONITORING = 23,
- JMM_THREAD_CPU_TIME = 24
+ JMM_THREAD_CPU_TIME = 24,
+ JMM_THREAD_ALLOCATED_MEMORY = 25
} jmmBoolAttribute;
@@ -213,7 +215,10 @@ typedef struct jmmInterface_1_ {
jobject (JNICALL *GetMemoryPoolUsage) (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);
@@ -228,6 +233,8 @@ typedef struct jmmInterface_1_ {
jlong* result);
jobjectArray (JNICALL *FindCircularBlockedThreads) (JNIEnv *env);
+
+ // Not used in JDK 6 or JDK 7
jlong (JNICALL *GetThreadCpuTime) (JNIEnv *env, jlong thread_id);
jobjectArray (JNICALL *GetVMGlobalNames) (JNIEnv *env);
@@ -262,14 +269,22 @@ typedef struct jmmInterface_1_ {
void (JNICALL *GetLastGCStat) (JNIEnv *env,
jobject mgr,
jmmGCStat *gc_stat);
- jlong (JNICALL *GetThreadCpuTimeWithKind) (JNIEnv *env,
- jlong thread_id,
- jboolean user_sys_cpu_time);
- void* reserved5;
+
+ jlong (JNICALL *GetThreadCpuTimeWithKind)
+ (JNIEnv *env,
+ jlong thread_id,
+ jboolean user_sys_cpu_time);
+ void (JNICALL *GetThreadCpuTimesWithKind)
+ (JNIEnv *env,
+ jlongArray ids,
+ jlongArray timeArray,
+ jboolean user_sys_cpu_time);
+
jint (JNICALL *DumpHeap0) (JNIEnv *env,
jstring outputfile,
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,
jstring flag_name,
jvalue new_value);
diff --git a/src/share/vm/services/management.cpp b/src/share/vm/services/management.cpp
index cbc255cd2..40c35874a 100644
--- a/src/share/vm/services/management.cpp
+++ b/src/share/vm/services/management.cpp
@@ -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.
*
* 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.isOtherThreadCpuTimeSupported = 0;
}
+
_optional_support.isBootClassPathSupported = 1;
_optional_support.isObjectMonitorUsageSupported = 1;
#ifndef SERVICES_KERNEL
// This depends on the heap inspector
_optional_support.isSynchronizerUsageSupported = 1;
#endif // SERVICES_KERNEL
+ _optional_support.isThreadAllocatedMemorySupported = 1;
}
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) {
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
int i = 0;
@@ -402,11 +399,9 @@ static void validate_thread_id_array(typeArrayHandle ids_ah, TRAPS) {
"Invalid thread ID entry");
}
}
-
}
static void validate_thread_info_array(objArrayHandle infoArray_h, TRAPS) {
-
// check if the element of infoArray is of type ThreadInfo class
klassOop threadinfo_klass = Management::java_lang_management_ThreadInfo_klass(CHECK);
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(),
"infoArray element type is not ThreadInfo class");
}
-
}
@@ -770,6 +764,45 @@ JVM_ENTRY(jlong, jmm_SetPoolThreshold(JNIEnv* env, jobject obj, jmmThresholdType
return prev;
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
// the memory usage for the heap or non-heap memory.
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();
case JMM_THREAD_CPU_TIME:
return ThreadService::is_thread_cpu_time_enabled();
+ case JMM_THREAD_ALLOCATED_MEMORY:
+ return ThreadService::is_thread_allocated_memory_enabled();
default:
assert(0, "Unrecognized attribute");
return false;
@@ -851,6 +886,8 @@ JVM_ENTRY(jboolean, jmm_SetBoolAttribute(JNIEnv *env, jmmBoolAttribute att, jboo
return ThreadService::set_thread_monitoring_contention(flag != 0);
case JMM_THREAD_CPU_TIME:
return ThreadService::set_thread_cpu_time_enabled(flag != 0);
+ case JMM_THREAD_ALLOCATED_MEMORY:
+ return ThreadService::set_thread_allocated_memory_enabled(flag != 0);
default:
assert(0, "Unrecognized attribute");
return false;
@@ -1096,6 +1133,7 @@ static void do_thread_dump(ThreadDumpResult* dump_result,
// maxDepth == 0 requests no stack trace.
// 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))
// Check if threads is null
if (ids == NULL || infoArray == NULL) {
@@ -1159,7 +1197,6 @@ JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jo
}
} else {
// obtain thread dump with the specific list of threads with stack trace
-
do_thread_dump(&dump_result,
ids_ah,
num_threads,
@@ -1252,8 +1289,6 @@ JVM_ENTRY(jobjectArray, jmm_DumpThreads(JNIEnv *env, jlongArray thread_ids, jboo
continue;
}
-
-
ThreadStackTrace* stacktrace = ts->get_stack_trace();
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;
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
JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env))
// last flag entry is always NULL, so subtract 1
@@ -2020,7 +2098,7 @@ const struct jmmInterface_1_ jmm_interface = {
jmm_GetMemoryManagers,
jmm_GetMemoryPoolUsage,
jmm_GetPeakMemoryPoolUsage,
- NULL,
+ jmm_GetThreadAllocatedMemory,
jmm_GetMemoryUsage,
jmm_GetLongAttribute,
jmm_GetBoolAttribute,
@@ -2038,7 +2116,7 @@ const struct jmmInterface_1_ jmm_interface = {
jmm_GetGCExtAttributeInfo,
jmm_GetLastGCStat,
jmm_GetThreadCpuTimeWithKind,
- NULL,
+ jmm_GetThreadCpuTimesWithKind,
jmm_DumpHeap0,
jmm_FindDeadlockedThreads,
jmm_SetVMGlobal,
diff --git a/src/share/vm/services/threadService.cpp b/src/share/vm/services/threadService.cpp
index 4c3139752..753cc9685 100644
--- a/src/share/vm/services/threadService.cpp
+++ b/src/share/vm/services/threadService.cpp
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,6 +46,7 @@
// Default is disabled.
bool ThreadService::_thread_monitoring_contention_enabled = false;
bool ThreadService::_thread_cpu_time_enabled = false;
+bool ThreadService::_thread_allocated_memory_enabled = false;
PerfCounter* ThreadService::_total_threads_count = NULL;
PerfVariable* ThreadService::_live_threads_count = NULL;
@@ -84,6 +85,8 @@ void ThreadService::init() {
if (os::is_thread_cpu_time_supported()) {
_thread_cpu_time_enabled = true;
}
+
+ _thread_allocated_memory_enabled = true; // Always on, so enable it
}
void ThreadService::reset_peak_thread_count() {
@@ -181,6 +184,15 @@ bool ThreadService::set_thread_cpu_time_enabled(bool flag) {
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
void ThreadService::oops_do(OopClosure* f) {
for (ThreadDumpResult* dump = _threaddump_list; dump != NULL; dump = dump->next()) {
diff --git a/src/share/vm/services/threadService.hpp b/src/share/vm/services/threadService.hpp
index acef14edd..bd1395a7d 100644
--- a/src/share/vm/services/threadService.hpp
+++ b/src/share/vm/services/threadService.hpp
@@ -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.
*
* 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_cpu_time_enabled;
+ static bool _thread_allocated_memory_enabled;
// Need to keep the list of thread dump result that
// 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 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_peak_thread_count() { return _peak_threads_count->get_value(); }
static jlong get_live_thread_count() { return _live_threads_count->get_value() - _exiting_threads_count; }
diff --git a/src/share/vm/utilities/debug.cpp b/src/share/vm/utilities/debug.cpp
index 484dcf581..cb44189fd 100644
--- a/src/share/vm/utilities/debug.cpp
+++ b/src/share/vm/utilities/debug.cpp
@@ -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,
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
// error only; gathering additional data might cause an allocation and a
diff --git a/src/share/vm/utilities/vmError.cpp b/src/share/vm/utilities/vmError.cpp
index 371115036..4b8e055d4 100644
--- a/src/share/vm/utilities/vmError.cpp
+++ b/src/share/vm/utilities/vmError.cpp
@@ -67,7 +67,7 @@ const char *env_list[] = {
// threads are blocked forever inside report_and_die().
// 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;
_id = sig;
_pc = pc;
@@ -322,29 +322,51 @@ void VMError::report(outputStream* st) {
STEP(10, "(printing fatal error message)")
- st->print_cr("#");
- st->print_cr("# A fatal error has been detected by the Java Runtime Environment:");
+ st->print_cr("#");
+ if (should_report_bug(_id)) {
+ 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)")
switch(_id) {
case oom_error:
- st->print_cr("#");
- st->print("# java.lang.OutOfMemoryError: ");
if (_size) {
- st->print("requested ");
- sprintf(buf,SIZE_FORMAT,_size);
+ st->print("# Native memory allocation (malloc) failed to allocate ");
+ jio_snprintf(buf, sizeof(buf), SIZE_FORMAT, _size);
st->print(buf);
st->print(" bytes");
if (_message != NULL) {
st->print(" for ");
st->print(_message);
}
- st->print_cr(". Out of swap space?");
+ st->cr();
} else {
if (_message != NULL)
+ st->print("# ");
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;
case internal_error:
default:
@@ -361,7 +383,11 @@ void VMError::report(outputStream* st) {
st->print(" (0x%x)", _id); // signal number
st->print(" at pc=" PTR_FORMAT, _pc);
} else {
- st->print("Internal Error");
+ if (should_report_bug(_id)) {
+ st->print("Internal Error");
+ } else {
+ st->print("Out of Memory Error");
+ }
if (_filename != NULL && _lineno > 0) {
#ifdef PRODUCT
// In product mode chop off pathname?
@@ -393,12 +419,14 @@ void VMError::report(outputStream* st) {
STEP(40, "(printing error message)")
- // error message
- if (_detail_msg) {
- st->print_cr("# %s: %s", _message ? _message : "Error", _detail_msg);
- } else if (_message) {
- st->print_cr("# Error: %s", _message);
- }
+ if (should_report_bug(_id)) { // already printed the message.
+ // error message
+ if (_detail_msg) {
+ st->print_cr("# %s: %s", _message ? _message : "Error", _detail_msg);
+ } else if (_message) {
+ st->print_cr("# Error: %s", _message);
+ }
+ }
STEP(50, "(printing Java version string)")
@@ -428,7 +456,9 @@ void VMError::report(outputStream* st) {
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)" )
@@ -906,7 +936,7 @@ void VMError::report_and_die() {
OnError = NULL;
}
- static bool skip_bug_url = false;
+ static bool skip_bug_url = !should_report_bug(first_error->_id);
if (!skip_bug_url) {
skip_bug_url = true;
@@ -919,7 +949,8 @@ void VMError::report_and_die() {
static bool skip_os_abort = false;
if (!skip_os_abort) {
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();
diff --git a/src/share/vm/utilities/vmError.hpp b/src/share/vm/utilities/vmError.hpp
index 3d80ce321..e9d60b3a1 100644
--- a/src/share/vm/utilities/vmError.hpp
+++ b/src/share/vm/utilities/vmError.hpp
@@ -87,10 +87,12 @@ class VMError : public StackObj {
// accessor
const char* message() const { return _message; }
const char* detail_msg() const { return _detail_msg; }
+ bool should_report_bug(unsigned int id) { return id != oom_error; }
public:
// 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
VMError(Thread* thread, const char* filename, int lineno,
const char* message, const char * detail_msg);
diff --git a/test/compiler/6579789/Test6579789.java b/test/compiler/6579789/Test6579789.java
new file mode 100644
index 000000000..344a08fae
--- /dev/null
+++ b/test/compiler/6579789/Test6579789.java
@@ -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++;
+ }
+ }
+}
diff --git a/test/compiler/7009231/Test7009231.java b/test/compiler/7009231/Test7009231.java
new file mode 100644
index 000000000..64afc6601
--- /dev/null
+++ b/test/compiler/7009231/Test7009231.java
@@ -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;
+ }
+}
diff --git a/test/compiler/7009359/Test7009359.java b/test/compiler/7009359/Test7009359.java
new file mode 100644
index 000000000..408fd713e
--- /dev/null
+++ b/test/compiler/7009359/Test7009359.java
@@ -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";
+ }
+ }
+}
+