提交 e1f463ac 编写于 作者: K kvn

Merge

...@@ -432,3 +432,8 @@ e56d11f8cc2158d4280f80e56d196193349c150a hs25.20-b03 ...@@ -432,3 +432,8 @@ e56d11f8cc2158d4280f80e56d196193349c150a hs25.20-b03
ecf3678d5736a645aea893b525a9eb5fa1a8e072 hs25.20-b04 ecf3678d5736a645aea893b525a9eb5fa1a8e072 hs25.20-b04
51e1bb81df8680bd237630323de5e0704fb25607 jdk8u20-b03 51e1bb81df8680bd237630323de5e0704fb25607 jdk8u20-b03
54436d3b2a915ff50a8d6b34f61d5afb45be7bb6 hs25.20-b05 54436d3b2a915ff50a8d6b34f61d5afb45be7bb6 hs25.20-b05
d4e18f0633c662588cc0875be7759721c7d85af4 jdk8u20-b04
57eb3e69397e9d5818c5fdaef65b47d9b03f7f88 jdk8u20-b05
804f89b6ff46728d60a69e9a338e63f362f7ac68 hs25.20-b06
c3d92e04873788275eeebec6bcd2948cdbd143a7 jdk8u20-b06
39eae002499704438142e78f5e0e24d46d0b266f hs25.20-b07
...@@ -51,9 +51,9 @@ public class G1CollectedHeap extends SharedHeap { ...@@ -51,9 +51,9 @@ public class G1CollectedHeap extends SharedHeap {
static private CIntegerField summaryBytesUsedField; static private CIntegerField summaryBytesUsedField;
// G1MonitoringSupport* _g1mm; // G1MonitoringSupport* _g1mm;
static private AddressField g1mmField; static private AddressField g1mmField;
// MasterOldRegionSet _old_set; // HeapRegionSet _old_set;
static private long oldSetFieldOffset; static private long oldSetFieldOffset;
// MasterHumongousRegionSet _humongous_set; // HeapRegionSet _humongous_set;
static private long humongousSetFieldOffset; static private long humongousSetFieldOffset;
static { static {
......
...@@ -40,12 +40,8 @@ import sun.jvm.hotspot.types.TypeDataBase; ...@@ -40,12 +40,8 @@ import sun.jvm.hotspot.types.TypeDataBase;
// Mirror class for HeapRegionSetBase. Represents a group of regions. // Mirror class for HeapRegionSetBase. Represents a group of regions.
public class HeapRegionSetBase extends VMObject { public class HeapRegionSetBase extends VMObject {
// uint _length;
static private CIntegerField lengthField; static private long countField;
// uint _region_num;
static private CIntegerField regionNumField;
// size_t _total_used_bytes;
static private CIntegerField totalUsedBytesField;
static { static {
VM.registerVMInitializedObserver(new Observer() { VM.registerVMInitializedObserver(new Observer() {
...@@ -58,21 +54,13 @@ public class HeapRegionSetBase extends VMObject { ...@@ -58,21 +54,13 @@ public class HeapRegionSetBase extends VMObject {
static private synchronized void initialize(TypeDataBase db) { static private synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("HeapRegionSetBase"); Type type = db.lookupType("HeapRegionSetBase");
lengthField = type.getCIntegerField("_length"); countField = type.getField("_count").getOffset();
regionNumField = type.getCIntegerField("_region_num");
totalUsedBytesField = type.getCIntegerField("_total_used_bytes");
}
public long length() {
return lengthField.getValue(addr);
} }
public long regionNum() {
return regionNumField.getValue(addr);
}
public long totalUsedBytes() { public HeapRegionSetCount count() {
return totalUsedBytesField.getValue(addr); Address countFieldAddr = addr.addOffsetTo(countField);
return (HeapRegionSetCount) VMObjectFactory.newObject(HeapRegionSetCount.class, countFieldAddr);
} }
public HeapRegionSetBase(Address addr) { public HeapRegionSetBase(Address addr) {
......
/*
* Copyright (c) 2014, 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.
*
*/
package sun.jvm.hotspot.gc_implementation.g1;
import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;
import sun.jvm.hotspot.debugger.Address;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.runtime.VMObject;
import sun.jvm.hotspot.runtime.VMObjectFactory;
import sun.jvm.hotspot.types.AddressField;
import sun.jvm.hotspot.types.CIntegerField;
import sun.jvm.hotspot.types.Type;
import sun.jvm.hotspot.types.TypeDataBase;
// Mirror class for HeapRegionSetCount. Represents a group of regions.
public class HeapRegionSetCount extends VMObject {
static private CIntegerField lengthField;
static private CIntegerField capacityField;
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
static private synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("HeapRegionSetCount");
lengthField = type.getCIntegerField("_length");
capacityField = type.getCIntegerField("_capacity");
}
public long length() {
return lengthField.getValue(addr);
}
public long capacity() {
return capacityField.getValue(addr);
}
public HeapRegionSetCount(Address addr) {
super(addr);
}
}
...@@ -114,7 +114,8 @@ public class HeapSummary extends Tool { ...@@ -114,7 +114,8 @@ public class HeapSummary extends Tool {
long survivorRegionNum = g1mm.survivorRegionNum(); long survivorRegionNum = g1mm.survivorRegionNum();
HeapRegionSetBase oldSet = g1h.oldSet(); HeapRegionSetBase oldSet = g1h.oldSet();
HeapRegionSetBase humongousSet = g1h.humongousSet(); HeapRegionSetBase humongousSet = g1h.humongousSet();
long oldRegionNum = oldSet.regionNum() + humongousSet.regionNum(); long oldRegionNum = oldSet.count().length()
+ humongousSet.count().capacity() / HeapRegion.grainBytes();
printG1Space("G1 Heap:", g1h.n_regions(), printG1Space("G1 Heap:", g1h.n_regions(),
g1h.used(), g1h.capacity()); g1h.used(), g1h.capacity());
System.out.println("G1 Young Generation:"); System.out.println("G1 Young Generation:");
......
# #
# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
...@@ -87,9 +87,10 @@ ifeq ($(INCLUDE_ALL_GCS), false) ...@@ -87,9 +87,10 @@ ifeq ($(INCLUDE_ALL_GCS), false)
g1BlockOffsetTable.cpp g1CardCounts.cpp g1CollectedHeap.cpp g1CollectorPolicy.cpp \ g1BlockOffsetTable.cpp g1CardCounts.cpp g1CollectedHeap.cpp g1CollectorPolicy.cpp \
g1ErgoVerbose.cpp g1GCPhaseTimes.cpp g1HRPrinter.cpp g1HotCardCache.cpp g1Log.cpp \ g1ErgoVerbose.cpp g1GCPhaseTimes.cpp g1HRPrinter.cpp g1HotCardCache.cpp g1Log.cpp \
g1MMUTracker.cpp g1MarkSweep.cpp g1MemoryPool.cpp g1MonitoringSupport.cpp g1OopClosures.cpp \ g1MMUTracker.cpp g1MarkSweep.cpp g1MemoryPool.cpp g1MonitoringSupport.cpp g1OopClosures.cpp \
g1RemSet.cpp g1RemSetSummary.cpp g1SATBCardTableModRefBS.cpp g1_globals.cpp heapRegion.cpp \ g1RemSet.cpp g1RemSetSummary.cpp g1SATBCardTableModRefBS.cpp g1StringDedup.cpp g1StringDedupStat.cpp \
g1StringDedupTable.cpp g1StringDedupThread.cpp g1StringDedupQueue.cpp g1_globals.cpp heapRegion.cpp \
g1BiasedArray.cpp heapRegionRemSet.cpp heapRegionSeq.cpp heapRegionSet.cpp heapRegionSets.cpp \ g1BiasedArray.cpp heapRegionRemSet.cpp heapRegionSeq.cpp heapRegionSet.cpp heapRegionSets.cpp \
ptrQueue.cpp satbQueue.cpp sparsePRT.cpp survRateGroup.cpp vm_operations_g1.cpp \ ptrQueue.cpp satbQueue.cpp sparsePRT.cpp survRateGroup.cpp vm_operations_g1.cpp g1CodeCacheRemSet.cpp \
adjoiningGenerations.cpp adjoiningVirtualSpaces.cpp asPSOldGen.cpp asPSYoungGen.cpp \ adjoiningGenerations.cpp adjoiningVirtualSpaces.cpp asPSOldGen.cpp asPSYoungGen.cpp \
cardTableExtension.cpp gcTaskManager.cpp gcTaskThread.cpp objectStartArray.cpp \ cardTableExtension.cpp gcTaskManager.cpp gcTaskThread.cpp objectStartArray.cpp \
parallelScavengeHeap.cpp parMarkBitMap.cpp pcTasks.cpp psAdaptiveSizePolicy.cpp \ parallelScavengeHeap.cpp parMarkBitMap.cpp pcTasks.cpp psAdaptiveSizePolicy.cpp \
......
...@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2014 ...@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2014
HS_MAJOR_VER=25 HS_MAJOR_VER=25
HS_MINOR_VER=20 HS_MINOR_VER=20
HS_BUILD_NUMBER=05 HS_BUILD_NUMBER=08
JDK_MAJOR_VER=1 JDK_MAJOR_VER=1
JDK_MINOR_VER=8 JDK_MINOR_VER=8
......
...@@ -2071,19 +2071,6 @@ const RegMask Matcher::method_handle_invoke_SP_save_mask() { ...@@ -2071,19 +2071,6 @@ const RegMask Matcher::method_handle_invoke_SP_save_mask() {
return L7_REGP_mask(); return L7_REGP_mask();
} }
const RegMask Matcher::mathExactI_result_proj_mask() {
return G1_REGI_mask();
}
const RegMask Matcher::mathExactL_result_proj_mask() {
return G1_REGL_mask();
}
const RegMask Matcher::mathExactI_flags_proj_mask() {
return INT_FLAGS_mask();
}
%} %}
......
...@@ -1089,6 +1089,21 @@ void Assembler::andl(Register dst, Register src) { ...@@ -1089,6 +1089,21 @@ void Assembler::andl(Register dst, Register src) {
emit_arith(0x23, 0xC0, dst, src); emit_arith(0x23, 0xC0, dst, src);
} }
void Assembler::andnl(Register dst, Register src1, Register src2) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
int encode = vex_prefix_0F38_and_encode(dst, src1, src2);
emit_int8((unsigned char)0xF2);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::andnl(Register dst, Register src1, Address src2) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
vex_prefix_0F38(dst, src1, src2);
emit_int8((unsigned char)0xF2);
emit_operand(dst, src2);
}
void Assembler::bsfl(Register dst, Register src) { void Assembler::bsfl(Register dst, Register src) {
int encode = prefix_and_encode(dst->encoding(), src->encoding()); int encode = prefix_and_encode(dst->encoding(), src->encoding());
emit_int8(0x0F); emit_int8(0x0F);
...@@ -1097,7 +1112,6 @@ void Assembler::bsfl(Register dst, Register src) { ...@@ -1097,7 +1112,6 @@ void Assembler::bsfl(Register dst, Register src) {
} }
void Assembler::bsrl(Register dst, Register src) { void Assembler::bsrl(Register dst, Register src) {
assert(!VM_Version::supports_lzcnt(), "encoding is treated as LZCNT");
int encode = prefix_and_encode(dst->encoding(), src->encoding()); int encode = prefix_and_encode(dst->encoding(), src->encoding());
emit_int8(0x0F); emit_int8(0x0F);
emit_int8((unsigned char)0xBD); emit_int8((unsigned char)0xBD);
...@@ -1110,6 +1124,51 @@ void Assembler::bswapl(Register reg) { // bswap ...@@ -1110,6 +1124,51 @@ void Assembler::bswapl(Register reg) { // bswap
emit_int8((unsigned char)(0xC8 | encode)); emit_int8((unsigned char)(0xC8 | encode));
} }
void Assembler::blsil(Register dst, Register src) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
int encode = vex_prefix_0F38_and_encode(rbx, dst, src);
emit_int8((unsigned char)0xF3);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::blsil(Register dst, Address src) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
vex_prefix_0F38(rbx, dst, src);
emit_int8((unsigned char)0xF3);
emit_operand(rbx, src);
}
void Assembler::blsmskl(Register dst, Register src) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
int encode = vex_prefix_0F38_and_encode(rdx, dst, src);
emit_int8((unsigned char)0xF3);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::blsmskl(Register dst, Address src) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
vex_prefix_0F38(rdx, dst, src);
emit_int8((unsigned char)0xF3);
emit_operand(rdx, src);
}
void Assembler::blsrl(Register dst, Register src) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
int encode = vex_prefix_0F38_and_encode(rcx, dst, src);
emit_int8((unsigned char)0xF3);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::blsrl(Register dst, Address src) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
vex_prefix_0F38(rcx, dst, src);
emit_int8((unsigned char)0xF3);
emit_operand(rcx, src);
}
void Assembler::call(Label& L, relocInfo::relocType rtype) { void Assembler::call(Label& L, relocInfo::relocType rtype) {
// suspect disp32 is always good // suspect disp32 is always good
int operand = LP64_ONLY(disp32_operand) NOT_LP64(imm_operand); int operand = LP64_ONLY(disp32_operand) NOT_LP64(imm_operand);
...@@ -2283,6 +2342,11 @@ void Assembler::vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector25 ...@@ -2283,6 +2342,11 @@ void Assembler::vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector25
emit_int8(imm8); emit_int8(imm8);
} }
void Assembler::pause() {
emit_int8((unsigned char)0xF3);
emit_int8((unsigned char)0x90);
}
void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) { void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) {
assert(VM_Version::supports_sse4_2(), ""); assert(VM_Version::supports_sse4_2(), "");
InstructionMark im(this); InstructionMark im(this);
...@@ -2607,6 +2671,11 @@ void Assembler::rcll(Register dst, int imm8) { ...@@ -2607,6 +2671,11 @@ void Assembler::rcll(Register dst, int imm8) {
} }
} }
void Assembler::rdtsc() {
emit_int8((unsigned char)0x0F);
emit_int8((unsigned char)0x31);
}
// copies data from [esi] to [edi] using rcx pointer sized words // copies data from [esi] to [edi] using rcx pointer sized words
// generic // generic
void Assembler::rep_mov() { void Assembler::rep_mov() {
...@@ -2878,6 +2947,24 @@ void Assembler::testl(Register dst, Address src) { ...@@ -2878,6 +2947,24 @@ void Assembler::testl(Register dst, Address src) {
emit_operand(dst, src); emit_operand(dst, src);
} }
void Assembler::tzcntl(Register dst, Register src) {
assert(VM_Version::supports_bmi1(), "tzcnt instruction not supported");
emit_int8((unsigned char)0xF3);
int encode = prefix_and_encode(dst->encoding(), src->encoding());
emit_int8(0x0F);
emit_int8((unsigned char)0xBC);
emit_int8((unsigned char)0xC0 | encode);
}
void Assembler::tzcntq(Register dst, Register src) {
assert(VM_Version::supports_bmi1(), "tzcnt instruction not supported");
emit_int8((unsigned char)0xF3);
int encode = prefixq_and_encode(dst->encoding(), src->encoding());
emit_int8(0x0F);
emit_int8((unsigned char)0xBC);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::ucomisd(XMMRegister dst, Address src) { void Assembler::ucomisd(XMMRegister dst, Address src) {
NOT_LP64(assert(VM_Version::supports_sse2(), "")); NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_66); emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_66);
...@@ -2898,6 +2985,11 @@ void Assembler::ucomiss(XMMRegister dst, XMMRegister src) { ...@@ -2898,6 +2985,11 @@ void Assembler::ucomiss(XMMRegister dst, XMMRegister src) {
emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE); emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE);
} }
void Assembler::xabort(int8_t imm8) {
emit_int8((unsigned char)0xC6);
emit_int8((unsigned char)0xF8);
emit_int8((unsigned char)(imm8 & 0xFF));
}
void Assembler::xaddl(Address dst, Register src) { void Assembler::xaddl(Address dst, Register src) {
InstructionMark im(this); InstructionMark im(this);
...@@ -2907,6 +2999,24 @@ void Assembler::xaddl(Address dst, Register src) { ...@@ -2907,6 +2999,24 @@ void Assembler::xaddl(Address dst, Register src) {
emit_operand(src, dst); emit_operand(src, dst);
} }
void Assembler::xbegin(Label& abort, relocInfo::relocType rtype) {
InstructionMark im(this);
relocate(rtype);
if (abort.is_bound()) {
address entry = target(abort);
assert(entry != NULL, "abort entry NULL");
intptr_t offset = entry - pc();
emit_int8((unsigned char)0xC7);
emit_int8((unsigned char)0xF8);
emit_int32(offset - 6); // 2 opcode + 4 address
} else {
abort.add_patch_at(code(), locator());
emit_int8((unsigned char)0xC7);
emit_int8((unsigned char)0xF8);
emit_int32(0);
}
}
void Assembler::xchgl(Register dst, Address src) { // xchg void Assembler::xchgl(Register dst, Address src) { // xchg
InstructionMark im(this); InstructionMark im(this);
prefix(src, dst); prefix(src, dst);
...@@ -2920,6 +3030,12 @@ void Assembler::xchgl(Register dst, Register src) { ...@@ -2920,6 +3030,12 @@ void Assembler::xchgl(Register dst, Register src) {
emit_int8((unsigned char)(0xC0 | encode)); emit_int8((unsigned char)(0xC0 | encode));
} }
void Assembler::xend() {
emit_int8((unsigned char)0x0F);
emit_int8((unsigned char)0x01);
emit_int8((unsigned char)0xD5);
}
void Assembler::xgetbv() { void Assembler::xgetbv() {
emit_int8(0x0F); emit_int8(0x0F);
emit_int8(0x01); emit_int8(0x01);
...@@ -4837,6 +4953,21 @@ void Assembler::andq(Register dst, Register src) { ...@@ -4837,6 +4953,21 @@ void Assembler::andq(Register dst, Register src) {
emit_arith(0x23, 0xC0, dst, src); emit_arith(0x23, 0xC0, dst, src);
} }
void Assembler::andnq(Register dst, Register src1, Register src2) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
int encode = vex_prefix_0F38_and_encode_q(dst, src1, src2);
emit_int8((unsigned char)0xF2);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::andnq(Register dst, Register src1, Address src2) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
vex_prefix_0F38_q(dst, src1, src2);
emit_int8((unsigned char)0xF2);
emit_operand(dst, src2);
}
void Assembler::bsfq(Register dst, Register src) { void Assembler::bsfq(Register dst, Register src) {
int encode = prefixq_and_encode(dst->encoding(), src->encoding()); int encode = prefixq_and_encode(dst->encoding(), src->encoding());
emit_int8(0x0F); emit_int8(0x0F);
...@@ -4845,7 +4976,6 @@ void Assembler::bsfq(Register dst, Register src) { ...@@ -4845,7 +4976,6 @@ void Assembler::bsfq(Register dst, Register src) {
} }
void Assembler::bsrq(Register dst, Register src) { void Assembler::bsrq(Register dst, Register src) {
assert(!VM_Version::supports_lzcnt(), "encoding is treated as LZCNT");
int encode = prefixq_and_encode(dst->encoding(), src->encoding()); int encode = prefixq_and_encode(dst->encoding(), src->encoding());
emit_int8(0x0F); emit_int8(0x0F);
emit_int8((unsigned char)0xBD); emit_int8((unsigned char)0xBD);
...@@ -4858,6 +4988,51 @@ void Assembler::bswapq(Register reg) { ...@@ -4858,6 +4988,51 @@ void Assembler::bswapq(Register reg) {
emit_int8((unsigned char)(0xC8 | encode)); emit_int8((unsigned char)(0xC8 | encode));
} }
void Assembler::blsiq(Register dst, Register src) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
int encode = vex_prefix_0F38_and_encode_q(rbx, dst, src);
emit_int8((unsigned char)0xF3);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::blsiq(Register dst, Address src) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
vex_prefix_0F38_q(rbx, dst, src);
emit_int8((unsigned char)0xF3);
emit_operand(rbx, src);
}
void Assembler::blsmskq(Register dst, Register src) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
int encode = vex_prefix_0F38_and_encode_q(rdx, dst, src);
emit_int8((unsigned char)0xF3);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::blsmskq(Register dst, Address src) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
vex_prefix_0F38_q(rdx, dst, src);
emit_int8((unsigned char)0xF3);
emit_operand(rdx, src);
}
void Assembler::blsrq(Register dst, Register src) {
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
int encode = vex_prefix_0F38_and_encode_q(rcx, dst, src);
emit_int8((unsigned char)0xF3);
emit_int8((unsigned char)(0xC0 | encode));
}
void Assembler::blsrq(Register dst, Address src) {
InstructionMark im(this);
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
vex_prefix_0F38_q(rcx, dst, src);
emit_int8((unsigned char)0xF3);
emit_operand(rcx, src);
}
void Assembler::cdqq() { void Assembler::cdqq() {
prefix(REX_W); prefix(REX_W);
emit_int8((unsigned char)0x99); emit_int8((unsigned char)0x99);
......
...@@ -590,10 +590,35 @@ private: ...@@ -590,10 +590,35 @@ private:
vex_prefix(src, nds_enc, dst_enc, pre, VEX_OPCODE_0F, false, vector256); vex_prefix(src, nds_enc, dst_enc, pre, VEX_OPCODE_0F, false, vector256);
} }
void vex_prefix_0F38(Register dst, Register nds, Address src) {
bool vex_w = false;
bool vector256 = false;
vex_prefix(src, nds->encoding(), dst->encoding(),
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector256);
}
void vex_prefix_0F38_q(Register dst, Register nds, Address src) {
bool vex_w = true;
bool vector256 = false;
vex_prefix(src, nds->encoding(), dst->encoding(),
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector256);
}
int vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc, int vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc,
VexSimdPrefix pre, VexOpcode opc, VexSimdPrefix pre, VexOpcode opc,
bool vex_w, bool vector256); bool vex_w, bool vector256);
int vex_prefix_0F38_and_encode(Register dst, Register nds, Register src) {
bool vex_w = false;
bool vector256 = false;
return vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(),
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector256);
}
int vex_prefix_0F38_and_encode_q(Register dst, Register nds, Register src) {
bool vex_w = true;
bool vector256 = false;
return vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(),
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector256);
}
int vex_prefix_and_encode(XMMRegister dst, XMMRegister nds, XMMRegister src, int vex_prefix_and_encode(XMMRegister dst, XMMRegister nds, XMMRegister src,
VexSimdPrefix pre, bool vector256 = false, VexSimdPrefix pre, bool vector256 = false,
VexOpcode opc = VEX_OPCODE_0F) { VexOpcode opc = VEX_OPCODE_0F) {
...@@ -897,6 +922,27 @@ private: ...@@ -897,6 +922,27 @@ private:
void andq(Register dst, Address src); void andq(Register dst, Address src);
void andq(Register dst, Register src); void andq(Register dst, Register src);
// BMI instructions
void andnl(Register dst, Register src1, Register src2);
void andnl(Register dst, Register src1, Address src2);
void andnq(Register dst, Register src1, Register src2);
void andnq(Register dst, Register src1, Address src2);
void blsil(Register dst, Register src);
void blsil(Register dst, Address src);
void blsiq(Register dst, Register src);
void blsiq(Register dst, Address src);
void blsmskl(Register dst, Register src);
void blsmskl(Register dst, Address src);
void blsmskq(Register dst, Register src);
void blsmskq(Register dst, Address src);
void blsrl(Register dst, Register src);
void blsrl(Register dst, Address src);
void blsrq(Register dst, Register src);
void blsrq(Register dst, Address src);
void bsfl(Register dst, Register src); void bsfl(Register dst, Register src);
void bsrl(Register dst, Register src); void bsrl(Register dst, Register src);
...@@ -1405,6 +1451,8 @@ private: ...@@ -1405,6 +1451,8 @@ private:
// Pemutation of 64bit words // Pemutation of 64bit words
void vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector256); void vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector256);
void pause();
// SSE4.2 string instructions // SSE4.2 string instructions
void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8); void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8);
void pcmpestri(XMMRegister xmm1, Address src, int imm8); void pcmpestri(XMMRegister xmm1, Address src, int imm8);
...@@ -1489,6 +1537,8 @@ private: ...@@ -1489,6 +1537,8 @@ private:
void rclq(Register dst, int imm8); void rclq(Register dst, int imm8);
void rdtsc();
void ret(int imm16); void ret(int imm16);
void sahf(); void sahf();
...@@ -1574,6 +1624,9 @@ private: ...@@ -1574,6 +1624,9 @@ private:
void testq(Register dst, int32_t imm32); void testq(Register dst, int32_t imm32);
void testq(Register dst, Register src); void testq(Register dst, Register src);
// BMI - count trailing zeros
void tzcntl(Register dst, Register src);
void tzcntq(Register dst, Register src);
// Unordered Compare Scalar Double-Precision Floating-Point Values and set EFLAGS // Unordered Compare Scalar Double-Precision Floating-Point Values and set EFLAGS
void ucomisd(XMMRegister dst, Address src); void ucomisd(XMMRegister dst, Address src);
...@@ -1583,16 +1636,22 @@ private: ...@@ -1583,16 +1636,22 @@ private:
void ucomiss(XMMRegister dst, Address src); void ucomiss(XMMRegister dst, Address src);
void ucomiss(XMMRegister dst, XMMRegister src); void ucomiss(XMMRegister dst, XMMRegister src);
void xabort(int8_t imm8);
void xaddl(Address dst, Register src); void xaddl(Address dst, Register src);
void xaddq(Address dst, Register src); void xaddq(Address dst, Register src);
void xbegin(Label& abort, relocInfo::relocType rtype = relocInfo::none);
void xchgl(Register reg, Address adr); void xchgl(Register reg, Address adr);
void xchgl(Register dst, Register src); void xchgl(Register dst, Register src);
void xchgq(Register reg, Address adr); void xchgq(Register reg, Address adr);
void xchgq(Register dst, Register src); void xchgq(Register dst, Register src);
void xend();
// Get Value of Extended Control Register // Get Value of Extended Control Register
void xgetbv(); void xgetbv();
......
...@@ -129,11 +129,53 @@ define_pd_global(uintx, TypeProfileLevel, 111); ...@@ -129,11 +129,53 @@ define_pd_global(uintx, TypeProfileLevel, 111);
product(bool, UseFastStosb, false, \ product(bool, UseFastStosb, false, \
"Use fast-string operation for zeroing: rep stosb") \ "Use fast-string operation for zeroing: rep stosb") \
\ \
/* Use Restricted Transactional Memory for lock eliding */ \
experimental(bool, UseRTMLocking, false, \
"Enable RTM lock eliding for inflated locks in compiled code") \
\
experimental(bool, UseRTMForStackLocks, false, \
"Enable RTM lock eliding for stack locks in compiled code") \
\
experimental(bool, UseRTMDeopt, false, \
"Perform deopt and recompilation based on RTM abort ratio") \
\
experimental(uintx, RTMRetryCount, 5, \
"Number of RTM retries on lock abort or busy") \
\
experimental(intx, RTMSpinLoopCount, 100, \
"Spin count for lock to become free before RTM retry") \
\
experimental(intx, RTMAbortThreshold, 1000, \
"Calculate abort ratio after this number of aborts") \
\
experimental(intx, RTMLockingThreshold, 10000, \
"Lock count at which to do RTM lock eliding without " \
"abort ratio calculation") \
\
experimental(intx, RTMAbortRatio, 50, \
"Lock abort ratio at which to stop use RTM lock eliding") \
\
experimental(intx, RTMTotalCountIncrRate, 64, \
"Increment total RTM attempted lock count once every n times") \
\
experimental(intx, RTMLockingCalculationDelay, 0, \
"Number of milliseconds to wait before start calculating aborts " \
"for RTM locking") \
\
experimental(bool, UseRTMXendForLockBusy, false, \
"Use RTM Xend instead of Xabort when lock busy") \
\
/* assembler */ \ /* assembler */ \
product(bool, Use486InstrsOnly, false, \ product(bool, Use486InstrsOnly, false, \
"Use 80486 Compliant instruction subset") \ "Use 80486 Compliant instruction subset") \
\ \
product(bool, UseCountLeadingZerosInstruction, false, \ product(bool, UseCountLeadingZerosInstruction, false, \
"Use count leading zeros instruction") \ "Use count leading zeros instruction") \
\
product(bool, UseCountTrailingZerosInstruction, false, \
"Use count trailing zeros instruction") \
\
product(bool, UseBMI1Instructions, false, \
"Use BMI instructions")
#endif // CPU_X86_VM_GLOBALS_X86_HPP #endif // CPU_X86_VM_GLOBALS_X86_HPP
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "asm/assembler.hpp" #include "asm/assembler.hpp"
#include "utilities/macros.hpp" #include "utilities/macros.hpp"
#include "runtime/rtmLocking.hpp"
// MacroAssembler extends Assembler by frequently used macros. // MacroAssembler extends Assembler by frequently used macros.
...@@ -111,7 +112,8 @@ class MacroAssembler: public Assembler { ...@@ -111,7 +112,8 @@ class MacroAssembler: public Assembler {
op == 0xE9 /* jmp */ || op == 0xE9 /* jmp */ ||
op == 0xEB /* short jmp */ || op == 0xEB /* short jmp */ ||
(op & 0xF0) == 0x70 /* short jcc */ || (op & 0xF0) == 0x70 /* short jcc */ ||
op == 0x0F && (branch[1] & 0xF0) == 0x80 /* jcc */, op == 0x0F && (branch[1] & 0xF0) == 0x80 /* jcc */ ||
op == 0xC7 && branch[1] == 0xF8 /* xbegin */,
"Invalid opcode at patch point"); "Invalid opcode at patch point");
if (op == 0xEB || (op & 0xF0) == 0x70) { if (op == 0xEB || (op & 0xF0) == 0x70) {
...@@ -121,7 +123,7 @@ class MacroAssembler: public Assembler { ...@@ -121,7 +123,7 @@ class MacroAssembler: public Assembler {
guarantee(this->is8bit(imm8), "Short forward jump exceeds 8-bit offset"); guarantee(this->is8bit(imm8), "Short forward jump exceeds 8-bit offset");
*disp = imm8; *disp = imm8;
} else { } else {
int* disp = (int*) &branch[(op == 0x0F)? 2: 1]; int* disp = (int*) &branch[(op == 0x0F || op == 0xC7)? 2: 1];
int imm32 = target - (address) &disp[1]; int imm32 = target - (address) &disp[1];
*disp = imm32; *disp = imm32;
} }
...@@ -161,7 +163,6 @@ class MacroAssembler: public Assembler { ...@@ -161,7 +163,6 @@ class MacroAssembler: public Assembler {
void incrementq(Register reg, int value = 1); void incrementq(Register reg, int value = 1);
void incrementq(Address dst, int value = 1); void incrementq(Address dst, int value = 1);
// Support optimal SSE move instructions. // Support optimal SSE move instructions.
void movflt(XMMRegister dst, XMMRegister src) { void movflt(XMMRegister dst, XMMRegister src) {
if (UseXmmRegToRegMoveAll) { movaps(dst, src); return; } if (UseXmmRegToRegMoveAll) { movaps(dst, src); return; }
...@@ -187,6 +188,8 @@ class MacroAssembler: public Assembler { ...@@ -187,6 +188,8 @@ class MacroAssembler: public Assembler {
void incrementl(AddressLiteral dst); void incrementl(AddressLiteral dst);
void incrementl(ArrayAddress dst); void incrementl(ArrayAddress dst);
void incrementq(AddressLiteral dst);
// Alignment // Alignment
void align(int modulus); void align(int modulus);
...@@ -651,7 +654,40 @@ class MacroAssembler: public Assembler { ...@@ -651,7 +654,40 @@ class MacroAssembler: public Assembler {
Label& done, Label* slow_case = NULL, Label& done, Label* slow_case = NULL,
BiasedLockingCounters* counters = NULL); BiasedLockingCounters* counters = NULL);
void biased_locking_exit (Register obj_reg, Register temp_reg, Label& done); void biased_locking_exit (Register obj_reg, Register temp_reg, Label& done);
#ifdef COMPILER2
// Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file.
// See full desription in macroAssembler_x86.cpp.
void fast_lock(Register obj, Register box, Register tmp,
Register scr, Register cx1, Register cx2,
BiasedLockingCounters* counters,
RTMLockingCounters* rtm_counters,
RTMLockingCounters* stack_rtm_counters,
Metadata* method_data,
bool use_rtm, bool profile_rtm);
void fast_unlock(Register obj, Register box, Register tmp, bool use_rtm);
#if INCLUDE_RTM_OPT
void rtm_counters_update(Register abort_status, Register rtm_counters);
void branch_on_random_using_rdtsc(Register tmp, Register scr, int count, Label& brLabel);
void rtm_abort_ratio_calculation(Register tmp, Register rtm_counters_reg,
RTMLockingCounters* rtm_counters,
Metadata* method_data);
void rtm_profiling(Register abort_status_Reg, Register rtm_counters_Reg,
RTMLockingCounters* rtm_counters, Metadata* method_data, bool profile_rtm);
void rtm_retry_lock_on_abort(Register retry_count, Register abort_status, Label& retryLabel);
void rtm_retry_lock_on_busy(Register retry_count, Register box, Register tmp, Register scr, Label& retryLabel);
void rtm_stack_locking(Register obj, Register tmp, Register scr,
Register retry_on_abort_count,
RTMLockingCounters* stack_rtm_counters,
Metadata* method_data, bool profile_rtm,
Label& DONE_LABEL, Label& IsInflated);
void rtm_inflated_locking(Register obj, Register box, Register tmp,
Register scr, Register retry_on_busy_count,
Register retry_on_abort_count,
RTMLockingCounters* rtm_counters,
Metadata* method_data, bool profile_rtm,
Label& DONE_LABEL);
#endif
#endif
Condition negate_condition(Condition cond); Condition negate_condition(Condition cond);
...@@ -716,6 +752,7 @@ class MacroAssembler: public Assembler { ...@@ -716,6 +752,7 @@ class MacroAssembler: public Assembler {
void imulptr(Register dst, Register src) { LP64_ONLY(imulq(dst, src)) NOT_LP64(imull(dst, src)); } void imulptr(Register dst, Register src) { LP64_ONLY(imulq(dst, src)) NOT_LP64(imull(dst, src)); }
void imulptr(Register dst, Register src, int imm32) { LP64_ONLY(imulq(dst, src, imm32)) NOT_LP64(imull(dst, src, imm32)); }
void negptr(Register dst) { LP64_ONLY(negq(dst)) NOT_LP64(negl(dst)); } void negptr(Register dst) { LP64_ONLY(negq(dst)) NOT_LP64(negl(dst)); }
...@@ -757,7 +794,14 @@ class MacroAssembler: public Assembler { ...@@ -757,7 +794,14 @@ class MacroAssembler: public Assembler {
// Conditionally (atomically, on MPs) increments passed counter address, preserving condition codes. // Conditionally (atomically, on MPs) increments passed counter address, preserving condition codes.
void cond_inc32(Condition cond, AddressLiteral counter_addr); void cond_inc32(Condition cond, AddressLiteral counter_addr);
// Unconditional atomic increment. // Unconditional atomic increment.
void atomic_incl(AddressLiteral counter_addr); void atomic_incl(Address counter_addr);
void atomic_incl(AddressLiteral counter_addr, Register scr = rscratch1);
#ifdef _LP64
void atomic_incq(Address counter_addr);
void atomic_incq(AddressLiteral counter_addr, Register scr = rscratch1);
#endif
void atomic_incptr(AddressLiteral counter_addr, Register scr = rscratch1) { LP64_ONLY(atomic_incq(counter_addr, scr)) NOT_LP64(atomic_incl(counter_addr, scr)) ; }
void atomic_incptr(Address counter_addr) { LP64_ONLY(atomic_incq(counter_addr)) NOT_LP64(atomic_incl(counter_addr)) ; }
void lea(Register dst, AddressLiteral adr); void lea(Register dst, AddressLiteral adr);
void lea(Address dst, AddressLiteral adr); void lea(Address dst, AddressLiteral adr);
...@@ -1069,7 +1113,11 @@ public: ...@@ -1069,7 +1113,11 @@ public:
void movptr(Register dst, Address src); void movptr(Register dst, Address src);
void movptr(Register dst, AddressLiteral src); #ifdef _LP64
void movptr(Register dst, AddressLiteral src, Register scratch=rscratch1);
#else
void movptr(Register dst, AddressLiteral src, Register scratch=noreg); // Scratch reg is ignored in 32-bit
#endif
void movptr(Register dst, intptr_t src); void movptr(Register dst, intptr_t src);
void movptr(Register dst, Register src); void movptr(Register dst, Register src);
......
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/task.hpp"
#include "runtime/rtmLocking.hpp"
// One-shot PeriodicTask subclass for enabling RTM locking
uintx RTMLockingCounters::_calculation_flag = 0;
class RTMLockingCalculationTask : public PeriodicTask {
public:
RTMLockingCalculationTask(size_t interval_time) : PeriodicTask(interval_time){ }
virtual void task() {
RTMLockingCounters::_calculation_flag = 1;
// Reclaim our storage and disenroll ourself
delete this;
}
};
void RTMLockingCounters::init() {
if (UseRTMLocking && RTMLockingCalculationDelay > 0) {
RTMLockingCalculationTask* task = new RTMLockingCalculationTask(RTMLockingCalculationDelay);
task->enroll();
} else {
_calculation_flag = 1;
}
}
//------------------------------print_on-------------------------------
void RTMLockingCounters::print_on(outputStream* st) {
tty->print_cr("# rtm locks total (estimated): " UINTX_FORMAT, _total_count * RTMTotalCountIncrRate);
tty->print_cr("# rtm lock aborts : " UINTX_FORMAT, _abort_count);
for (int i = 0; i < ABORT_STATUS_LIMIT; i++) {
tty->print_cr("# rtm lock aborts %d: " UINTX_FORMAT, i, _abortX_count[i]);
}
}
...@@ -1817,6 +1817,13 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, ...@@ -1817,6 +1817,13 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Frame is now completed as far as size and linkage. // Frame is now completed as far as size and linkage.
int frame_complete = ((intptr_t)__ pc()) - start; int frame_complete = ((intptr_t)__ pc()) - start;
if (UseRTMLocking) {
// Abort RTM transaction before calling JNI
// because critical section will be large and will be
// aborted anyway. Also nmethod could be deoptimized.
__ xabort(0);
}
// Calculate the difference between rsp and rbp,. We need to know it // Calculate the difference between rsp and rbp,. We need to know it
// after the native call because on windows Java Natives will pop // after the native call because on windows Java Natives will pop
// the arguments and it is painful to do rsp relative addressing // the arguments and it is painful to do rsp relative addressing
...@@ -3170,6 +3177,12 @@ void SharedRuntime::generate_uncommon_trap_blob() { ...@@ -3170,6 +3177,12 @@ void SharedRuntime::generate_uncommon_trap_blob() {
}; };
address start = __ pc(); address start = __ pc();
if (UseRTMLocking) {
// Abort RTM transaction before possible nmethod deoptimization.
__ xabort(0);
}
// Push self-frame. // Push self-frame.
__ subptr(rsp, return_off*wordSize); // Epilog! __ subptr(rsp, return_off*wordSize); // Epilog!
...@@ -3355,6 +3368,14 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t ...@@ -3355,6 +3368,14 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
address call_pc = NULL; address call_pc = NULL;
bool cause_return = (poll_type == POLL_AT_RETURN); bool cause_return = (poll_type == POLL_AT_RETURN);
bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP); bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP);
if (UseRTMLocking) {
// Abort RTM transaction before calling runtime
// because critical section will be large and will be
// aborted anyway. Also nmethod could be deoptimized.
__ xabort(0);
}
// If cause_return is true we are at a poll_return and there is // If cause_return is true we are at a poll_return and there is
// the return address on the stack to the caller on the nmethod // the return address on the stack to the caller on the nmethod
// that is safepoint. We can leave this return on the stack and // that is safepoint. We can leave this return on the stack and
......
...@@ -2012,6 +2012,13 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, ...@@ -2012,6 +2012,13 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Frame is now completed as far as size and linkage. // Frame is now completed as far as size and linkage.
int frame_complete = ((intptr_t)__ pc()) - start; int frame_complete = ((intptr_t)__ pc()) - start;
if (UseRTMLocking) {
// Abort RTM transaction before calling JNI
// because critical section will be large and will be
// aborted anyway. Also nmethod could be deoptimized.
__ xabort(0);
}
#ifdef ASSERT #ifdef ASSERT
{ {
Label L; Label L;
...@@ -3612,6 +3619,11 @@ void SharedRuntime::generate_uncommon_trap_blob() { ...@@ -3612,6 +3619,11 @@ void SharedRuntime::generate_uncommon_trap_blob() {
address start = __ pc(); address start = __ pc();
if (UseRTMLocking) {
// Abort RTM transaction before possible nmethod deoptimization.
__ xabort(0);
}
// Push self-frame. We get here with a return address on the // Push self-frame. We get here with a return address on the
// stack, so rsp is 8-byte aligned until we allocate our frame. // stack, so rsp is 8-byte aligned until we allocate our frame.
__ subptr(rsp, SimpleRuntimeFrame::return_off << LogBytesPerInt); // Epilog! __ subptr(rsp, SimpleRuntimeFrame::return_off << LogBytesPerInt); // Epilog!
...@@ -3792,6 +3804,13 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t ...@@ -3792,6 +3804,13 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
bool cause_return = (poll_type == POLL_AT_RETURN); bool cause_return = (poll_type == POLL_AT_RETURN);
bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP); bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP);
if (UseRTMLocking) {
// Abort RTM transaction before calling runtime
// because critical section will be large and will be
// aborted anyway. Also nmethod could be deoptimized.
__ xabort(0);
}
// Make room for return address (or push it again) // Make room for return address (or push it again)
if (!cause_return) { if (!cause_return) {
__ push(rbx); __ push(rbx);
......
...@@ -50,8 +50,13 @@ int VM_Version::_cpuFeatures; ...@@ -50,8 +50,13 @@ int VM_Version::_cpuFeatures;
const char* VM_Version::_features_str = ""; const char* VM_Version::_features_str = "";
VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, }; VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, };
// Address of instruction which causes SEGV
address VM_Version::_cpuinfo_segv_addr = 0;
// Address of instruction after the one which causes SEGV
address VM_Version::_cpuinfo_cont_addr = 0;
static BufferBlob* stub_blob; static BufferBlob* stub_blob;
static const int stub_size = 550; static const int stub_size = 600;
extern "C" { extern "C" {
typedef void (*getPsrInfo_stub_t)(void*); typedef void (*getPsrInfo_stub_t)(void*);
...@@ -234,9 +239,9 @@ class VM_Version_StubGenerator: public StubCodeGenerator { ...@@ -234,9 +239,9 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
// Check if OS has enabled XGETBV instruction to access XCR0 // Check if OS has enabled XGETBV instruction to access XCR0
// (OSXSAVE feature flag) and CPU supports AVX // (OSXSAVE feature flag) and CPU supports AVX
// //
__ andl(rcx, 0x18000000); __ andl(rcx, 0x18000000); // cpuid1 bits osxsave | avx
__ cmpl(rcx, 0x18000000); __ cmpl(rcx, 0x18000000);
__ jccb(Assembler::notEqual, sef_cpuid); __ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported
// //
// XCR0, XFEATURE_ENABLED_MASK register // XCR0, XFEATURE_ENABLED_MASK register
...@@ -247,6 +252,47 @@ class VM_Version_StubGenerator: public StubCodeGenerator { ...@@ -247,6 +252,47 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 0), rax);
__ movl(Address(rsi, 4), rdx); __ movl(Address(rsi, 4), rdx);
__ andl(rax, 0x6); // xcr0 bits sse | ymm
__ cmpl(rax, 0x6);
__ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported
//
// Some OSs have a bug when upper 128bits of YMM
// registers are not restored after a signal processing.
// Generate SEGV here (reference through NULL)
// and check upper YMM bits after it.
//
VM_Version::set_avx_cpuFeatures(); // Enable temporary to pass asserts
// load value into all 32 bytes of ymm7 register
__ movl(rcx, VM_Version::ymm_test_value());
__ movdl(xmm0, rcx);
__ pshufd(xmm0, xmm0, 0x00);
__ vinsertf128h(xmm0, xmm0, xmm0);
__ vmovdqu(xmm7, xmm0);
#ifdef _LP64
__ vmovdqu(xmm8, xmm0);
__ vmovdqu(xmm15, xmm0);
#endif
__ xorl(rsi, rsi);
VM_Version::set_cpuinfo_segv_addr( __ pc() );
// Generate SEGV
__ movl(rax, Address(rsi, 0));
VM_Version::set_cpuinfo_cont_addr( __ pc() );
// Returns here after signal. Save xmm0 to check it later.
__ lea(rsi, Address(rbp, in_bytes(VM_Version::ymm_save_offset())));
__ vmovdqu(Address(rsi, 0), xmm0);
__ vmovdqu(Address(rsi, 32), xmm7);
#ifdef _LP64
__ vmovdqu(Address(rsi, 64), xmm8);
__ vmovdqu(Address(rsi, 96), xmm15);
#endif
VM_Version::clean_cpuFeatures();
// //
// cpuid(0x7) Structured Extended Features // cpuid(0x7) Structured Extended Features
// //
...@@ -429,7 +475,7 @@ void VM_Version::get_processor_features() { ...@@ -429,7 +475,7 @@ void VM_Version::get_processor_features() {
} }
char buf[256]; char buf[256];
jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
cores_per_cpu(), threads_per_core(), cores_per_cpu(), threads_per_core(),
cpu_family(), _model, _stepping, cpu_family(), _model, _stepping,
(supports_cmov() ? ", cmov" : ""), (supports_cmov() ? ", cmov" : ""),
...@@ -446,8 +492,9 @@ void VM_Version::get_processor_features() { ...@@ -446,8 +492,9 @@ void VM_Version::get_processor_features() {
(supports_avx() ? ", avx" : ""), (supports_avx() ? ", avx" : ""),
(supports_avx2() ? ", avx2" : ""), (supports_avx2() ? ", avx2" : ""),
(supports_aes() ? ", aes" : ""), (supports_aes() ? ", aes" : ""),
(supports_clmul() ? ", clmul" : ""), (supports_clmul() ? ", clmul" : ""),
(supports_erms() ? ", erms" : ""), (supports_erms() ? ", erms" : ""),
(supports_rtm() ? ", rtm" : ""),
(supports_mmx_ext() ? ", mmxext" : ""), (supports_mmx_ext() ? ", mmxext" : ""),
(supports_3dnow_prefetch() ? ", 3dnowpref" : ""), (supports_3dnow_prefetch() ? ", 3dnowpref" : ""),
(supports_lzcnt() ? ", lzcnt": ""), (supports_lzcnt() ? ", lzcnt": ""),
...@@ -455,7 +502,9 @@ void VM_Version::get_processor_features() { ...@@ -455,7 +502,9 @@ void VM_Version::get_processor_features() {
(supports_ht() ? ", ht": ""), (supports_ht() ? ", ht": ""),
(supports_tsc() ? ", tsc": ""), (supports_tsc() ? ", tsc": ""),
(supports_tscinv_bit() ? ", tscinvbit": ""), (supports_tscinv_bit() ? ", tscinvbit": ""),
(supports_tscinv() ? ", tscinv": "")); (supports_tscinv() ? ", tscinv": ""),
(supports_bmi1() ? ", bmi1" : ""),
(supports_bmi2() ? ", bmi2" : ""));
_features_str = strdup(buf); _features_str = strdup(buf);
// UseSSE is set to the smaller of what hardware supports and what // UseSSE is set to the smaller of what hardware supports and what
...@@ -486,7 +535,7 @@ void VM_Version::get_processor_features() { ...@@ -486,7 +535,7 @@ void VM_Version::get_processor_features() {
} }
} else if (UseAES) { } else if (UseAES) {
if (!FLAG_IS_DEFAULT(UseAES)) if (!FLAG_IS_DEFAULT(UseAES))
warning("AES instructions not available on this CPU"); warning("AES instructions are not available on this CPU");
FLAG_SET_DEFAULT(UseAES, false); FLAG_SET_DEFAULT(UseAES, false);
} }
...@@ -519,10 +568,57 @@ void VM_Version::get_processor_features() { ...@@ -519,10 +568,57 @@ void VM_Version::get_processor_features() {
} }
} else if (UseAESIntrinsics) { } else if (UseAESIntrinsics) {
if (!FLAG_IS_DEFAULT(UseAESIntrinsics)) if (!FLAG_IS_DEFAULT(UseAESIntrinsics))
warning("AES intrinsics not available on this CPU"); warning("AES intrinsics are not available on this CPU");
FLAG_SET_DEFAULT(UseAESIntrinsics, false); FLAG_SET_DEFAULT(UseAESIntrinsics, false);
} }
// Adjust RTM (Restricted Transactional Memory) flags
if (!supports_rtm() && UseRTMLocking) {
// Can't continue because UseRTMLocking affects UseBiasedLocking flag
// setting during arguments processing. See use_biased_locking().
// VM_Version_init() is executed after UseBiasedLocking is used
// in Thread::allocate().
vm_exit_during_initialization("RTM instructions are not available on this CPU");
}
#if INCLUDE_RTM_OPT
if (UseRTMLocking) {
if (!FLAG_IS_CMDLINE(UseRTMLocking)) {
// RTM locking should be used only for applications with
// high lock contention. For now we do not use it by default.
vm_exit_during_initialization("UseRTMLocking flag should be only set on command line");
}
if (!is_power_of_2(RTMTotalCountIncrRate)) {
warning("RTMTotalCountIncrRate must be a power of 2, resetting it to 64");
FLAG_SET_DEFAULT(RTMTotalCountIncrRate, 64);
}
if (RTMAbortRatio < 0 || RTMAbortRatio > 100) {
warning("RTMAbortRatio must be in the range 0 to 100, resetting it to 50");
FLAG_SET_DEFAULT(RTMAbortRatio, 50);
}
} else { // !UseRTMLocking
if (UseRTMForStackLocks) {
if (!FLAG_IS_DEFAULT(UseRTMForStackLocks)) {
warning("UseRTMForStackLocks flag should be off when UseRTMLocking flag is off");
}
FLAG_SET_DEFAULT(UseRTMForStackLocks, false);
}
if (UseRTMDeopt) {
FLAG_SET_DEFAULT(UseRTMDeopt, false);
}
if (PrintPreciseRTMLockingStatistics) {
FLAG_SET_DEFAULT(PrintPreciseRTMLockingStatistics, false);
}
}
#else
if (UseRTMLocking) {
// Only C2 does RTM locking optimization.
// Can't continue because UseRTMLocking affects UseBiasedLocking flag
// setting during arguments processing. See use_biased_locking().
vm_exit_during_initialization("RTM locking optimization is not supported in this VM");
}
#endif
#ifdef COMPILER2 #ifdef COMPILER2
if (UseFPUForSpilling) { if (UseFPUForSpilling) {
if (UseSSE < 2) { if (UseSSE < 2) {
...@@ -538,14 +634,28 @@ void VM_Version::get_processor_features() { ...@@ -538,14 +634,28 @@ void VM_Version::get_processor_features() {
if (MaxVectorSize > 32) { if (MaxVectorSize > 32) {
FLAG_SET_DEFAULT(MaxVectorSize, 32); FLAG_SET_DEFAULT(MaxVectorSize, 32);
} }
if (MaxVectorSize > 16 && UseAVX == 0) { if (MaxVectorSize > 16 && (UseAVX == 0 || !os_supports_avx_vectors())) {
// Only supported with AVX+ // 32 bytes vectors (in YMM) are only supported with AVX+
FLAG_SET_DEFAULT(MaxVectorSize, 16); FLAG_SET_DEFAULT(MaxVectorSize, 16);
} }
if (UseSSE < 2) { if (UseSSE < 2) {
// Only supported with SSE2+ // Vectors (in XMM) are only supported with SSE2+
FLAG_SET_DEFAULT(MaxVectorSize, 0); FLAG_SET_DEFAULT(MaxVectorSize, 0);
} }
#ifdef ASSERT
if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) {
tty->print_cr("State of YMM registers after signal handle:");
int nreg = 2 LP64_ONLY(+2);
const char* ymm_name[4] = {"0", "7", "8", "15"};
for (int i = 0; i < nreg; i++) {
tty->print("YMM%s:", ymm_name[i]);
for (int j = 7; j >=0; j--) {
tty->print(" %x", _cpuid_info.ymm_save[i*8 + j]);
}
tty->cr();
}
}
#endif
} }
#endif #endif
...@@ -600,13 +710,6 @@ void VM_Version::get_processor_features() { ...@@ -600,13 +710,6 @@ void VM_Version::get_processor_features() {
} }
} }
// Use count leading zeros count instruction if available.
if (supports_lzcnt()) {
if (FLAG_IS_DEFAULT(UseCountLeadingZerosInstruction)) {
UseCountLeadingZerosInstruction = true;
}
}
// some defaults for AMD family 15h // some defaults for AMD family 15h
if ( cpu_family() == 0x15 ) { if ( cpu_family() == 0x15 ) {
// On family 15h processors default is no sw prefetch // On family 15h processors default is no sw prefetch
...@@ -683,14 +786,35 @@ void VM_Version::get_processor_features() { ...@@ -683,14 +786,35 @@ void VM_Version::get_processor_features() {
} }
} }
} }
#if defined(COMPILER2) && defined(_ALLBSD_SOURCE)
if (MaxVectorSize > 16) { // Use count leading zeros count instruction if available.
// Limit vectors size to 16 bytes on BSD until it fixes if (supports_lzcnt()) {
// restoring upper 128bit of YMM registers on return if (FLAG_IS_DEFAULT(UseCountLeadingZerosInstruction)) {
// from signal handler. UseCountLeadingZerosInstruction = true;
FLAG_SET_DEFAULT(MaxVectorSize, 16);
} }
#endif // COMPILER2 } else if (UseCountLeadingZerosInstruction) {
warning("lzcnt instruction is not available on this CPU");
FLAG_SET_DEFAULT(UseCountLeadingZerosInstruction, false);
}
if (supports_bmi1()) {
if (FLAG_IS_DEFAULT(UseBMI1Instructions)) {
UseBMI1Instructions = true;
}
} else if (UseBMI1Instructions) {
warning("BMI1 instructions are not available on this CPU");
FLAG_SET_DEFAULT(UseBMI1Instructions, false);
}
// Use count trailing zeros instruction if available
if (supports_bmi1()) {
if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstruction)) {
UseCountTrailingZerosInstruction = UseBMI1Instructions;
}
} else if (UseCountTrailingZerosInstruction) {
warning("tzcnt instruction is not available on this CPU");
FLAG_SET_DEFAULT(UseCountTrailingZerosInstruction, false);
}
// Use population count instruction if available. // Use population count instruction if available.
if (supports_popcnt()) { if (supports_popcnt()) {
...@@ -790,6 +914,11 @@ void VM_Version::get_processor_features() { ...@@ -790,6 +914,11 @@ void VM_Version::get_processor_features() {
if (UseAES) { if (UseAES) {
tty->print(" UseAES=1"); tty->print(" UseAES=1");
} }
#ifdef COMPILER2
if (MaxVectorSize > 0) {
tty->print(" MaxVectorSize=%d", MaxVectorSize);
}
#endif
tty->cr(); tty->cr();
tty->print("Allocation"); tty->print("Allocation");
if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) { if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) {
...@@ -832,6 +961,27 @@ void VM_Version::get_processor_features() { ...@@ -832,6 +961,27 @@ void VM_Version::get_processor_features() {
#endif // !PRODUCT #endif // !PRODUCT
} }
bool VM_Version::use_biased_locking() {
#if INCLUDE_RTM_OPT
// RTM locking is most useful when there is high lock contention and
// low data contention. With high lock contention the lock is usually
// inflated and biased locking is not suitable for that case.
// RTM locking code requires that biased locking is off.
// Note: we can't switch off UseBiasedLocking in get_processor_features()
// because it is used by Thread::allocate() which is called before
// VM_Version::initialize().
if (UseRTMLocking && UseBiasedLocking) {
if (FLAG_IS_DEFAULT(UseBiasedLocking)) {
FLAG_SET_DEFAULT(UseBiasedLocking, false);
} else {
warning("Biased locking is not supported with RTM locking; ignoring UseBiasedLocking flag." );
UseBiasedLocking = false;
}
}
#endif
return UseBiasedLocking;
}
void VM_Version::initialize() { void VM_Version::initialize() {
ResourceMark rm; ResourceMark rm;
// Making this stub must be FIRST use of assembler // Making this stub must be FIRST use of assembler
......
...@@ -141,7 +141,8 @@ public: ...@@ -141,7 +141,8 @@ public:
struct { struct {
uint32_t LahfSahf : 1, uint32_t LahfSahf : 1,
CmpLegacy : 1, CmpLegacy : 1,
: 4, : 3,
lzcnt_intel : 1,
lzcnt : 1, lzcnt : 1,
sse4a : 1, sse4a : 1,
misalignsse : 1, misalignsse : 1,
...@@ -206,7 +207,9 @@ public: ...@@ -206,7 +207,9 @@ public:
: 2, : 2,
bmi2 : 1, bmi2 : 1,
erms : 1, erms : 1,
: 22; : 1,
rtm : 1,
: 20;
} bits; } bits;
}; };
...@@ -228,6 +231,9 @@ protected: ...@@ -228,6 +231,9 @@ protected:
// 0 if this instruction is not available // 0 if this instruction is not available
static const char* _features_str; static const char* _features_str;
static address _cpuinfo_segv_addr; // address of instruction which causes SEGV
static address _cpuinfo_cont_addr; // address of instruction after the one which causes SEGV
enum { enum {
CPU_CX8 = (1 << 0), // next bits are from cpuid 1 (EDX) CPU_CX8 = (1 << 0), // next bits are from cpuid 1 (EDX)
CPU_CMOV = (1 << 1), CPU_CMOV = (1 << 1),
...@@ -251,7 +257,10 @@ protected: ...@@ -251,7 +257,10 @@ protected:
CPU_AVX2 = (1 << 18), CPU_AVX2 = (1 << 18),
CPU_AES = (1 << 19), CPU_AES = (1 << 19),
CPU_ERMS = (1 << 20), // enhanced 'rep movsb/stosb' instructions CPU_ERMS = (1 << 20), // enhanced 'rep movsb/stosb' instructions
CPU_CLMUL = (1 << 21) // carryless multiply for CRC CPU_CLMUL = (1 << 21), // carryless multiply for CRC
CPU_BMI1 = (1 << 22),
CPU_BMI2 = (1 << 23),
CPU_RTM = (1 << 24) // Restricted Transactional Memory instructions
} cpuFeatureFlags; } cpuFeatureFlags;
enum { enum {
...@@ -358,6 +367,9 @@ protected: ...@@ -358,6 +367,9 @@ protected:
// extended control register XCR0 (the XFEATURE_ENABLED_MASK register) // extended control register XCR0 (the XFEATURE_ENABLED_MASK register)
XemXcr0Eax xem_xcr0_eax; XemXcr0Eax xem_xcr0_eax;
uint32_t xem_xcr0_edx; // reserved uint32_t xem_xcr0_edx; // reserved
// Space to save ymm registers after signal handle
int ymm_save[8*4]; // Save ymm0, ymm7, ymm8, ymm15
}; };
// The actual cpuid info block // The actual cpuid info block
...@@ -423,6 +435,8 @@ protected: ...@@ -423,6 +435,8 @@ protected:
if (_cpuid_info.sef_cpuid7_ebx.bits.avx2 != 0) if (_cpuid_info.sef_cpuid7_ebx.bits.avx2 != 0)
result |= CPU_AVX2; result |= CPU_AVX2;
} }
if(_cpuid_info.sef_cpuid7_ebx.bits.bmi1 != 0)
result |= CPU_BMI1;
if (_cpuid_info.std_cpuid1_edx.bits.tsc != 0) if (_cpuid_info.std_cpuid1_edx.bits.tsc != 0)
result |= CPU_TSC; result |= CPU_TSC;
if (_cpuid_info.ext_cpuid7_edx.bits.tsc_invariance != 0) if (_cpuid_info.ext_cpuid7_edx.bits.tsc_invariance != 0)
...@@ -433,6 +447,8 @@ protected: ...@@ -433,6 +447,8 @@ protected:
result |= CPU_ERMS; result |= CPU_ERMS;
if (_cpuid_info.std_cpuid1_ecx.bits.clmul != 0) if (_cpuid_info.std_cpuid1_ecx.bits.clmul != 0)
result |= CPU_CLMUL; result |= CPU_CLMUL;
if (_cpuid_info.sef_cpuid7_ebx.bits.rtm != 0)
result |= CPU_RTM;
// AMD features. // AMD features.
if (is_amd()) { if (is_amd()) {
...@@ -444,10 +460,32 @@ protected: ...@@ -444,10 +460,32 @@ protected:
if (_cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0) if (_cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0)
result |= CPU_SSE4A; result |= CPU_SSE4A;
} }
// Intel features.
if(is_intel()) {
if(_cpuid_info.sef_cpuid7_ebx.bits.bmi2 != 0)
result |= CPU_BMI2;
if(_cpuid_info.ext_cpuid1_ecx.bits.lzcnt_intel != 0)
result |= CPU_LZCNT;
}
return result; return result;
} }
static bool os_supports_avx_vectors() {
if (!supports_avx()) {
return false;
}
// Verify that OS save/restore all bits of AVX registers
// during signal processing.
int nreg = 2 LP64_ONLY(+2);
for (int i = 0; i < 8 * nreg; i++) { // 32 bytes per ymm register
if (_cpuid_info.ymm_save[i] != ymm_test_value()) {
return false;
}
}
return true;
}
static void get_processor_features(); static void get_processor_features();
public: public:
...@@ -464,10 +502,26 @@ public: ...@@ -464,10 +502,26 @@ public:
static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); } static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); }
static ByteSize tpl_cpuidB2_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB2_eax); } static ByteSize tpl_cpuidB2_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB2_eax); }
static ByteSize xem_xcr0_offset() { return byte_offset_of(CpuidInfo, xem_xcr0_eax); } static ByteSize xem_xcr0_offset() { return byte_offset_of(CpuidInfo, xem_xcr0_eax); }
static ByteSize ymm_save_offset() { return byte_offset_of(CpuidInfo, ymm_save); }
// The value used to check ymm register after signal handle
static int ymm_test_value() { return 0xCAFEBABE; }
static void set_cpuinfo_segv_addr(address pc) { _cpuinfo_segv_addr = pc; }
static bool is_cpuinfo_segv_addr(address pc) { return _cpuinfo_segv_addr == pc; }
static void set_cpuinfo_cont_addr(address pc) { _cpuinfo_cont_addr = pc; }
static address cpuinfo_cont_addr() { return _cpuinfo_cont_addr; }
static void clean_cpuFeatures() { _cpuFeatures = 0; }
static void set_avx_cpuFeatures() { _cpuFeatures = (CPU_SSE | CPU_SSE2 | CPU_AVX); }
// Initialization // Initialization
static void initialize(); static void initialize();
// Override Abstract_VM_Version implementation
static bool use_biased_locking();
// Asserts // Asserts
static void assert_is_initialized() { static void assert_is_initialized() {
assert(_cpuid_info.std_cpuid1_eax.bits.family != 0, "VM_Version not initialized"); assert(_cpuid_info.std_cpuid1_eax.bits.family != 0, "VM_Version not initialized");
...@@ -560,7 +614,9 @@ public: ...@@ -560,7 +614,9 @@ public:
static bool supports_aes() { return (_cpuFeatures & CPU_AES) != 0; } static bool supports_aes() { return (_cpuFeatures & CPU_AES) != 0; }
static bool supports_erms() { return (_cpuFeatures & CPU_ERMS) != 0; } static bool supports_erms() { return (_cpuFeatures & CPU_ERMS) != 0; }
static bool supports_clmul() { return (_cpuFeatures & CPU_CLMUL) != 0; } static bool supports_clmul() { return (_cpuFeatures & CPU_CLMUL) != 0; }
static bool supports_rtm() { return (_cpuFeatures & CPU_RTM) != 0; }
static bool supports_bmi1() { return (_cpuFeatures & CPU_BMI1) != 0; }
static bool supports_bmi2() { return (_cpuFeatures & CPU_BMI2) != 0; }
// Intel features // Intel features
static bool is_intel_family_core() { return is_intel() && static bool is_intel_family_core() { return is_intel() &&
extended_cpu_family() == CPU_FAMILY_INTEL_CORE; } extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
......
此差异已折叠。
此差异已折叠。
...@@ -2590,9 +2590,21 @@ int os::sleep(Thread* thread, jlong millis, bool interruptible) { ...@@ -2590,9 +2590,21 @@ int os::sleep(Thread* thread, jlong millis, bool interruptible) {
} }
} }
int os::naked_sleep() { void os::naked_short_sleep(jlong ms) {
// %% make the sleep time an integer flag. for now use 1 millisec. struct timespec req;
return os::sleep(Thread::current(), 1, false);
assert(ms < 1000, "Un-interruptable sleep, short time use only");
req.tv_sec = 0;
if (ms > 0) {
req.tv_nsec = (ms % 1000) * 1000000;
}
else {
req.tv_nsec = 1;
}
nanosleep(&req, NULL);
return;
} }
// Sleep forever; naked call to OS-specific sleep; use with CAUTION // Sleep forever; naked call to OS-specific sleep; use with CAUTION
......
/* /*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -109,6 +109,8 @@ ...@@ -109,6 +109,8 @@
#define MAX_PATH (2 * K) #define MAX_PATH (2 * K)
#define MAX_SECS 100000000
// for timer info max values which include all bits // for timer info max values which include all bits
#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
...@@ -2433,7 +2435,6 @@ class Semaphore : public StackObj { ...@@ -2433,7 +2435,6 @@ class Semaphore : public StackObj {
sem_t _semaphore; sem_t _semaphore;
}; };
Semaphore::Semaphore() { Semaphore::Semaphore() {
sem_init(&_semaphore, 0, 0); sem_init(&_semaphore, 0, 0);
} }
...@@ -2455,8 +2456,22 @@ bool Semaphore::trywait() { ...@@ -2455,8 +2456,22 @@ bool Semaphore::trywait() {
} }
bool Semaphore::timedwait(unsigned int sec, int nsec) { bool Semaphore::timedwait(unsigned int sec, int nsec) {
struct timespec ts; struct timespec ts;
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); // Semaphore's are always associated with CLOCK_REALTIME
os::Linux::clock_gettime(CLOCK_REALTIME, &ts);
// see unpackTime for discussion on overflow checking
if (sec >= MAX_SECS) {
ts.tv_sec += MAX_SECS;
ts.tv_nsec = 0;
} else {
ts.tv_sec += sec;
ts.tv_nsec += nsec;
if (ts.tv_nsec >= NANOSECS_PER_SEC) {
ts.tv_nsec -= NANOSECS_PER_SEC;
++ts.tv_sec; // note: this must be <= max_secs
}
}
while (1) { while (1) {
int result = sem_timedwait(&_semaphore, &ts); int result = sem_timedwait(&_semaphore, &ts);
...@@ -2961,7 +2976,9 @@ address get_stack_commited_bottom(address bottom, size_t size) { ...@@ -2961,7 +2976,9 @@ address get_stack_commited_bottom(address bottom, size_t size) {
unsigned char vec[1]; unsigned char vec[1];
unsigned imin = 1, imax = pages + 1, imid; unsigned imin = 1, imax = pages + 1, imid;
int mincore_return_value; int mincore_return_value = 0;
assert(imin <= imax, "Unexpected page size");
while (imin < imax) { while (imin < imax) {
imid = (imax + imin) / 2; imid = (imax + imin) / 2;
...@@ -3833,9 +3850,33 @@ int os::sleep(Thread* thread, jlong millis, bool interruptible) { ...@@ -3833,9 +3850,33 @@ int os::sleep(Thread* thread, jlong millis, bool interruptible) {
} }
} }
int os::naked_sleep() { //
// %% make the sleep time an integer flag. for now use 1 millisec. // Short sleep, direct OS call.
return os::sleep(Thread::current(), 1, false); //
// Note: certain versions of Linux CFS scheduler (since 2.6.23) do not guarantee
// sched_yield(2) will actually give up the CPU:
//
// * Alone on this pariticular CPU, keeps running.
// * Before the introduction of "skip_buddy" with "compat_yield" disabled
// (pre 2.6.39).
//
// So calling this with 0 is an alternative.
//
void os::naked_short_sleep(jlong ms) {
struct timespec req;
assert(ms < 1000, "Un-interruptable sleep, short time use only");
req.tv_sec = 0;
if (ms > 0) {
req.tv_nsec = (ms % 1000) * 1000000;
}
else {
req.tv_nsec = 1;
}
nanosleep(&req, NULL);
return;
} }
// Sleep forever; naked call to OS-specific sleep; use with CAUTION // Sleep forever; naked call to OS-specific sleep; use with CAUTION
...@@ -5752,7 +5793,6 @@ void os::PlatformEvent::unpark() { ...@@ -5752,7 +5793,6 @@ void os::PlatformEvent::unpark() {
* is no need to track notifications. * is no need to track notifications.
*/ */
#define MAX_SECS 100000000
/* /*
* This code is common to linux and solaris and will be moved to a * This code is common to linux and solaris and will be moved to a
* common place in dolphin. * common place in dolphin.
......
/* /*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -891,8 +891,16 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor ...@@ -891,8 +891,16 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
FREE_C_HEAP_ARRAY(char, filename, mtInternal); FREE_C_HEAP_ARRAY(char, filename, mtInternal);
// open the shared memory file for the give vmid // open the shared memory file for the give vmid
fd = open_sharedmem_file(rfilename, file_flags, CHECK); fd = open_sharedmem_file(rfilename, file_flags, THREAD);
assert(fd != OS_ERR, "unexpected value");
if (fd == OS_ERR) {
return;
}
if (HAS_PENDING_EXCEPTION) {
::close(fd);
return;
}
if (*sizep == 0) { if (*sizep == 0) {
size = sharedmem_filesize(fd, CHECK); size = sharedmem_filesize(fd, CHECK);
......
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -2232,8 +2232,8 @@ static bool check_addr0(outputStream* st) { ...@@ -2232,8 +2232,8 @@ static bool check_addr0(outputStream* st) {
st->cr(); st->cr();
status = true; status = true;
} }
::close(fd);
} }
::close(fd);
} }
return status; return status;
} }
...@@ -2967,7 +2967,7 @@ bool os::get_page_info(char *start, page_info* info) { ...@@ -2967,7 +2967,7 @@ bool os::get_page_info(char *start, page_info* info) {
char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info* page_found) { char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info* page_found) {
const uint_t info_types[] = { MEMINFO_VLGRP, MEMINFO_VPAGESIZE }; const uint_t info_types[] = { MEMINFO_VLGRP, MEMINFO_VPAGESIZE };
const size_t types = sizeof(info_types) / sizeof(info_types[0]); const size_t types = sizeof(info_types) / sizeof(info_types[0]);
uint64_t addrs[MAX_MEMINFO_CNT], outdata[types * MAX_MEMINFO_CNT]; uint64_t addrs[MAX_MEMINFO_CNT], outdata[types * MAX_MEMINFO_CNT + 1];
uint_t validity[MAX_MEMINFO_CNT]; uint_t validity[MAX_MEMINFO_CNT];
size_t page_size = MAX2((size_t)os::vm_page_size(), page_expected->size); size_t page_size = MAX2((size_t)os::vm_page_size(), page_expected->size);
...@@ -3006,7 +3006,7 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info ...@@ -3006,7 +3006,7 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info
} }
} }
if (i != addrs_count) { if (i < addrs_count) {
if ((validity[i] & 2) != 0) { if ((validity[i] & 2) != 0) {
page_found->lgrp_id = outdata[types * i]; page_found->lgrp_id = outdata[types * i];
} else { } else {
...@@ -3496,9 +3496,14 @@ int os::sleep(Thread* thread, jlong millis, bool interruptible) { ...@@ -3496,9 +3496,14 @@ int os::sleep(Thread* thread, jlong millis, bool interruptible) {
return os_sleep(millis, interruptible); return os_sleep(millis, interruptible);
} }
int os::naked_sleep() { void os::naked_short_sleep(jlong ms) {
// %% make the sleep time an integer flag. for now use 1 millisec. assert(ms < 1000, "Un-interruptable sleep, short time use only");
return os_sleep(1, false);
// usleep is deprecated and removed from POSIX, in favour of nanosleep, but
// Solaris requires -lrt for this.
usleep((ms * 1000));
return;
} }
// Sleep forever; naked call to OS-specific sleep; use with CAUTION // Sleep forever; naked call to OS-specific sleep; use with CAUTION
......
/* /*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -431,10 +431,12 @@ static char* get_user_name(int vmid, TRAPS) { ...@@ -431,10 +431,12 @@ static char* get_user_name(int vmid, TRAPS) {
RESTARTABLE(::read(fd, addr, remaining), result); RESTARTABLE(::read(fd, addr, remaining), result);
if (result == OS_ERR) { if (result == OS_ERR) {
::close(fd);
THROW_MSG_0(vmSymbols::java_io_IOException(), "Read error"); THROW_MSG_0(vmSymbols::java_io_IOException(), "Read error");
} else {
remaining-=result;
addr+=result;
} }
remaining-=result;
addr+=result;
} }
::close(fd); ::close(fd);
...@@ -906,8 +908,16 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor ...@@ -906,8 +908,16 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
FREE_C_HEAP_ARRAY(char, filename, mtInternal); FREE_C_HEAP_ARRAY(char, filename, mtInternal);
// open the shared memory file for the give vmid // open the shared memory file for the give vmid
fd = open_sharedmem_file(rfilename, file_flags, CHECK); fd = open_sharedmem_file(rfilename, file_flags, THREAD);
assert(fd != OS_ERR, "unexpected value");
if (fd == OS_ERR) {
return;
}
if (HAS_PENDING_EXCEPTION) {
::close(fd);
return;
}
if (*sizep == 0) { if (*sizep == 0) {
size = sharedmem_filesize(fd, CHECK); size = sharedmem_filesize(fd, CHECK);
......
...@@ -2437,6 +2437,12 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { ...@@ -2437,6 +2437,12 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
} }
} }
if ((exception_code == EXCEPTION_ACCESS_VIOLATION) &&
VM_Version::is_cpuinfo_segv_addr(pc)) {
// Verify that OS save/restore AVX registers.
return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr());
}
if (t != NULL && t->is_Java_thread()) { if (t != NULL && t->is_Java_thread()) {
JavaThread* thread = (JavaThread*) t; JavaThread* thread = (JavaThread*) t;
bool in_java = thread->thread_state() == _thread_in_Java; bool in_java = thread->thread_state() == _thread_in_Java;
...@@ -3496,6 +3502,16 @@ int os::sleep(Thread* thread, jlong ms, bool interruptable) { ...@@ -3496,6 +3502,16 @@ int os::sleep(Thread* thread, jlong ms, bool interruptable) {
return result; return result;
} }
//
// Short sleep, direct OS call.
//
// ms = 0, means allow others (if any) to run.
//
void os::naked_short_sleep(jlong ms) {
assert(ms < 1000, "Un-interruptable sleep, short time use only");
Sleep(ms);
}
// Sleep forever; naked call to OS-specific sleep; use with CAUTION // Sleep forever; naked call to OS-specific sleep; use with CAUTION
void os::infinite_sleep() { void os::infinite_sleep() {
while (true) { // sleep forever ... while (true) { // sleep forever ...
...@@ -3623,13 +3639,14 @@ bool os::is_interrupted(Thread* thread, bool clear_interrupted) { ...@@ -3623,13 +3639,14 @@ bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
"possibility of dangling Thread pointer"); "possibility of dangling Thread pointer");
OSThread* osthread = thread->osthread(); OSThread* osthread = thread->osthread();
bool interrupted = osthread->interrupted();
// There is no synchronization between the setting of the interrupt // There is no synchronization between the setting of the interrupt
// and it being cleared here. It is critical - see 6535709 - that // and it being cleared here. It is critical - see 6535709 - that
// we only clear the interrupt state, and reset the interrupt event, // we only clear the interrupt state, and reset the interrupt event,
// if we are going to report that we were indeed interrupted - else // if we are going to report that we were indeed interrupted - else
// an interrupt can be "lost", leading to spurious wakeups or lost wakeups // an interrupt can be "lost", leading to spurious wakeups or lost wakeups
// depending on the timing // depending on the timing. By checking thread interrupt event to see
// if the thread gets real interrupt thus prevent spurious wakeup.
bool interrupted = osthread->interrupted() && (WaitForSingleObject(osthread->interrupt_event(), 0) == WAIT_OBJECT_0);
if (interrupted && clear_interrupted) { if (interrupted && clear_interrupted) {
osthread->set_interrupted(false); osthread->set_interrupted(false);
ResetEvent(osthread->interrupt_event()); ResetEvent(osthread->interrupt_event());
......
...@@ -492,6 +492,11 @@ JVM_handle_bsd_signal(int sig, ...@@ -492,6 +492,11 @@ JVM_handle_bsd_signal(int sig,
} }
} }
if ((sig == SIGSEGV || sig == SIGBUS) && VM_Version::is_cpuinfo_segv_addr(pc)) {
// Verify that OS save/restore AVX registers.
stub = VM_Version::cpuinfo_cont_addr();
}
// We test if stub is already set (by the stack overflow code // We test if stub is already set (by the stack overflow code
// above) so it is not overwritten by the code that follows. This // above) so it is not overwritten by the code that follows. This
// check is not required on other platforms, because on other // check is not required on other platforms, because on other
......
...@@ -337,6 +337,11 @@ JVM_handle_linux_signal(int sig, ...@@ -337,6 +337,11 @@ JVM_handle_linux_signal(int sig,
} }
} }
if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr(pc)) {
// Verify that OS save/restore AVX registers.
stub = VM_Version::cpuinfo_cont_addr();
}
if (thread->thread_state() == _thread_in_Java) { if (thread->thread_state() == _thread_in_Java) {
// Java thread running in Java code => find exception handler if any // Java thread running in Java code => find exception handler if any
// a fault inside compiled code, the interpreter, or a stub // a fault inside compiled code, the interpreter, or a stub
......
/* /*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -459,6 +459,11 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, ...@@ -459,6 +459,11 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
} }
} }
if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr(pc)) {
// Verify that OS save/restore AVX registers.
stub = VM_Version::cpuinfo_cont_addr();
}
if (thread->thread_state() == _thread_in_vm) { if (thread->thread_state() == _thread_in_vm) {
if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) { if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
stub = StubRoutines::handler_for_unsafe_access(); stub = StubRoutines::handler_for_unsafe_access();
...@@ -475,9 +480,11 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, ...@@ -475,9 +480,11 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
// here if the underlying file has been truncated. // here if the underlying file has been truncated.
// Do not crash the VM in such a case. // Do not crash the VM in such a case.
CodeBlob* cb = CodeCache::find_blob_unsafe(pc); CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL; if (cb != NULL) {
if (nm != NULL && nm->has_unsafe_access()) { nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL;
stub = StubRoutines::handler_for_unsafe_access(); if (nm != NULL && nm->has_unsafe_access()) {
stub = StubRoutines::handler_for_unsafe_access();
}
} }
} }
else else
...@@ -724,6 +731,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, ...@@ -724,6 +731,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
err.report_and_die(); err.report_and_die();
ShouldNotReachHere(); ShouldNotReachHere();
return false;
} }
void os::print_context(outputStream *st, void *context) { void os::print_context(outputStream *st, void *context) {
......
...@@ -1193,15 +1193,12 @@ void ArchDesc::buildMustCloneMap(FILE *fp_hpp, FILE *fp_cpp) { ...@@ -1193,15 +1193,12 @@ void ArchDesc::buildMustCloneMap(FILE *fp_hpp, FILE *fp_cpp) {
|| strcmp(idealName,"CmpF") == 0 || strcmp(idealName,"CmpF") == 0
|| strcmp(idealName,"FastLock") == 0 || strcmp(idealName,"FastLock") == 0
|| strcmp(idealName,"FastUnlock") == 0 || strcmp(idealName,"FastUnlock") == 0
|| strcmp(idealName,"AddExactI") == 0 || strcmp(idealName,"OverflowAddI") == 0
|| strcmp(idealName,"AddExactL") == 0 || strcmp(idealName,"OverflowAddL") == 0
|| strcmp(idealName,"SubExactI") == 0 || strcmp(idealName,"OverflowSubI") == 0
|| strcmp(idealName,"SubExactL") == 0 || strcmp(idealName,"OverflowSubL") == 0
|| strcmp(idealName,"MulExactI") == 0 || strcmp(idealName,"OverflowMulI") == 0
|| strcmp(idealName,"MulExactL") == 0 || strcmp(idealName,"OverflowMulL") == 0
|| strcmp(idealName,"NegExactI") == 0
|| strcmp(idealName,"NegExactL") == 0
|| strcmp(idealName,"FlagsProj") == 0
|| strcmp(idealName,"Bool") == 0 || strcmp(idealName,"Bool") == 0
|| strcmp(idealName,"Binary") == 0 ) { || strcmp(idealName,"Binary") == 0 ) {
// Removed ConI from the must_clone list. CPUs that cannot use // Removed ConI from the must_clone list. CPUs that cannot use
......
...@@ -660,6 +660,7 @@ int InstructForm::memory_operand(FormDict &globals) const { ...@@ -660,6 +660,7 @@ int InstructForm::memory_operand(FormDict &globals) const {
int USE_of_memory = 0; int USE_of_memory = 0;
int DEF_of_memory = 0; int DEF_of_memory = 0;
const char* last_memory_DEF = NULL; // to test DEF/USE pairing in asserts const char* last_memory_DEF = NULL; // to test DEF/USE pairing in asserts
const char* last_memory_USE = NULL;
Component *unique = NULL; Component *unique = NULL;
Component *comp = NULL; Component *comp = NULL;
ComponentList &components = (ComponentList &)_components; ComponentList &components = (ComponentList &)_components;
...@@ -681,7 +682,16 @@ int InstructForm::memory_operand(FormDict &globals) const { ...@@ -681,7 +682,16 @@ int InstructForm::memory_operand(FormDict &globals) const {
assert(0 == strcmp(last_memory_DEF, comp->_name), "every memory DEF is followed by a USE of the same name"); assert(0 == strcmp(last_memory_DEF, comp->_name), "every memory DEF is followed by a USE of the same name");
last_memory_DEF = NULL; last_memory_DEF = NULL;
} }
USE_of_memory++; // Handles same memory being used multiple times in the case of BMI1 instructions.
if (last_memory_USE != NULL) {
if (strcmp(comp->_name, last_memory_USE) != 0) {
USE_of_memory++;
}
} else {
USE_of_memory++;
}
last_memory_USE = comp->_name;
if (DEF_of_memory == 0) // defs take precedence if (DEF_of_memory == 0) // defs take precedence
unique = comp; unique = comp;
} else { } else {
......
...@@ -1599,6 +1599,8 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) { ...@@ -1599,6 +1599,8 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
if( node->is_ideal_fastlock() && new_inst->is_ideal_fastlock() ) { if( node->is_ideal_fastlock() && new_inst->is_ideal_fastlock() ) {
fprintf(fp, " ((MachFastLockNode*)n%d)->_counters = _counters;\n",cnt); fprintf(fp, " ((MachFastLockNode*)n%d)->_counters = _counters;\n",cnt);
fprintf(fp, " ((MachFastLockNode*)n%d)->_rtm_counters = _rtm_counters;\n",cnt);
fprintf(fp, " ((MachFastLockNode*)n%d)->_stack_rtm_counters = _stack_rtm_counters;\n",cnt);
} }
// Fill in the bottom_type where requested // Fill in the bottom_type where requested
...@@ -3980,6 +3982,8 @@ void ArchDesc::buildMachNode(FILE *fp_cpp, InstructForm *inst, const char *inden ...@@ -3980,6 +3982,8 @@ void ArchDesc::buildMachNode(FILE *fp_cpp, InstructForm *inst, const char *inden
} }
if( inst->is_ideal_fastlock() ) { if( inst->is_ideal_fastlock() ) {
fprintf(fp_cpp, "%s node->_counters = _leaf->as_FastLock()->counters();\n", indent); fprintf(fp_cpp, "%s node->_counters = _leaf->as_FastLock()->counters();\n", indent);
fprintf(fp_cpp, "%s node->_rtm_counters = _leaf->as_FastLock()->rtm_counters();\n", indent);
fprintf(fp_cpp, "%s node->_stack_rtm_counters = _leaf->as_FastLock()->stack_rtm_counters();\n", indent);
} }
} }
......
...@@ -103,6 +103,7 @@ friend class ciMethodHandle; \ ...@@ -103,6 +103,7 @@ friend class ciMethodHandle; \
friend class ciMethodType; \ friend class ciMethodType; \
friend class ciReceiverTypeData; \ friend class ciReceiverTypeData; \
friend class ciTypeEntries; \ friend class ciTypeEntries; \
friend class ciSpeculativeTrapData; \
friend class ciSymbol; \ friend class ciSymbol; \
friend class ciArray; \ friend class ciArray; \
friend class ciObjArray; \ friend class ciObjArray; \
......
...@@ -926,7 +926,8 @@ void ciEnv::register_method(ciMethod* target, ...@@ -926,7 +926,8 @@ void ciEnv::register_method(ciMethod* target,
AbstractCompiler* compiler, AbstractCompiler* compiler,
int comp_level, int comp_level,
bool has_unsafe_access, bool has_unsafe_access,
bool has_wide_vectors) { bool has_wide_vectors,
RTMState rtm_state) {
VM_ENTRY_MARK; VM_ENTRY_MARK;
nmethod* nm = NULL; nmethod* nm = NULL;
{ {
...@@ -973,6 +974,15 @@ void ciEnv::register_method(ciMethod* target, ...@@ -973,6 +974,15 @@ void ciEnv::register_method(ciMethod* target,
methodHandle method(THREAD, target->get_Method()); methodHandle method(THREAD, target->get_Method());
#if INCLUDE_RTM_OPT
if (!failing() && (rtm_state != NoRTM) &&
(method()->method_data() != NULL) &&
(method()->method_data()->rtm_state() != rtm_state)) {
// Preemptive decompile if rtm state was changed.
record_failure("RTM state change invalidated rtm code");
}
#endif
if (failing()) { if (failing()) {
// While not a true deoptimization, it is a preemptive decompile. // While not a true deoptimization, it is a preemptive decompile.
MethodData* mdo = method()->method_data(); MethodData* mdo = method()->method_data();
...@@ -999,13 +1009,15 @@ void ciEnv::register_method(ciMethod* target, ...@@ -999,13 +1009,15 @@ void ciEnv::register_method(ciMethod* target,
frame_words, oop_map_set, frame_words, oop_map_set,
handler_table, inc_table, handler_table, inc_table,
compiler, comp_level); compiler, comp_level);
// Free codeBlobs // Free codeBlobs
code_buffer->free_blob(); code_buffer->free_blob();
if (nm != NULL) { if (nm != NULL) {
nm->set_has_unsafe_access(has_unsafe_access); nm->set_has_unsafe_access(has_unsafe_access);
nm->set_has_wide_vectors(has_wide_vectors); nm->set_has_wide_vectors(has_wide_vectors);
#if INCLUDE_RTM_OPT
nm->set_rtm_state(rtm_state);
#endif
// Record successful registration. // Record successful registration.
// (Put nm into the task handle *before* publishing to the Java heap.) // (Put nm into the task handle *before* publishing to the Java heap.)
......
...@@ -363,7 +363,8 @@ public: ...@@ -363,7 +363,8 @@ public:
AbstractCompiler* compiler, AbstractCompiler* compiler,
int comp_level, int comp_level,
bool has_unsafe_access, bool has_unsafe_access,
bool has_wide_vectors); bool has_wide_vectors,
RTMState rtm_state = NoRTM);
// Access to certain well known ciObjects. // Access to certain well known ciObjects.
......
此差异已折叠。
此差异已折叠。
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -39,24 +39,24 @@ ...@@ -39,24 +39,24 @@
class AltHashing : AllStatic { class AltHashing : AllStatic {
// utility function copied from java/lang/Integer // utility function copied from java/lang/Integer
static jint Integer_rotateLeft(jint i, int distance) { static juint Integer_rotateLeft(juint i, int distance) {
return (i << distance) | (((juint)i) >> (32-distance)); return (i << distance) | (i >> (32-distance));
} }
static jint murmur3_32(const int* data, int len); static juint murmur3_32(const int* data, int len);
static jint murmur3_32(jint seed, const int* data, int len); static juint murmur3_32(juint seed, const int* data, int len);
#ifndef PRODUCT #ifndef PRODUCT
// Hashing functions used for internal testing // Hashing functions used for internal testing
static jint murmur3_32(const jbyte* data, int len); static juint murmur3_32(const jbyte* data, int len);
static jint murmur3_32(const jchar* data, int len); static juint murmur3_32(const jchar* data, int len);
static void testMurmur3_32_ByteArray(); static void testMurmur3_32_ByteArray();
static void testEquivalentHashes(); static void testEquivalentHashes();
#endif // PRODUCT #endif // PRODUCT
public: public:
static jint compute_seed(); static juint compute_seed();
static jint murmur3_32(jint seed, const jbyte* data, int len); static juint murmur3_32(juint seed, const jbyte* data, int len);
static jint murmur3_32(jint seed, const jchar* data, int len); static juint murmur3_32(juint seed, const jchar* data, int len);
NOT_PRODUCT(static void test_alt_hash();) NOT_PRODUCT(static void test_alt_hash();)
}; };
#endif // SHARE_VM_CLASSFILE_ALTHASHING_HPP #endif // SHARE_VM_CLASSFILE_ALTHASHING_HPP
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -35,6 +35,9 @@ ...@@ -35,6 +35,9 @@
#include "oops/oop.inline2.hpp" #include "oops/oop.inline2.hpp"
#include "runtime/mutexLocker.hpp" #include "runtime/mutexLocker.hpp"
#include "utilities/hashtable.inline.hpp" #include "utilities/hashtable.inline.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/g1/g1StringDedup.hpp"
#endif
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
...@@ -728,6 +731,15 @@ oop StringTable::intern(Handle string_or_null, jchar* name, ...@@ -728,6 +731,15 @@ oop StringTable::intern(Handle string_or_null, jchar* name,
string = java_lang_String::create_from_unicode(name, len, CHECK_NULL); string = java_lang_String::create_from_unicode(name, len, CHECK_NULL);
} }
#if INCLUDE_ALL_GCS
if (G1StringDedup::is_enabled()) {
// Deduplicate the string before it is interned. Note that we should never
// deduplicate a string after it has been interned. Doing so will counteract
// compiler optimizations done on e.g. interned string literals.
G1StringDedup::deduplicate(string());
}
#endif
// Grab the StringTable_lock before getting the_table() because it could // Grab the StringTable_lock before getting the_table() because it could
// change at safepoint. // change at safepoint.
MutexLocker ml(StringTable_lock, THREAD); MutexLocker ml(StringTable_lock, THREAD);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册