# HG changeset patch # User amurillo # Date 1343073260 25200 # Node ID bd54fe36b5e50f9ef1e30a5047b27fee5297e268 # Parent e3619706a7253540a2d94e9e841acaab8ace7038# Parent 12fc2571a6e2e54f163cfa280edf700979109ff8 Merge diff -r e3619706a725 -r bd54fe36b5e5 agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java Mon Jul 23 12:38:08 2012 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java Mon Jul 23 12:54:20 2012 -0700 @@ -47,14 +47,11 @@ private static int HAS_LINENUMBER_TABLE; private static int HAS_CHECKED_EXCEPTIONS; private static int HAS_LOCALVARIABLE_TABLE; + private static int HAS_EXCEPTION_TABLE; private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { Type type = db.lookupType("constMethodOopDesc"); constants = new OopField(type.getOopField("_constants"), 0); - // The exception handler table. 4-tuples of ints [start_pc, end_pc, - // handler_pc, catch_type index] For methods with no exceptions the - // table is pointing to Universe::the_empty_int_array - exceptionTable = new OopField(type.getOopField("_exception_table"), 0); constMethodSize = new CIntField(type.getCIntegerField("_constMethod_size"), 0); flags = new ByteField(type.getJByteField("_flags"), 0); @@ -62,6 +59,7 @@ HAS_LINENUMBER_TABLE = db.lookupIntConstant("constMethodOopDesc::_has_linenumber_table").intValue(); HAS_CHECKED_EXCEPTIONS = db.lookupIntConstant("constMethodOopDesc::_has_checked_exceptions").intValue(); HAS_LOCALVARIABLE_TABLE = db.lookupIntConstant("constMethodOopDesc::_has_localvariable_table").intValue(); + HAS_EXCEPTION_TABLE = db.lookupIntConstant("constMethodOopDesc::_has_exception_table").intValue(); // Size of Java bytecodes allocated immediately after constMethodOop. codeSize = new CIntField(type.getCIntegerField("_code_size"), 0); @@ -78,6 +76,9 @@ type = db.lookupType("LocalVariableTableElement"); localVariableTableElementSize = type.getSize(); + + type = db.lookupType("ExceptionTableElement"); + exceptionTableElementSize = type.getSize(); } ConstMethod(OopHandle handle, ObjectHeap heap) { @@ -86,7 +87,6 @@ // Fields private static OopField constants; - private static OopField exceptionTable; private static CIntField constMethodSize; private static ByteField flags; private static CIntField codeSize; @@ -100,6 +100,7 @@ private static long checkedExceptionElementSize; private static long localVariableTableElementSize; + private static long exceptionTableElementSize; public Method getMethod() { InstanceKlass ik = (InstanceKlass)getConstants().getPoolHolder(); @@ -112,10 +113,6 @@ return (ConstantPool) constants.getValue(this); } - public TypeArray getExceptionTable() { - return (TypeArray) exceptionTable.getValue(this); - } - public long getConstMethodSize() { return constMethodSize.getValue(this); } @@ -235,7 +232,6 @@ super.iterateFields(visitor, doVMFields); if (doVMFields) { visitor.doOop(constants, true); - visitor.doOop(exceptionTable, true); visitor.doCInt(constMethodSize, true); visitor.doByte(flags, true); visitor.doCInt(codeSize, true); @@ -326,6 +322,23 @@ return ret; } + public boolean hasExceptionTable() { + return (getFlags() & HAS_EXCEPTION_TABLE) != 0; + } + + public ExceptionTableElement[] getExceptionTable() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(hasExceptionTable(), "should only be called if table is present"); + } + ExceptionTableElement[] ret = new ExceptionTableElement[getExceptionTableLength()]; + long offset = offsetOfExceptionTable(); + for (int i = 0; i < ret.length; i++) { + ret[i] = new ExceptionTableElement(getHandle(), offset); + offset += exceptionTableElementSize; + } + return ret; + } + public boolean hasCheckedExceptions() { return (getFlags() & HAS_CHECKED_EXCEPTIONS) != 0; } @@ -415,7 +428,10 @@ if (Assert.ASSERTS_ENABLED) { Assert.that(hasLocalVariableTable(), "should only be called if table is present"); } - if (hasCheckedExceptions()) { + + if (hasExceptionTable()) { + return offsetOfExceptionTable() - 2; + } else if (hasCheckedExceptions()) { return offsetOfCheckedExceptions() - 2; } else { return offsetOfLastU2Element(); @@ -432,4 +448,33 @@ return offset; } + private int getExceptionTableLength() { + if (hasExceptionTable()) { + return (int) getHandle().getCIntegerAt(offsetOfExceptionTableLength(), 2, true); + } else { + return 0; + } + } + + private long offsetOfExceptionTableLength() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(hasExceptionTable(), "should only be called if table is present"); + } + if (hasCheckedExceptions()) { + return offsetOfCheckedExceptions() - 2; + } else { + return offsetOfLastU2Element(); + } + } + + private long offsetOfExceptionTable() { + long offset = offsetOfExceptionTableLength(); + long length = getExceptionTableLength(); + if (Assert.ASSERTS_ENABLED) { + Assert.that(length > 0, "should only be called if table is present"); + } + offset -= length * exceptionTableElementSize; + return offset; + } + } diff -r e3619706a725 -r bd54fe36b5e5 agent/src/share/classes/sun/jvm/hotspot/oops/ExceptionTableElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ExceptionTableElement.java Mon Jul 23 12:54:20 2012 -0700 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2012, 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.oops; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.interpreter.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +public class ExceptionTableElement { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ExceptionTableElement"); + offsetOfStartPC = type.getCIntegerField("start_pc").getOffset(); + offsetOfEndPC = type.getCIntegerField("end_pc").getOffset(); + offsetOfHandlerPC = type.getCIntegerField("handler_pc").getOffset(); + offsetOfCatchTypeIndex = type.getCIntegerField("catch_type_index").getOffset(); + } + + private static long offsetOfStartPC; + private static long offsetOfEndPC; + private static long offsetOfHandlerPC; + private static long offsetOfCatchTypeIndex; + + private OopHandle handle; + private long offset; + + public ExceptionTableElement(OopHandle handle, long offset) { + this.handle = handle; + this.offset = offset; + } + + public int getStartPC() { + return (int) handle.getCIntegerAt(offset + offsetOfStartPC, 2, true); + } + + public int getEndPC() { + return (int) handle.getCIntegerAt(offset + offsetOfEndPC, 2, true); + } + + public int getHandlerPC() { + return (int) handle.getCIntegerAt(offset + offsetOfHandlerPC, 2, true); + } + + public int getCatchTypeIndex() { + return (int) handle.getCIntegerAt(offset + offsetOfCatchTypeIndex, 2, true); + } +} + diff -r e3619706a725 -r bd54fe36b5e5 agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java Mon Jul 23 12:38:08 2012 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java Mon Jul 23 12:54:20 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, 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 @@ -651,10 +651,11 @@ boolean fellThrough = false; // False to get first BB marked. // First mark all exception handlers as start of a basic-block - TypeArray excps = method().getExceptionTable(); - for(int i = 0; i < excps.getLength(); i += 4) { - int handler_pc_idx = i+2; - markBB(excps.getIntAt(handler_pc_idx), null); + if (method().hasExceptionTable()) { + ExceptionTableElement[] excps = method().getExceptionTable(); + for(int i = 0; i < excps.length; i++) { + markBB(excps[i].getHandlerPC(), null); + } } // Then iterate through the code @@ -891,14 +892,15 @@ // Mark entry basic block as alive and all exception handlers _basic_blocks[0].markAsAlive(); - TypeArray excps = method().getExceptionTable(); - for(int i = 0; i < excps.getLength(); i += 4) { - int handler_pc_idx = i+2; - BasicBlock bb = getBasicBlockAt(excps.getIntAt(handler_pc_idx)); - // If block is not already alive (due to multiple exception handlers to same bb), then - // make it alive - if (bb.isDead()) - bb.markAsAlive(); + if (method().hasExceptionTable()) { + ExceptionTableElement[] excps = method().getExceptionTable(); + for(int i = 0; i < excps.length; i ++) { + BasicBlock bb = getBasicBlockAt(excps[i].getHandlerPC()); + // If block is not already alive (due to multiple exception handlers to same bb), then + // make it alive + if (bb.isDead()) + bb.markAsAlive(); + } } BytecodeStream bcs = new BytecodeStream(_method); @@ -1468,12 +1470,12 @@ if (_has_exceptions) { int bci = itr.bci(); - TypeArray exct = method().getExceptionTable(); - for(int i = 0; i< exct.getLength(); i+=4) { - int start_pc = exct.getIntAt(i); - int end_pc = exct.getIntAt(i+1); - int handler_pc = exct.getIntAt(i+2); - int catch_type = exct.getIntAt(i+3); + ExceptionTableElement[] exct = method().getExceptionTable(); + for(int i = 0; i< exct.length; i++) { + int start_pc = exct[i].getStartPC(); + int end_pc = exct[i].getEndPC(); + int handler_pc = exct[i].getHandlerPC(); + int catch_type = exct[i].getCatchTypeIndex(); if (start_pc <= bci && bci < end_pc) { BasicBlock excBB = getBasicBlockAt(handler_pc); @@ -2151,7 +2153,7 @@ _conflict = false; _max_locals = (int) method().getMaxLocals(); _max_stack = (int) method().getMaxStack(); - _has_exceptions = (method().getExceptionTable().getLength() > 0); + _has_exceptions = (method().hasExceptionTable()); _nof_refval_conflicts = 0; _init_vars = new ArrayList(5); // There are seldom more than 5 init_vars _report_result = false; diff -r e3619706a725 -r bd54fe36b5e5 agent/src/share/classes/sun/jvm/hotspot/oops/Method.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Mon Jul 23 12:38:08 2012 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Mon Jul 23 12:54:20 2012 -0700 @@ -127,7 +127,6 @@ return getConstMethod().getConstants(); } public MethodData getMethodData() { return (MethodData) methodData.getValue(this); } - public TypeArray getExceptionTable() { return getConstMethod().getExceptionTable(); } /** WARNING: this is in words, not useful in this system; use getObjectSize() instead */ public long getMethodSize() { return methodSize.getValue(this); } public long getMaxStack() { return maxStack.getValue(this); } @@ -328,6 +327,14 @@ return null; } + public boolean hasExceptionTable() { + return getConstMethod().hasExceptionTable(); + } + + public ExceptionTableElement[] getExceptionTable() { + return getConstMethod().getExceptionTable(); + } + public boolean hasCheckedExceptions() { return getConstMethod().hasCheckedExceptions(); } diff -r e3619706a725 -r bd54fe36b5e5 agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Mon Jul 23 12:38:08 2012 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Mon Jul 23 12:54:20 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, 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 @@ -504,11 +504,14 @@ 2 /* exp. table len. */ + 2 /* code attr. count */; - TypeArray exceptionTable = m.getExceptionTable(); - final int exceptionTableLen = (int) exceptionTable.getLength(); - if (exceptionTableLen != 0) { + boolean hasExceptionTable = m.hasExceptionTable(); + ExceptionTableElement[] exceptionTable = null; + int exceptionTableLen = 0; + if (hasExceptionTable) { + exceptionTable = m.getExceptionTable(); + exceptionTableLen = exceptionTable.length; if (DEBUG) debugMessage("\tmethod has exception table"); - codeSize += (exceptionTableLen / 4) /* exception table is 4-tuple array */ + codeSize += exceptionTableLen /* exception table is 4-tuple array */ * (2 /* start_pc */ + 2 /* end_pc */ + 2 /* handler_pc */ + @@ -586,15 +589,15 @@ dos.write(code); // write exception table size - dos.writeShort((short) (exceptionTableLen / 4)); - if (DEBUG) debugMessage("\texception table length = " + (exceptionTableLen / 4)); + dos.writeShort((short) exceptionTableLen); + if (DEBUG) debugMessage("\texception table length = " + exceptionTableLen); if (exceptionTableLen != 0) { - for (int e = 0; e < exceptionTableLen; e += 4) { - dos.writeShort((short) exceptionTable.getIntAt(e)); - dos.writeShort((short) exceptionTable.getIntAt(e + 1)); - dos.writeShort((short) exceptionTable.getIntAt(e + 2)); - dos.writeShort((short) exceptionTable.getIntAt(e + 3)); + for (int e = 0; e < exceptionTableLen; e++) { + dos.writeShort((short) exceptionTable[e].getStartPC()); + dos.writeShort((short) exceptionTable[e].getEndPC()); + dos.writeShort((short) exceptionTable[e].getHandlerPC()); + dos.writeShort((short) exceptionTable[e].getCatchTypeIndex()); } } diff -r e3619706a725 -r bd54fe36b5e5 agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java --- a/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Mon Jul 23 12:38:08 2012 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Mon Jul 23 12:54:20 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, 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 @@ -783,37 +783,39 @@ }); // display exception table for this method - TypeArray exceptionTable = method.getExceptionTable(); - // exception table is 4 tuple array of shorts - int numEntries = (int)exceptionTable.getLength() / 4; - if (numEntries != 0) { - buf.h4("Exception Table"); - buf.beginTable(1); - buf.beginTag("tr"); - buf.headerCell("start bci"); - buf.headerCell("end bci"); - buf.headerCell("handler bci"); - buf.headerCell("catch type"); - buf.endTag("tr"); - - for (int e = 0; e < numEntries; e += 4) { + boolean hasException = method.hasExceptionTable(); + if (hasException) { + ExceptionTableElement[] exceptionTable = method.getExceptionTable(); + int numEntries = exceptionTable.length; + if (numEntries != 0) { + buf.h4("Exception Table"); + buf.beginTable(1); buf.beginTag("tr"); - buf.cell(Integer.toString(exceptionTable.getIntAt(e))); - buf.cell(Integer.toString(exceptionTable.getIntAt(e + 1))); - buf.cell(Integer.toString(exceptionTable.getIntAt(e + 2))); - short cpIndex = (short) exceptionTable.getIntAt(e + 3); - ConstantPool.CPSlot obj = cpIndex == 0? null : cpool.getSlotAt(cpIndex); - if (obj == null) { - buf.cell("Any"); - } else if (obj.isMetaData()) { - buf.cell(obj.getSymbol().asString().replace('/', '.')); - } else { - buf.cell(genKlassLink((InstanceKlass)obj.getOop())); + buf.headerCell("start bci"); + buf.headerCell("end bci"); + buf.headerCell("handler bci"); + buf.headerCell("catch type"); + buf.endTag("tr"); + + for (int e = 0; e < numEntries; e ++) { + buf.beginTag("tr"); + buf.cell(Integer.toString(exceptionTable[e].getStartPC())); + buf.cell(Integer.toString(exceptionTable[e].getEndPC())); + buf.cell(Integer.toString(exceptionTable[e].getHandlerPC())); + short cpIndex = (short) exceptionTable[e].getCatchTypeIndex(); + ConstantPool.CPSlot obj = cpIndex == 0? null : cpool.getSlotAt(cpIndex); + if (obj == null) { + buf.cell("Any"); + } else if (obj.isMetaData()) { + buf.cell(obj.getSymbol().asString().replace('/', '.')); + } else { + buf.cell(genKlassLink((InstanceKlass)obj.getOop())); + } + buf.endTag("tr"); } - buf.endTag("tr"); + + buf.endTable(); } - - buf.endTable(); } // display constant pool hyperlink diff -r e3619706a725 -r bd54fe36b5e5 make/hotspot_version --- a/make/hotspot_version Mon Jul 23 12:38:08 2012 -0700 +++ b/make/hotspot_version Mon Jul 23 12:54:20 2012 -0700 @@ -35,7 +35,7 @@ HS_MAJOR_VER=24 HS_MINOR_VER=0 -HS_BUILD_NUMBER=16 +HS_BUILD_NUMBER=17 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r e3619706a725 -r bd54fe36b5e5 src/cpu/x86/vm/assembler_x86.cpp --- a/src/cpu/x86/vm/assembler_x86.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/cpu/x86/vm/assembler_x86.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -2573,6 +2573,13 @@ emit_byte(0xC0 | encode); } +void Assembler::punpcklqdq(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); + emit_byte(0x6C); + emit_byte(0xC0 | encode); +} + void Assembler::push(int32_t imm32) { // in 64bits we push 64bits onto the stack but only // take a 32bit immediate @@ -3178,6 +3185,13 @@ emit_byte(0xC0 | encode); } +void Assembler::vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx2() || (!vector256) && VM_Version::supports_avx(), ""); + int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector256); + emit_byte(0xEF); + emit_byte(0xC0 | encode); +} + void Assembler::vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); bool vector256 = true; @@ -3189,6 +3203,17 @@ emit_byte(0x01); } +void Assembler::vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) { + assert(VM_Version::supports_avx2(), ""); + bool vector256 = true; + int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector256, VEX_OPCODE_0F_3A); + emit_byte(0x38); + emit_byte(0xC0 | encode); + // 0x00 - insert into lower 128 bits + // 0x01 - insert into upper 128 bits + emit_byte(0x01); +} + void Assembler::vzeroupper() { assert(VM_Version::supports_avx(), ""); (void)vex_prefix_and_encode(xmm0, xmm0, xmm0, VEX_SIMD_NONE); @@ -7480,6 +7505,24 @@ movb(as_Address(dst), src); } +void MacroAssembler::movdl(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + movdl(dst, as_Address(src)); + } else { + lea(rscratch1, src); + movdl(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::movq(XMMRegister dst, AddressLiteral src) { + if (reachable(src)) { + movq(dst, as_Address(src)); + } else { + lea(rscratch1, src); + movq(dst, Address(rscratch1, 0)); + } +} + void MacroAssembler::movdbl(XMMRegister dst, AddressLiteral src) { if (reachable(src)) { if (UseXmmLoadAndClearUpper) { diff -r e3619706a725 -r bd54fe36b5e5 src/cpu/x86/vm/assembler_x86.hpp --- a/src/cpu/x86/vm/assembler_x86.hpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/cpu/x86/vm/assembler_x86.hpp Mon Jul 23 12:54:20 2012 -0700 @@ -1466,6 +1466,9 @@ void punpckldq(XMMRegister dst, XMMRegister src); void punpckldq(XMMRegister dst, Address src); + // Interleave Low Quadwords + void punpcklqdq(XMMRegister dst, XMMRegister src); + #ifndef _LP64 // no 32bit push/pop on amd64 void pushl(Address src); #endif @@ -1606,13 +1609,11 @@ void set_byte_if_not_zero(Register dst); // sets reg to 1 if not zero, otherwise 0 - // AVX 3-operands instructions (encoded with VEX prefix) + // AVX 3-operands scalar instructions (encoded with VEX prefix) void vaddsd(XMMRegister dst, XMMRegister nds, Address src); void vaddsd(XMMRegister dst, XMMRegister nds, XMMRegister src); void vaddss(XMMRegister dst, XMMRegister nds, Address src); void vaddss(XMMRegister dst, XMMRegister nds, XMMRegister src); - void vandpd(XMMRegister dst, XMMRegister nds, Address src); - void vandps(XMMRegister dst, XMMRegister nds, Address src); void vdivsd(XMMRegister dst, XMMRegister nds, Address src); void vdivsd(XMMRegister dst, XMMRegister nds, XMMRegister src); void vdivss(XMMRegister dst, XMMRegister nds, Address src); @@ -1625,13 +1626,17 @@ void vsubsd(XMMRegister dst, XMMRegister nds, XMMRegister src); void vsubss(XMMRegister dst, XMMRegister nds, Address src); void vsubss(XMMRegister dst, XMMRegister nds, XMMRegister src); - void vxorpd(XMMRegister dst, XMMRegister nds, Address src); - void vxorps(XMMRegister dst, XMMRegister nds, Address src); // AVX Vector instrucitons. + void vandpd(XMMRegister dst, XMMRegister nds, Address src); + void vandps(XMMRegister dst, XMMRegister nds, Address src); + void vxorpd(XMMRegister dst, XMMRegister nds, Address src); + void vxorps(XMMRegister dst, XMMRegister nds, Address src); void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); void vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); void vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src); + void vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src); // AVX instruction which is used to clear upper 128 bits of YMM registers and // to avoid transaction penalty between AVX and SSE states. There is no @@ -2563,6 +2568,20 @@ void vxorps(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vxorps(dst, nds, src); } void vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src); + void vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + if (UseAVX > 1 || !vector256) // vpxor 256 bit is available only in AVX2 + Assembler::vpxor(dst, nds, src, vector256); + else + Assembler::vxorpd(dst, nds, src, vector256); + } + + // Move packed integer values from low 128 bit to hign 128 bit in 256 bit vector. + void vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) { + if (UseAVX > 1) // vinserti128h is available only in AVX2 + Assembler::vinserti128h(dst, nds, src); + else + Assembler::vinsertf128h(dst, nds, src); + } // Data @@ -2615,6 +2634,13 @@ // to avoid hiding movb void movbyte(ArrayAddress dst, int src); + // Import other mov() methods from the parent class or else + // they will be hidden by the following overriding declaration. + using Assembler::movdl; + using Assembler::movq; + void movdl(XMMRegister dst, AddressLiteral src); + void movq(XMMRegister dst, AddressLiteral src); + // Can push value or effective address void pushptr(AddressLiteral src); diff -r e3619706a725 -r bd54fe36b5e5 src/cpu/x86/vm/vm_version_x86.cpp --- a/src/cpu/x86/vm/vm_version_x86.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/cpu/x86/vm/vm_version_x86.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -562,7 +562,7 @@ AllocatePrefetchInstr = 3; } // On family 15h processors use XMM and UnalignedLoadStores for Array Copy - if( FLAG_IS_DEFAULT(UseXMMForArrayCopy) ) { + if( supports_sse2() && FLAG_IS_DEFAULT(UseXMMForArrayCopy) ) { UseXMMForArrayCopy = true; } if( FLAG_IS_DEFAULT(UseUnalignedLoadStores) && UseXMMForArrayCopy ) { diff -r e3619706a725 -r bd54fe36b5e5 src/cpu/x86/vm/x86.ad --- a/src/cpu/x86/vm/x86.ad Mon Jul 23 12:38:08 2012 -0700 +++ b/src/cpu/x86/vm/x86.ad Mon Jul 23 12:54:20 2012 -0700 @@ -71,244 +71,244 @@ // XMM0-XMM3 might hold parameters reg_def XMM0 ( SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()); -reg_def XMM0b( SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()->next()); -reg_def XMM0c( SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()->next()->next()); -reg_def XMM0d( SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()->next()->next()->next()); -reg_def XMM0e( SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()->next()->next()->next()->next()); -reg_def XMM0f( SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM0g( SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM0h( SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM0b( SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()->next(1)); +reg_def XMM0c( SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()->next(2)); +reg_def XMM0d( SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()->next(3)); +reg_def XMM0e( SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()->next(4)); +reg_def XMM0f( SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()->next(5)); +reg_def XMM0g( SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()->next(6)); +reg_def XMM0h( SOC, SOC, Op_RegF, 0, xmm0->as_VMReg()->next(7)); reg_def XMM1 ( SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()); -reg_def XMM1b( SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()->next()); -reg_def XMM1c( SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()->next()->next()); -reg_def XMM1d( SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()->next()->next()->next()); -reg_def XMM1e( SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()->next()->next()->next()->next()); -reg_def XMM1f( SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM1g( SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM1h( SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM1b( SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()->next(1)); +reg_def XMM1c( SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()->next(2)); +reg_def XMM1d( SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()->next(3)); +reg_def XMM1e( SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()->next(4)); +reg_def XMM1f( SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()->next(5)); +reg_def XMM1g( SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()->next(6)); +reg_def XMM1h( SOC, SOC, Op_RegF, 1, xmm1->as_VMReg()->next(7)); reg_def XMM2 ( SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()); -reg_def XMM2b( SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()->next()); -reg_def XMM2c( SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()->next()->next()); -reg_def XMM2d( SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()->next()->next()->next()); -reg_def XMM2e( SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()->next()->next()->next()->next()); -reg_def XMM2f( SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM2g( SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM2h( SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM2b( SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()->next(1)); +reg_def XMM2c( SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()->next(2)); +reg_def XMM2d( SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()->next(3)); +reg_def XMM2e( SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()->next(4)); +reg_def XMM2f( SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()->next(5)); +reg_def XMM2g( SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()->next(6)); +reg_def XMM2h( SOC, SOC, Op_RegF, 2, xmm2->as_VMReg()->next(7)); reg_def XMM3 ( SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()); -reg_def XMM3b( SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()->next()); -reg_def XMM3c( SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()->next()->next()); -reg_def XMM3d( SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()->next()->next()->next()); -reg_def XMM3e( SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()->next()->next()->next()->next()); -reg_def XMM3f( SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM3g( SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM3h( SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM3b( SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()->next(1)); +reg_def XMM3c( SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()->next(2)); +reg_def XMM3d( SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()->next(3)); +reg_def XMM3e( SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()->next(4)); +reg_def XMM3f( SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()->next(5)); +reg_def XMM3g( SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()->next(6)); +reg_def XMM3h( SOC, SOC, Op_RegF, 3, xmm3->as_VMReg()->next(7)); reg_def XMM4 ( SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()); -reg_def XMM4b( SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()->next()); -reg_def XMM4c( SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()->next()->next()); -reg_def XMM4d( SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()->next()->next()->next()); -reg_def XMM4e( SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()->next()->next()->next()->next()); -reg_def XMM4f( SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM4g( SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM4h( SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM4b( SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()->next(1)); +reg_def XMM4c( SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()->next(2)); +reg_def XMM4d( SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()->next(3)); +reg_def XMM4e( SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()->next(4)); +reg_def XMM4f( SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()->next(5)); +reg_def XMM4g( SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()->next(6)); +reg_def XMM4h( SOC, SOC, Op_RegF, 4, xmm4->as_VMReg()->next(7)); reg_def XMM5 ( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()); -reg_def XMM5b( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next()); -reg_def XMM5c( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next()->next()); -reg_def XMM5d( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next()->next()->next()); -reg_def XMM5e( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next()->next()->next()->next()); -reg_def XMM5f( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM5g( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM5h( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM5b( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next(1)); +reg_def XMM5c( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next(2)); +reg_def XMM5d( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next(3)); +reg_def XMM5e( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next(4)); +reg_def XMM5f( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next(5)); +reg_def XMM5g( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next(6)); +reg_def XMM5h( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next(7)); #ifdef _WIN64 reg_def XMM6 ( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()); -reg_def XMM6b( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next()); -reg_def XMM6c( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next()->next()); -reg_def XMM6d( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next()->next()->next()); -reg_def XMM6e( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next()->next()->next()->next()); -reg_def XMM6f( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM6g( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM6h( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM6b( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(1)); +reg_def XMM6c( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(2)); +reg_def XMM6d( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(3)); +reg_def XMM6e( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(4)); +reg_def XMM6f( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(5)); +reg_def XMM6g( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(6)); +reg_def XMM6h( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(7)); reg_def XMM7 ( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()); -reg_def XMM7b( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next()); -reg_def XMM7c( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next()->next()); -reg_def XMM7d( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next()->next()->next()); -reg_def XMM7e( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next()->next()->next()->next()); -reg_def XMM7f( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM7g( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM7h( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM7b( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(1)); +reg_def XMM7c( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(2)); +reg_def XMM7d( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(3)); +reg_def XMM7e( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(4)); +reg_def XMM7f( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(5)); +reg_def XMM7g( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(6)); +reg_def XMM7h( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(7)); reg_def XMM8 ( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()); -reg_def XMM8b( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next()); -reg_def XMM8c( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next()->next()); -reg_def XMM8d( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next()->next()->next()); -reg_def XMM8e( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next()->next()->next()->next()); -reg_def XMM8f( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM8g( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM8h( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM8b( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(1)); +reg_def XMM8c( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(2)); +reg_def XMM8d( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(3)); +reg_def XMM8e( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(4)); +reg_def XMM8f( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(5)); +reg_def XMM8g( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(6)); +reg_def XMM8h( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(7)); reg_def XMM9 ( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()); -reg_def XMM9b( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next()); -reg_def XMM9c( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next()->next()); -reg_def XMM9d( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next()->next()->next()); -reg_def XMM9e( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next()->next()->next()->next()); -reg_def XMM9f( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM9g( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM9h( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM9b( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(1)); +reg_def XMM9c( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(2)); +reg_def XMM9d( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(3)); +reg_def XMM9e( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(4)); +reg_def XMM9f( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(5)); +reg_def XMM9g( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(6)); +reg_def XMM9h( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(7)); reg_def XMM10 ( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()); -reg_def XMM10b( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next()); -reg_def XMM10c( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next()->next()); -reg_def XMM10d( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next()->next()->next()); -reg_def XMM10e( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next()->next()->next()->next()); -reg_def XMM10f( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM10g( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM10h( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM10b( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(1)); +reg_def XMM10c( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(2)); +reg_def XMM10d( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(3)); +reg_def XMM10e( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(4)); +reg_def XMM10f( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(5)); +reg_def XMM10g( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(6)); +reg_def XMM10h( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(7)); reg_def XMM11 ( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()); -reg_def XMM11b( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next()); -reg_def XMM11c( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next()->next()); -reg_def XMM11d( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next()->next()->next()); -reg_def XMM11e( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next()->next()->next()->next()); -reg_def XMM11f( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM11g( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM11h( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM11b( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(1)); +reg_def XMM11c( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(2)); +reg_def XMM11d( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(3)); +reg_def XMM11e( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(4)); +reg_def XMM11f( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(5)); +reg_def XMM11g( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(6)); +reg_def XMM11h( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(7)); reg_def XMM12 ( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()); -reg_def XMM12b( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next()); -reg_def XMM12c( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next()->next()); -reg_def XMM12d( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next()->next()->next()); -reg_def XMM12e( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next()->next()->next()->next()); -reg_def XMM12f( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM12g( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM12h( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM12b( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(1)); +reg_def XMM12c( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(2)); +reg_def XMM12d( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(3)); +reg_def XMM12e( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(4)); +reg_def XMM12f( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(5)); +reg_def XMM12g( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(6)); +reg_def XMM12h( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(7)); reg_def XMM13 ( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()); -reg_def XMM13b( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next()); -reg_def XMM13c( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next()->next()); -reg_def XMM13d( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next()->next()->next()); -reg_def XMM13e( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next()->next()->next()->next()); -reg_def XMM13f( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM13g( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM13h( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM13b( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(1)); +reg_def XMM13c( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(2)); +reg_def XMM13d( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(3)); +reg_def XMM13e( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(4)); +reg_def XMM13f( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(5)); +reg_def XMM13g( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(6)); +reg_def XMM13h( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(7)); reg_def XMM14 ( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()); -reg_def XMM14b( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next()); -reg_def XMM14c( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next()->next()); -reg_def XMM14d( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next()->next()->next()); -reg_def XMM14e( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next()->next()->next()->next()); -reg_def XMM14f( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM14g( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM14h( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM14b( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(1)); +reg_def XMM14c( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(2)); +reg_def XMM14d( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(3)); +reg_def XMM14e( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(4)); +reg_def XMM14f( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(5)); +reg_def XMM14g( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(6)); +reg_def XMM14h( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(7)); reg_def XMM15 ( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()); -reg_def XMM15b( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next()); -reg_def XMM15c( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next()->next()); -reg_def XMM15d( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next()->next()->next()); -reg_def XMM15e( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next()->next()->next()->next()); -reg_def XMM15f( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM15g( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM15h( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM15b( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(1)); +reg_def XMM15c( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(2)); +reg_def XMM15d( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(3)); +reg_def XMM15e( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(4)); +reg_def XMM15f( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(5)); +reg_def XMM15g( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(6)); +reg_def XMM15h( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(7)); #else // _WIN64 reg_def XMM6 ( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()); -reg_def XMM6b( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next()); -reg_def XMM6c( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next()->next()); -reg_def XMM6d( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next()->next()->next()); -reg_def XMM6e( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next()->next()->next()->next()); -reg_def XMM6f( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM6g( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM6h( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM6b( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next(1)); +reg_def XMM6c( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next(2)); +reg_def XMM6d( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next(3)); +reg_def XMM6e( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next(4)); +reg_def XMM6f( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next(5)); +reg_def XMM6g( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next(6)); +reg_def XMM6h( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next(7)); reg_def XMM7 ( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()); -reg_def XMM7b( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next()); -reg_def XMM7c( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next()->next()); -reg_def XMM7d( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next()->next()->next()); -reg_def XMM7e( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next()->next()->next()->next()); -reg_def XMM7f( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM7g( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM7h( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM7b( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next(1)); +reg_def XMM7c( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next(2)); +reg_def XMM7d( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next(3)); +reg_def XMM7e( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next(4)); +reg_def XMM7f( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next(5)); +reg_def XMM7g( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next(6)); +reg_def XMM7h( SOC, SOC, Op_RegF, 7, xmm7->as_VMReg()->next(7)); #ifdef _LP64 reg_def XMM8 ( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()); -reg_def XMM8b( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next()); -reg_def XMM8c( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next()->next()); -reg_def XMM8d( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next()->next()->next()); -reg_def XMM8e( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next()->next()->next()->next()); -reg_def XMM8f( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM8g( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM8h( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM8b( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next(1)); +reg_def XMM8c( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next(2)); +reg_def XMM8d( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next(3)); +reg_def XMM8e( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next(4)); +reg_def XMM8f( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next(5)); +reg_def XMM8g( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next(6)); +reg_def XMM8h( SOC, SOC, Op_RegF, 8, xmm8->as_VMReg()->next(7)); reg_def XMM9 ( SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()); -reg_def XMM9b( SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()->next()); -reg_def XMM9c( SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()->next()->next()); -reg_def XMM9d( SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()->next()->next()->next()); -reg_def XMM9e( SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()->next()->next()->next()->next()); -reg_def XMM9f( SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM9g( SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM9h( SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM9b( SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()->next(1)); +reg_def XMM9c( SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()->next(2)); +reg_def XMM9d( SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()->next(3)); +reg_def XMM9e( SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()->next(4)); +reg_def XMM9f( SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()->next(5)); +reg_def XMM9g( SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()->next(6)); +reg_def XMM9h( SOC, SOC, Op_RegF, 9, xmm9->as_VMReg()->next(7)); reg_def XMM10 ( SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()); -reg_def XMM10b( SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()->next()); -reg_def XMM10c( SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()->next()->next()); -reg_def XMM10d( SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()->next()->next()->next()); -reg_def XMM10e( SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()->next()->next()->next()->next()); -reg_def XMM10f( SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM10g( SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM10h( SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM10b( SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()->next(1)); +reg_def XMM10c( SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()->next(2)); +reg_def XMM10d( SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()->next(3)); +reg_def XMM10e( SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()->next(4)); +reg_def XMM10f( SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()->next(5)); +reg_def XMM10g( SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()->next(6)); +reg_def XMM10h( SOC, SOC, Op_RegF, 10, xmm10->as_VMReg()->next(7)); reg_def XMM11 ( SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()); -reg_def XMM11b( SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()->next()); -reg_def XMM11c( SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()->next()->next()); -reg_def XMM11d( SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()->next()->next()->next()); -reg_def XMM11e( SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()->next()->next()->next()->next()); -reg_def XMM11f( SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM11g( SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM11h( SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM11b( SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()->next(1)); +reg_def XMM11c( SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()->next(2)); +reg_def XMM11d( SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()->next(3)); +reg_def XMM11e( SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()->next(4)); +reg_def XMM11f( SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()->next(5)); +reg_def XMM11g( SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()->next(6)); +reg_def XMM11h( SOC, SOC, Op_RegF, 11, xmm11->as_VMReg()->next(7)); reg_def XMM12 ( SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()); -reg_def XMM12b( SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()->next()); -reg_def XMM12c( SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()->next()->next()); -reg_def XMM12d( SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()->next()->next()->next()); -reg_def XMM12e( SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()->next()->next()->next()->next()); -reg_def XMM12f( SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM12g( SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM12h( SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM12b( SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()->next(1)); +reg_def XMM12c( SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()->next(2)); +reg_def XMM12d( SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()->next(3)); +reg_def XMM12e( SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()->next(4)); +reg_def XMM12f( SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()->next(5)); +reg_def XMM12g( SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()->next(6)); +reg_def XMM12h( SOC, SOC, Op_RegF, 12, xmm12->as_VMReg()->next(7)); reg_def XMM13 ( SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()); -reg_def XMM13b( SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()->next()); -reg_def XMM13c( SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()->next()->next()); -reg_def XMM13d( SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()->next()->next()->next()); -reg_def XMM13e( SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()->next()->next()->next()->next()); -reg_def XMM13f( SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM13g( SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM13h( SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM13b( SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()->next(1)); +reg_def XMM13c( SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()->next(2)); +reg_def XMM13d( SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()->next(3)); +reg_def XMM13e( SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()->next(4)); +reg_def XMM13f( SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()->next(5)); +reg_def XMM13g( SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()->next(6)); +reg_def XMM13h( SOC, SOC, Op_RegF, 13, xmm13->as_VMReg()->next(7)); reg_def XMM14 ( SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()); -reg_def XMM14b( SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()->next()); -reg_def XMM14c( SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()->next()->next()); -reg_def XMM14d( SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()->next()->next()->next()); -reg_def XMM14e( SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()->next()->next()->next()->next()); -reg_def XMM14f( SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM14g( SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM14h( SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM14b( SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()->next(1)); +reg_def XMM14c( SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()->next(2)); +reg_def XMM14d( SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()->next(3)); +reg_def XMM14e( SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()->next(4)); +reg_def XMM14f( SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()->next(5)); +reg_def XMM14g( SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()->next(6)); +reg_def XMM14h( SOC, SOC, Op_RegF, 14, xmm14->as_VMReg()->next(7)); reg_def XMM15 ( SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()); -reg_def XMM15b( SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()->next()); -reg_def XMM15c( SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()->next()->next()); -reg_def XMM15d( SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()->next()->next()->next()); -reg_def XMM15e( SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()->next()->next()->next()->next()); -reg_def XMM15f( SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()->next()->next()->next()->next()->next()); -reg_def XMM15g( SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()->next()->next()->next()->next()->next()->next()); -reg_def XMM15h( SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()->next()->next()->next()->next()->next()->next()->next()); +reg_def XMM15b( SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()->next(1)); +reg_def XMM15c( SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()->next(2)); +reg_def XMM15d( SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()->next(3)); +reg_def XMM15e( SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()->next(4)); +reg_def XMM15f( SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()->next(5)); +reg_def XMM15g( SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()->next(6)); +reg_def XMM15h( SOC, SOC, Op_RegF, 15, xmm15->as_VMReg()->next(7)); #endif // _LP64 @@ -889,7 +889,7 @@ ins_pipe(pipe_slow); %} -instruct vaddF_reg(regF dst, regF src1, regF src2) %{ +instruct addF_reg_reg(regF dst, regF src1, regF src2) %{ predicate(UseAVX > 0); match(Set dst (AddF src1 src2)); @@ -901,7 +901,7 @@ ins_pipe(pipe_slow); %} -instruct vaddF_mem(regF dst, regF src1, memory src2) %{ +instruct addF_reg_mem(regF dst, regF src1, memory src2) %{ predicate(UseAVX > 0); match(Set dst (AddF src1 (LoadF src2))); @@ -913,7 +913,7 @@ ins_pipe(pipe_slow); %} -instruct vaddF_imm(regF dst, regF src, immF con) %{ +instruct addF_reg_imm(regF dst, regF src, immF con) %{ predicate(UseAVX > 0); match(Set dst (AddF src con)); @@ -960,7 +960,7 @@ ins_pipe(pipe_slow); %} -instruct vaddD_reg(regD dst, regD src1, regD src2) %{ +instruct addD_reg_reg(regD dst, regD src1, regD src2) %{ predicate(UseAVX > 0); match(Set dst (AddD src1 src2)); @@ -972,7 +972,7 @@ ins_pipe(pipe_slow); %} -instruct vaddD_mem(regD dst, regD src1, memory src2) %{ +instruct addD_reg_mem(regD dst, regD src1, memory src2) %{ predicate(UseAVX > 0); match(Set dst (AddD src1 (LoadD src2))); @@ -984,7 +984,7 @@ ins_pipe(pipe_slow); %} -instruct vaddD_imm(regD dst, regD src, immD con) %{ +instruct addD_reg_imm(regD dst, regD src, immD con) %{ predicate(UseAVX > 0); match(Set dst (AddD src con)); @@ -1031,7 +1031,7 @@ ins_pipe(pipe_slow); %} -instruct vsubF_reg(regF dst, regF src1, regF src2) %{ +instruct subF_reg_reg(regF dst, regF src1, regF src2) %{ predicate(UseAVX > 0); match(Set dst (SubF src1 src2)); @@ -1043,7 +1043,7 @@ ins_pipe(pipe_slow); %} -instruct vsubF_mem(regF dst, regF src1, memory src2) %{ +instruct subF_reg_mem(regF dst, regF src1, memory src2) %{ predicate(UseAVX > 0); match(Set dst (SubF src1 (LoadF src2))); @@ -1055,7 +1055,7 @@ ins_pipe(pipe_slow); %} -instruct vsubF_imm(regF dst, regF src, immF con) %{ +instruct subF_reg_imm(regF dst, regF src, immF con) %{ predicate(UseAVX > 0); match(Set dst (SubF src con)); @@ -1102,7 +1102,7 @@ ins_pipe(pipe_slow); %} -instruct vsubD_reg(regD dst, regD src1, regD src2) %{ +instruct subD_reg_reg(regD dst, regD src1, regD src2) %{ predicate(UseAVX > 0); match(Set dst (SubD src1 src2)); @@ -1114,7 +1114,7 @@ ins_pipe(pipe_slow); %} -instruct vsubD_mem(regD dst, regD src1, memory src2) %{ +instruct subD_reg_mem(regD dst, regD src1, memory src2) %{ predicate(UseAVX > 0); match(Set dst (SubD src1 (LoadD src2))); @@ -1126,7 +1126,7 @@ ins_pipe(pipe_slow); %} -instruct vsubD_imm(regD dst, regD src, immD con) %{ +instruct subD_reg_imm(regD dst, regD src, immD con) %{ predicate(UseAVX > 0); match(Set dst (SubD src con)); @@ -1173,7 +1173,7 @@ ins_pipe(pipe_slow); %} -instruct vmulF_reg(regF dst, regF src1, regF src2) %{ +instruct mulF_reg_reg(regF dst, regF src1, regF src2) %{ predicate(UseAVX > 0); match(Set dst (MulF src1 src2)); @@ -1185,7 +1185,7 @@ ins_pipe(pipe_slow); %} -instruct vmulF_mem(regF dst, regF src1, memory src2) %{ +instruct mulF_reg_mem(regF dst, regF src1, memory src2) %{ predicate(UseAVX > 0); match(Set dst (MulF src1 (LoadF src2))); @@ -1197,7 +1197,7 @@ ins_pipe(pipe_slow); %} -instruct vmulF_imm(regF dst, regF src, immF con) %{ +instruct mulF_reg_imm(regF dst, regF src, immF con) %{ predicate(UseAVX > 0); match(Set dst (MulF src con)); @@ -1244,7 +1244,7 @@ ins_pipe(pipe_slow); %} -instruct vmulD_reg(regD dst, regD src1, regD src2) %{ +instruct mulD_reg_reg(regD dst, regD src1, regD src2) %{ predicate(UseAVX > 0); match(Set dst (MulD src1 src2)); @@ -1256,7 +1256,7 @@ ins_pipe(pipe_slow); %} -instruct vmulD_mem(regD dst, regD src1, memory src2) %{ +instruct mulD_reg_mem(regD dst, regD src1, memory src2) %{ predicate(UseAVX > 0); match(Set dst (MulD src1 (LoadD src2))); @@ -1268,7 +1268,7 @@ ins_pipe(pipe_slow); %} -instruct vmulD_imm(regD dst, regD src, immD con) %{ +instruct mulD_reg_imm(regD dst, regD src, immD con) %{ predicate(UseAVX > 0); match(Set dst (MulD src con)); @@ -1315,7 +1315,7 @@ ins_pipe(pipe_slow); %} -instruct vdivF_reg(regF dst, regF src1, regF src2) %{ +instruct divF_reg_reg(regF dst, regF src1, regF src2) %{ predicate(UseAVX > 0); match(Set dst (DivF src1 src2)); @@ -1327,7 +1327,7 @@ ins_pipe(pipe_slow); %} -instruct vdivF_mem(regF dst, regF src1, memory src2) %{ +instruct divF_reg_mem(regF dst, regF src1, memory src2) %{ predicate(UseAVX > 0); match(Set dst (DivF src1 (LoadF src2))); @@ -1339,7 +1339,7 @@ ins_pipe(pipe_slow); %} -instruct vdivF_imm(regF dst, regF src, immF con) %{ +instruct divF_reg_imm(regF dst, regF src, immF con) %{ predicate(UseAVX > 0); match(Set dst (DivF src con)); @@ -1386,7 +1386,7 @@ ins_pipe(pipe_slow); %} -instruct vdivD_reg(regD dst, regD src1, regD src2) %{ +instruct divD_reg_reg(regD dst, regD src1, regD src2) %{ predicate(UseAVX > 0); match(Set dst (DivD src1 src2)); @@ -1398,7 +1398,7 @@ ins_pipe(pipe_slow); %} -instruct vdivD_mem(regD dst, regD src1, memory src2) %{ +instruct divD_reg_mem(regD dst, regD src1, memory src2) %{ predicate(UseAVX > 0); match(Set dst (DivD src1 (LoadD src2))); @@ -1410,7 +1410,7 @@ ins_pipe(pipe_slow); %} -instruct vdivD_imm(regD dst, regD src, immD con) %{ +instruct divD_reg_imm(regD dst, regD src, immD con) %{ predicate(UseAVX > 0); match(Set dst (DivD src con)); @@ -1433,7 +1433,7 @@ ins_pipe(pipe_slow); %} -instruct vabsF_reg(regF dst, regF src) %{ +instruct absF_reg_reg(regF dst, regF src) %{ predicate(UseAVX > 0); match(Set dst (AbsF src)); ins_cost(150); @@ -1457,7 +1457,7 @@ ins_pipe(pipe_slow); %} -instruct vabsD_reg(regD dst, regD src) %{ +instruct absD_reg_reg(regD dst, regD src) %{ predicate(UseAVX > 0); match(Set dst (AbsD src)); ins_cost(150); @@ -1481,7 +1481,7 @@ ins_pipe(pipe_slow); %} -instruct vnegF_reg(regF dst, regF src) %{ +instruct negF_reg_reg(regF dst, regF src) %{ predicate(UseAVX > 0); match(Set dst (NegF src)); ins_cost(150); @@ -1505,7 +1505,7 @@ ins_pipe(pipe_slow); %} -instruct vnegD_reg(regD dst, regD src) %{ +instruct negD_reg_reg(regD dst, regD src) %{ predicate(UseAVX > 0); match(Set dst (NegD src)); ins_cost(150); @@ -1719,12 +1719,12 @@ format %{ "movd $dst,$src\n\t" "punpcklbw $dst,$dst\n\t" "pshuflw $dst,$dst,0x00\n\t" - "movlhps $dst,$dst\t! replicate16B" %} + "punpcklqdq $dst,$dst\t! replicate16B" %} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); __ punpcklbw($dst$$XMMRegister, $dst$$XMMRegister); __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -1735,14 +1735,14 @@ format %{ "movd $dst,$src\n\t" "punpcklbw $dst,$dst\n\t" "pshuflw $dst,$dst,0x00\n\t" - "movlhps $dst,$dst\n\t" - "vinsertf128h $dst,$dst,$dst\t! replicate32B" %} + "punpcklqdq $dst,$dst\n\t" + "vinserti128h $dst,$dst,$dst\t! replicate32B" %} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); __ punpcklbw($dst$$XMMRegister, $dst$$XMMRegister); __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -1751,9 +1751,9 @@ instruct Repl4B_imm(vecS dst, immI con) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateB con)); - format %{ "movss $dst,[$constantaddress]\t! replicate4B($con)" %} + format %{ "movdl $dst,[$constantaddress]\t! replicate4B($con)" %} ins_encode %{ - __ movflt($dst$$XMMRegister, $constantaddress(replicate4_imm($con$$constant, 1))); + __ movdl($dst$$XMMRegister, $constantaddress(replicate4_imm($con$$constant, 1))); %} ins_pipe( pipe_slow ); %} @@ -1761,9 +1761,9 @@ instruct Repl8B_imm(vecD dst, immI con) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (ReplicateB con)); - format %{ "movsd $dst,[$constantaddress]\t! replicate8B($con)" %} + format %{ "movq $dst,[$constantaddress]\t! replicate8B($con)" %} ins_encode %{ - __ movdbl($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 1))); + __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 1))); %} ins_pipe( pipe_slow ); %} @@ -1771,11 +1771,11 @@ instruct Repl16B_imm(vecX dst, immI con) %{ predicate(n->as_Vector()->length() == 16); match(Set dst (ReplicateB con)); - format %{ "movsd $dst,[$constantaddress]\t! replicate16B($con)\n\t" - "movlhps $dst,$dst" %} + format %{ "movq $dst,[$constantaddress]\n\t" + "punpcklqdq $dst,$dst\t! replicate16B($con)" %} ins_encode %{ - __ movdbl($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 1))); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); + __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 1))); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -1783,13 +1783,13 @@ instruct Repl32B_imm(vecY dst, immI con) %{ predicate(n->as_Vector()->length() == 32); match(Set dst (ReplicateB con)); - format %{ "movsd $dst,[$constantaddress]\t! lreplicate32B($con)\n\t" - "movlhps $dst,$dst\n\t" - "vinsertf128h $dst,$dst,$dst" %} + format %{ "movq $dst,[$constantaddress]\n\t" + "punpcklqdq $dst,$dst\n\t" + "vinserti128h $dst,$dst,$dst\t! lreplicate32B($con)" %} ins_encode %{ - __ movdbl($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 1))); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 1))); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -1828,11 +1828,11 @@ instruct Repl32B_zero(vecY dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 32); match(Set dst (ReplicateB zero)); - format %{ "vxorpd $dst,$dst,$dst\t! replicate32B zero" %} + format %{ "vpxor $dst,$dst,$dst\t! replicate32B zero" %} ins_encode %{ // Use vxorpd since AVX does not have vpxor for 256-bit (AVX2 will have it). bool vector256 = true; - __ vxorpd($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector256); + __ vpxor($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector256); %} ins_pipe( fpu_reg_reg ); %} @@ -1867,11 +1867,11 @@ match(Set dst (ReplicateS src)); format %{ "movd $dst,$src\n\t" "pshuflw $dst,$dst,0x00\n\t" - "movlhps $dst,$dst\t! replicate8S" %} + "punpcklqdq $dst,$dst\t! replicate8S" %} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -1881,13 +1881,13 @@ match(Set dst (ReplicateS src)); format %{ "movd $dst,$src\n\t" "pshuflw $dst,$dst,0x00\n\t" - "movlhps $dst,$dst\n\t" - "vinsertf128h $dst,$dst,$dst\t! replicate16S" %} + "punpcklqdq $dst,$dst\n\t" + "vinserti128h $dst,$dst,$dst\t! replicate16S" %} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -1896,9 +1896,9 @@ instruct Repl2S_imm(vecS dst, immI con) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateS con)); - format %{ "movss $dst,[$constantaddress]\t! replicate2S($con)" %} + format %{ "movdl $dst,[$constantaddress]\t! replicate2S($con)" %} ins_encode %{ - __ movflt($dst$$XMMRegister, $constantaddress(replicate4_imm($con$$constant, 2))); + __ movdl($dst$$XMMRegister, $constantaddress(replicate4_imm($con$$constant, 2))); %} ins_pipe( fpu_reg_reg ); %} @@ -1906,9 +1906,9 @@ instruct Repl4S_imm(vecD dst, immI con) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateS con)); - format %{ "movsd $dst,[$constantaddress]\t! replicate4S($con)" %} + format %{ "movq $dst,[$constantaddress]\t! replicate4S($con)" %} ins_encode %{ - __ movdbl($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 2))); + __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 2))); %} ins_pipe( fpu_reg_reg ); %} @@ -1916,11 +1916,11 @@ instruct Repl8S_imm(vecX dst, immI con) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (ReplicateS con)); - format %{ "movsd $dst,[$constantaddress]\t! replicate8S($con)\n\t" - "movlhps $dst,$dst" %} + format %{ "movq $dst,[$constantaddress]\n\t" + "punpcklqdq $dst,$dst\t! replicate8S($con)" %} ins_encode %{ - __ movdbl($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 2))); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); + __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 2))); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -1928,13 +1928,13 @@ instruct Repl16S_imm(vecY dst, immI con) %{ predicate(n->as_Vector()->length() == 16); match(Set dst (ReplicateS con)); - format %{ "movsd $dst,[$constantaddress]\t! replicate16S($con)\n\t" - "movlhps $dst,$dst\n\t" - "vinsertf128h $dst,$dst,$dst" %} + format %{ "movq $dst,[$constantaddress]\n\t" + "punpcklqdq $dst,$dst\n\t" + "vinserti128h $dst,$dst,$dst\t! replicate16S($con)" %} ins_encode %{ - __ movdbl($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 2))); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 2))); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -1973,11 +1973,11 @@ instruct Repl16S_zero(vecY dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 16); match(Set dst (ReplicateS zero)); - format %{ "vxorpd $dst,$dst,$dst\t! replicate16S zero" %} + format %{ "vpxor $dst,$dst,$dst\t! replicate16S zero" %} ins_encode %{ // Use vxorpd since AVX does not have vpxor for 256-bit (AVX2 will have it). bool vector256 = true; - __ vxorpd($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector256); + __ vpxor($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector256); %} ins_pipe( fpu_reg_reg ); %} @@ -2012,11 +2012,11 @@ match(Set dst (ReplicateI src)); format %{ "movd $dst,$src\n\t" "pshufd $dst,$dst,0x00\n\t" - "vinsertf128h $dst,$dst,$dst\t! replicate8I" %} + "vinserti128h $dst,$dst,$dst\t! replicate8I" %} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); __ pshufd($dst$$XMMRegister, $dst$$XMMRegister, 0x00); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -2025,9 +2025,9 @@ instruct Repl2I_imm(vecD dst, immI con) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateI con)); - format %{ "movsd $dst,[$constantaddress]\t! replicate2I($con)" %} + format %{ "movq $dst,[$constantaddress]\t! replicate2I($con)" %} ins_encode %{ - __ movdbl($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 4))); + __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 4))); %} ins_pipe( fpu_reg_reg ); %} @@ -2035,11 +2035,11 @@ instruct Repl4I_imm(vecX dst, immI con) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateI con)); - format %{ "movsd $dst,[$constantaddress]\t! replicate4I($con)\n\t" - "movlhps $dst,$dst" %} + format %{ "movq $dst,[$constantaddress]\t! replicate4I($con)\n\t" + "punpcklqdq $dst,$dst" %} ins_encode %{ - __ movdbl($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 4))); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); + __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 4))); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -2047,13 +2047,13 @@ instruct Repl8I_imm(vecY dst, immI con) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (ReplicateI con)); - format %{ "movsd $dst,[$constantaddress]\t! replicate8I($con)\n\t" - "movlhps $dst,$dst\n\t" - "vinsertf128h $dst,$dst,$dst" %} + format %{ "movq $dst,[$constantaddress]\t! replicate8I($con)\n\t" + "punpcklqdq $dst,$dst\n\t" + "vinserti128h $dst,$dst,$dst" %} ins_encode %{ - __ movdbl($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 4))); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 4))); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -2061,7 +2061,7 @@ // Integer could be loaded into xmm register directly from memory. instruct Repl2I_mem(vecD dst, memory mem) %{ predicate(n->as_Vector()->length() == 2); - match(Set dst (ReplicateI (LoadVector mem))); + match(Set dst (ReplicateI (LoadI mem))); format %{ "movd $dst,$mem\n\t" "pshufd $dst,$dst,0x00\t! replicate2I" %} ins_encode %{ @@ -2073,7 +2073,7 @@ instruct Repl4I_mem(vecX dst, memory mem) %{ predicate(n->as_Vector()->length() == 4); - match(Set dst (ReplicateI (LoadVector mem))); + match(Set dst (ReplicateI (LoadI mem))); format %{ "movd $dst,$mem\n\t" "pshufd $dst,$dst,0x00\t! replicate4I" %} ins_encode %{ @@ -2085,14 +2085,14 @@ instruct Repl8I_mem(vecY dst, memory mem) %{ predicate(n->as_Vector()->length() == 8); - match(Set dst (ReplicateI (LoadVector mem))); + match(Set dst (ReplicateI (LoadI mem))); format %{ "movd $dst,$mem\n\t" "pshufd $dst,$dst,0x00\n\t" - "vinsertf128h $dst,$dst,$dst\t! replicate8I" %} + "vinserti128h $dst,$dst,$dst\t! replicate8I" %} ins_encode %{ __ movdl($dst$$XMMRegister, $mem$$Address); __ pshufd($dst$$XMMRegister, $dst$$XMMRegister, 0x00); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -2121,11 +2121,11 @@ instruct Repl8I_zero(vecY dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (ReplicateI zero)); - format %{ "vxorpd $dst,$dst,$dst\t! replicate8I zero" %} + format %{ "vpxor $dst,$dst,$dst\t! replicate8I zero" %} ins_encode %{ // Use vxorpd since AVX does not have vpxor for 256-bit (AVX2 will have it). bool vector256 = true; - __ vxorpd($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector256); + __ vpxor($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector256); %} ins_pipe( fpu_reg_reg ); %} @@ -2136,10 +2136,10 @@ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateL src)); format %{ "movdq $dst,$src\n\t" - "movlhps $dst,$dst\t! replicate2L" %} + "punpcklqdq $dst,$dst\t! replicate2L" %} ins_encode %{ __ movdq($dst$$XMMRegister, $src$$Register); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -2148,12 +2148,12 @@ predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateL src)); format %{ "movdq $dst,$src\n\t" - "movlhps $dst,$dst\n\t" - "vinsertf128h $dst,$dst,$dst\t! replicate4L" %} + "punpcklqdq $dst,$dst\n\t" + "vinserti128h $dst,$dst,$dst\t! replicate4L" %} ins_encode %{ __ movdq($dst$$XMMRegister, $src$$Register); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -2165,12 +2165,12 @@ format %{ "movdl $dst,$src.lo\n\t" "movdl $tmp,$src.hi\n\t" "punpckldq $dst,$tmp\n\t" - "movlhps $dst,$dst\t! replicate2L"%} + "punpcklqdq $dst,$dst\t! replicate2L"%} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); __ movdl($tmp$$XMMRegister, HIGH_FROM_LOW($src$$Register)); __ punpckldq($dst$$XMMRegister, $tmp$$XMMRegister); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -2182,14 +2182,14 @@ format %{ "movdl $dst,$src.lo\n\t" "movdl $tmp,$src.hi\n\t" "punpckldq $dst,$tmp\n\t" - "movlhps $dst,$dst\n\t" - "vinsertf128h $dst,$dst,$dst\t! replicate4L" %} + "punpcklqdq $dst,$dst\n\t" + "vinserti128h $dst,$dst,$dst\t! replicate4L" %} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); __ movdl($tmp$$XMMRegister, HIGH_FROM_LOW($src$$Register)); __ punpckldq($dst$$XMMRegister, $tmp$$XMMRegister); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -2199,11 +2199,11 @@ instruct Repl2L_imm(vecX dst, immL con) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateL con)); - format %{ "movsd $dst,[$constantaddress]\t! replicate2L($con)\n\t" - "movlhps $dst,$dst" %} + format %{ "movq $dst,[$constantaddress]\n\t" + "punpcklqdq $dst,$dst\t! replicate2L($con)" %} ins_encode %{ - __ movdbl($dst$$XMMRegister, $constantaddress($con)); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); + __ movq($dst$$XMMRegister, $constantaddress($con)); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -2211,13 +2211,13 @@ instruct Repl4L_imm(vecY dst, immL con) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateL con)); - format %{ "movsd $dst,[$constantaddress]\t! replicate4L($con)\n\t" - "movlhps $dst,$dst\n\t" - "vinsertf128h $dst,$dst,$dst" %} + format %{ "movq $dst,[$constantaddress]\n\t" + "punpcklqdq $dst,$dst\n\t" + "vinserti128h $dst,$dst,$dst\t! replicate4L($con)" %} ins_encode %{ - __ movdbl($dst$$XMMRegister, $constantaddress($con)); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ movq($dst$$XMMRegister, $constantaddress($con)); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -2225,26 +2225,26 @@ // Long could be loaded into xmm register directly from memory. instruct Repl2L_mem(vecX dst, memory mem) %{ predicate(n->as_Vector()->length() == 2); - match(Set dst (ReplicateL (LoadVector mem))); + match(Set dst (ReplicateL (LoadL mem))); format %{ "movq $dst,$mem\n\t" - "movlhps $dst,$dst\t! replicate2L" %} + "punpcklqdq $dst,$dst\t! replicate2L" %} ins_encode %{ __ movq($dst$$XMMRegister, $mem$$Address); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} instruct Repl4L_mem(vecY dst, memory mem) %{ predicate(n->as_Vector()->length() == 4); - match(Set dst (ReplicateL (LoadVector mem))); + match(Set dst (ReplicateL (LoadL mem))); format %{ "movq $dst,$mem\n\t" - "movlhps $dst,$dst\n\t" - "vinsertf128h $dst,$dst,$dst\t! replicate4L" %} + "punpcklqdq $dst,$dst\n\t" + "vinserti128h $dst,$dst,$dst\t! replicate4L" %} ins_encode %{ __ movq($dst$$XMMRegister, $mem$$Address); - __ movlhps($dst$$XMMRegister, $dst$$XMMRegister); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -2263,11 +2263,11 @@ instruct Repl4L_zero(vecY dst, immL0 zero) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateL zero)); - format %{ "vxorpd $dst,$dst,$dst\t! replicate4L zero" %} + format %{ "vpxor $dst,$dst,$dst\t! replicate4L zero" %} ins_encode %{ // Use vxorpd since AVX does not have vpxor for 256-bit (AVX2 will have it). bool vector256 = true; - __ vxorpd($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector256); + __ vpxor($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister, vector256); %} ins_pipe( fpu_reg_reg ); %} diff -r e3619706a725 -r bd54fe36b5e5 src/os/solaris/dtrace/libjvm_db.c --- a/src/os/solaris/dtrace/libjvm_db.c Mon Jul 23 12:38:08 2012 -0700 +++ b/src/os/solaris/dtrace/libjvm_db.c Mon Jul 23 12:54:20 2012 -0700 @@ -516,7 +516,7 @@ err = read_pointer(J, methodOopPtr + OFFSET_methodOopDesc_constMethod, &constMethod); CHECK_FAIL(err); - err = read_pointer(J->P, constMethod + OFFSET_constMethodOopDesc_constants, &constantPool); + err = read_pointer(J, constMethod + OFFSET_constMethodOopDesc_constants, &constantPool); CHECK_FAIL(err); /* To get name string */ diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/c1/c1_GraphBuilder.cpp --- a/src/share/vm/c1/c1_GraphBuilder.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -3505,8 +3505,10 @@ } // now perform tests that are based on flag settings - if (callee->should_inline()) { + if (callee->force_inline() || callee->should_inline()) { // ignore heuristic controls on inlining + if (callee->force_inline()) + CompileTask::print_inlining(callee, scope()->level(), bci(), "force inline by annotation"); } else { if (inline_level() > MaxInlineLevel ) INLINE_BAILOUT("too-deep inlining"); if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("too-deep recursive inlining"); @@ -3531,7 +3533,7 @@ } #ifndef PRODUCT - // printing + // printing if (PrintInlining) { print_inline_result(callee, true); } diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/ci/ciMethod.cpp --- a/src/share/vm/ci/ciMethod.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/ci/ciMethod.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, 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 @@ -79,7 +79,7 @@ _max_locals = h_m()->max_locals(); _code_size = h_m()->code_size(); _intrinsic_id = h_m()->intrinsic_id(); - _handler_count = h_m()->exception_table()->length() / 4; + _handler_count = h_m()->exception_table_length(); _uses_monitors = h_m()->access_flags().has_monitor_bytecodes(); _balanced_monitors = !_uses_monitors || h_m()->access_flags().is_monitor_matching(); _is_c1_compilable = !h_m()->is_not_c1_compilable(); @@ -198,7 +198,7 @@ } // And load the exception table. - typeArrayOop exc_table = me->exception_table(); + ExceptionTable exc_table(me); // Allocate one extra spot in our list of exceptions. This // last entry will be used to represent the possibility that @@ -209,13 +209,12 @@ * (_handler_count + 1)); if (_handler_count > 0) { for (int i=0; i<_handler_count; i++) { - int base = i*4; _exception_handlers[i] = new (arena) ciExceptionHandler( holder(), - /* start */ exc_table->int_at(base), - /* limit */ exc_table->int_at(base+1), - /* goto pc */ exc_table->int_at(base+2), - /* cp index */ exc_table->int_at(base+3)); + /* start */ exc_table.start_pc(i), + /* limit */ exc_table.end_pc(i), + /* goto pc */ exc_table.handler_pc(i), + /* cp index */ exc_table.catch_type_index(i)); } } diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/ci/ciMethod.hpp --- a/src/share/vm/ci/ciMethod.hpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/ci/ciMethod.hpp Mon Jul 23 12:54:20 2012 -0700 @@ -160,6 +160,8 @@ // Code size for inlining decisions. int code_size_for_inlining(); + bool force_inline() { return get_methodOop()->force_inline(); } + int comp_level(); int highest_osr_comp_level(); diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/classfile/classFileParser.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -318,6 +318,13 @@ bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); } +inline Symbol* check_symbol_at(constantPoolHandle cp, int index) { + if (valid_cp_range(index, cp->length()) && cp->tag_at(index).is_utf8()) + return cp->symbol_at(index); + else + return NULL; +} + constantPoolHandle ClassFileParser::parse_constant_pool(Handle class_loader, TRAPS) { ClassFileStream* cfs = stream(); constantPoolHandle nullHandle; @@ -902,6 +909,7 @@ bool* is_synthetic_addr, u2* generic_signature_index_addr, typeArrayHandle* field_annotations, + ClassFileParser::FieldAnnotationCollector* parsed_annotations, TRAPS) { ClassFileStream* cfs = stream(); assert(attributes_count > 0, "length should be greater than 0"); @@ -1142,12 +1150,14 @@ bool is_synthetic = false; u2 generic_signature_index = 0; bool is_static = access_flags.is_static(); + FieldAnnotationCollector parsed_annotations; u2 attributes_count = cfs->get_u2_fast(); if (attributes_count > 0) { parse_field_attributes(cp, attributes_count, is_static, signature_index, &constantvalue_index, &is_synthetic, &generic_signature_index, &field_annotations, + &parsed_annotations, CHECK_(nullHandle)); if (field_annotations.not_null()) { if (fields_annotations->is_null()) { @@ -1173,6 +1183,8 @@ signature_index, constantvalue_index, 0); + if (parsed_annotations.has_any_annotations()) + parsed_annotations.apply_to(field); BasicType type = cp->basic_type_for_signature_at(signature_index); @@ -1284,42 +1296,38 @@ } -typeArrayHandle ClassFileParser::parse_exception_table(u4 code_length, - u4 exception_table_length, - constantPoolHandle cp, - TRAPS) { +u2* ClassFileParser::parse_exception_table(u4 code_length, + u4 exception_table_length, + constantPoolHandle cp, + TRAPS) { ClassFileStream* cfs = stream(); - typeArrayHandle nullHandle; - - // 4-tuples of ints [start_pc, end_pc, handler_pc, catch_type index] - typeArrayOop eh = oopFactory::new_permanent_intArray(exception_table_length*4, CHECK_(nullHandle)); - typeArrayHandle exception_handlers = typeArrayHandle(THREAD, eh); - - int index = 0; - cfs->guarantee_more(8 * exception_table_length, CHECK_(nullHandle)); // start_pc, end_pc, handler_pc, catch_type_index - for (unsigned int i = 0; i < exception_table_length; i++) { - u2 start_pc = cfs->get_u2_fast(); - u2 end_pc = cfs->get_u2_fast(); - u2 handler_pc = cfs->get_u2_fast(); - u2 catch_type_index = cfs->get_u2_fast(); - // Will check legal target after parsing code array in verifier. - if (_need_verify) { + + u2* exception_table_start = cfs->get_u2_buffer(); + assert(exception_table_start != NULL, "null exception table"); + cfs->guarantee_more(8 * exception_table_length, CHECK_NULL); // start_pc, end_pc, handler_pc, catch_type_index + // Will check legal target after parsing code array in verifier. + if (_need_verify) { + for (unsigned int i = 0; i < exception_table_length; i++) { + u2 start_pc = cfs->get_u2_fast(); + u2 end_pc = cfs->get_u2_fast(); + u2 handler_pc = cfs->get_u2_fast(); + u2 catch_type_index = cfs->get_u2_fast(); guarantee_property((start_pc < end_pc) && (end_pc <= code_length), - "Illegal exception table range in class file %s", CHECK_(nullHandle)); + "Illegal exception table range in class file %s", + CHECK_NULL); guarantee_property(handler_pc < code_length, - "Illegal exception table handler in class file %s", CHECK_(nullHandle)); + "Illegal exception table handler in class file %s", + CHECK_NULL); if (catch_type_index != 0) { guarantee_property(valid_cp_range(catch_type_index, cp->length()) && is_klass_reference(cp, catch_type_index), - "Catch type in exception table has bad constant type in class file %s", CHECK_(nullHandle)); + "Catch type in exception table has bad constant type in class file %s", CHECK_NULL); } } - exception_handlers->int_at_put(index++, start_pc); - exception_handlers->int_at_put(index++, end_pc); - exception_handlers->int_at_put(index++, handler_pc); - exception_handlers->int_at_put(index++, catch_type_index); + } else { + cfs->skip_u2_fast(exception_table_length * 4); } - return exception_handlers; + return exception_table_start; } void ClassFileParser::parse_linenumber_table( @@ -1638,12 +1646,158 @@ name->as_C_string(), _class_name->as_C_string(), sig->as_C_string()); } +// Skip an annotation. Return >=limit if there is any problem. +int ClassFileParser::skip_annotation(u1* buffer, int limit, int index) { + // annotation := atype:u2 do(nmem:u2) {member:u2 value} + // value := switch (tag:u1) { ... } + index += 2; // skip atype + if ((index += 2) >= limit) return limit; // read nmem + int nmem = Bytes::get_Java_u2(buffer+index-2); + while (--nmem >= 0 && index < limit) { + index += 2; // skip member + index = skip_annotation_value(buffer, limit, index); + } + return index; +} + +// Skip an annotation value. Return >=limit if there is any problem. +int ClassFileParser::skip_annotation_value(u1* buffer, int limit, int index) { + // value := switch (tag:u1) { + // case B, C, I, S, Z, D, F, J, c: con:u2; + // case e: e_class:u2 e_name:u2; + // case s: s_con:u2; + // case [: do(nval:u2) {value}; + // case @: annotation; + // case s: s_con:u2; + // } + if ((index += 1) >= limit) return limit; // read tag + u1 tag = buffer[index-1]; + switch (tag) { + case 'B': case 'C': case 'I': case 'S': case 'Z': + case 'D': case 'F': case 'J': case 'c': case 's': + index += 2; // skip con or s_con + break; + case 'e': + index += 4; // skip e_class, e_name + break; + case '[': + { + if ((index += 2) >= limit) return limit; // read nval + int nval = Bytes::get_Java_u2(buffer+index-2); + while (--nval >= 0 && index < limit) { + index = skip_annotation_value(buffer, limit, index); + } + } + break; + case '@': + index = skip_annotation(buffer, limit, index); + break; + default: + assert(false, "annotation tag"); + return limit; // bad tag byte + } + return index; +} + +// Sift through annotations, looking for those significant to the VM: +void ClassFileParser::parse_annotations(u1* buffer, int limit, + constantPoolHandle cp, + ClassFileParser::AnnotationCollector* coll, + TRAPS) { + // annotations := do(nann:u2) {annotation} + int index = 0; + if ((index += 2) >= limit) return; // read nann + int nann = Bytes::get_Java_u2(buffer+index-2); + enum { // initial annotation layout + atype_off = 0, // utf8 such as 'Ljava/lang/annotation/Retention;' + count_off = 2, // u2 such as 1 (one value) + member_off = 4, // utf8 such as 'value' + tag_off = 6, // u1 such as 'c' (type) or 'e' (enum) + e_tag_val = 'e', + e_type_off = 7, // utf8 such as 'Ljava/lang/annotation/RetentionPolicy;' + e_con_off = 9, // utf8 payload, such as 'SOURCE', 'CLASS', 'RUNTIME' + e_size = 11, // end of 'e' annotation + c_tag_val = 'c', + c_con_off = 7, // utf8 payload, such as 'I' or 'Ljava/lang/String;' + c_size = 9, // end of 'c' annotation + min_size = 6 // smallest possible size (zero members) + }; + while ((--nann) >= 0 && (index-2 + min_size <= limit)) { + int index0 = index; + index = skip_annotation(buffer, limit, index); + u1* abase = buffer + index0; + int atype = Bytes::get_Java_u2(abase + atype_off); + int count = Bytes::get_Java_u2(abase + count_off); + Symbol* aname = check_symbol_at(cp, atype); + if (aname == NULL) break; // invalid annotation name + Symbol* member = NULL; + if (count >= 1) { + int member_index = Bytes::get_Java_u2(abase + member_off); + member = check_symbol_at(cp, member_index); + if (member == NULL) break; // invalid member name + } + + // Here is where parsing particular annotations will take place. + AnnotationCollector::ID id = coll->annotation_index(aname); + if (id == AnnotationCollector::_unknown) continue; + coll->set_annotation(id); + // If there are no values, just set the bit and move on: + if (count == 0) continue; + + // For the record, here is how annotation payloads can be collected. + // Suppose we want to capture @Retention.value. Here is how: + //if (id == AnnotationCollector::_class_Retention) { + // Symbol* payload = NULL; + // if (count == 1 + // && e_size == (index0 - index) // match size + // && e_tag_val == *(abase + tag_off) + // && (check_symbol_at(cp, Bytes::get_Java_u2(abase + e_type_off)) + // == vmSymbols::RetentionPolicy_signature()) + // && member == vmSymbols::value_name()) { + // payload = check_symbol_at(cp, Bytes::get_Java_u2(abase + e_con_off)); + // } + // check_property(payload != NULL, + // "Invalid @Retention annotation at offset %u in class file %s", + // index0, CHECK); + // if (payload != NULL) { + // payload->increment_refcount(); + // coll->_class_RetentionPolicy = payload; + // } + //} + } +} + +ClassFileParser::AnnotationCollector::ID ClassFileParser::AnnotationCollector::annotation_index(Symbol* name) { + vmSymbols::SID sid = vmSymbols::find_sid(name); + switch (sid) { + case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_ForceInline_signature): + if (_location != _in_method) break; // only allow for methods + return _method_ForceInline; + default: break; + } + return AnnotationCollector::_unknown; +} + +void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) { + fatal("no field annotations yet"); +} + +void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) { + if (has_annotation(_method_ForceInline)) + m->set_force_inline(true); +} + +void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k) { + fatal("no class annotations yet"); +} + + #define MAX_ARGS_SIZE 255 #define MAX_CODE_SIZE 65535 #define INITIAL_MAX_LVT_NUMBER 256 // Note: the parse_method below is big and clunky because all parsing of the code and exceptions -// attribute is inlined. This is curbersome to avoid since we inline most of the parts in the +// attribute is inlined. This is cumbersome to avoid since we inline most of the parts in the // methodOop to save footprint, so we only know the size of the resulting methodOop when the // entire method attribute is parsed. // @@ -1712,6 +1866,7 @@ u4 code_length = 0; u1* code_start = 0; u2 exception_table_length = 0; + u2* exception_table_start = NULL; typeArrayHandle exception_handlers(THREAD, Universe::the_empty_int_array()); u2 checked_exceptions_length = 0; u2* checked_exceptions_start = NULL; @@ -1733,6 +1888,7 @@ // stackmap attribute - JDK1.5 typeArrayHandle stackmap_data; u2 generic_signature_index = 0; + MethodAnnotationCollector parsed_annotations; u1* runtime_visible_annotations = NULL; int runtime_visible_annotations_length = 0; u1* runtime_invisible_annotations = NULL; @@ -1798,7 +1954,7 @@ cfs->guarantee_more(2, CHECK_(nullHandle)); // exception_table_length exception_table_length = cfs->get_u2_fast(); if (exception_table_length > 0) { - exception_handlers = + exception_table_start = parse_exception_table(code_length, exception_table_length, cp, CHECK_(nullHandle)); } @@ -1959,6 +2115,7 @@ runtime_visible_annotations_length = method_attribute_length; runtime_visible_annotations = cfs->get_u1_buffer(); assert(runtime_visible_annotations != NULL, "null visible annotations"); + parse_annotations(runtime_visible_annotations, runtime_visible_annotations_length, cp, &parsed_annotations, CHECK_(nullHandle)); cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle)); } else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { runtime_invisible_annotations_length = method_attribute_length; @@ -2002,9 +2159,13 @@ } // All sizing information for a methodOop is finally available, now create it - methodOop m_oop = oopFactory::new_method(code_length, access_flags, linenumber_table_length, - total_lvt_length, checked_exceptions_length, - oopDesc::IsSafeConc, CHECK_(nullHandle)); + methodOop m_oop = oopFactory::new_method(code_length, access_flags, + linenumber_table_length, + total_lvt_length, + exception_table_length, + checked_exceptions_length, + oopDesc::IsSafeConc, + CHECK_(nullHandle)); methodHandle m (THREAD, m_oop); ClassLoadingService::add_class_method_size(m_oop->size()*HeapWordSize); @@ -2035,16 +2196,15 @@ // Fill in code attribute information m->set_max_stack(max_stack); m->set_max_locals(max_locals); - m->constMethod()->set_stackmap_data(stackmap_data()); /** - * The exception_table field is the flag used to indicate + * The stackmap_data field is the flag used to indicate * that the methodOop and it's associated constMethodOop are partially * initialized and thus are exempt from pre/post GC verification. Once * the field is set, the oops are considered fully initialized so make * sure that the oops can pass verification when this field is set. */ - m->set_exception_table(exception_handlers()); + m->constMethod()->set_stackmap_data(stackmap_data()); // Copy byte codes m->set_code(code_start); @@ -2055,6 +2215,14 @@ linenumber_table->buffer(), linenumber_table_length); } + // Copy exception table + if (exception_table_length > 0) { + int size = + exception_table_length * sizeof(ExceptionTableElement) / sizeof(u2); + copy_u2_with_conversion((u2*) m->exception_table_start(), + exception_table_start, size); + } + // Copy checked exceptions if (checked_exceptions_length > 0) { int size = checked_exceptions_length * sizeof(CheckedExceptionElement) / sizeof(u2); @@ -2136,6 +2304,8 @@ clear_hashtable(lvt_Hash); } + if (parsed_annotations.has_any_annotations()) + parsed_annotations.apply_to(m); *method_annotations = assemble_annotations(runtime_visible_annotations, runtime_visible_annotations_length, runtime_invisible_annotations, @@ -2314,7 +2484,7 @@ } -void ClassFileParser::parse_classfile_sourcefile_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS) { +void ClassFileParser::parse_classfile_sourcefile_attribute(constantPoolHandle cp, TRAPS) { ClassFileStream* cfs = stream(); cfs->guarantee_more(2, CHECK); // sourcefile_index u2 sourcefile_index = cfs->get_u2_fast(); @@ -2323,13 +2493,12 @@ cp->tag_at(sourcefile_index).is_utf8(), "Invalid SourceFile attribute at constant pool index %u in class file %s", sourcefile_index, CHECK); - k->set_source_file_name(cp->symbol_at(sourcefile_index)); + set_class_sourcefile(cp->symbol_at(sourcefile_index)); } void ClassFileParser::parse_classfile_source_debug_extension_attribute(constantPoolHandle cp, - instanceKlassHandle k, int length, TRAPS) { ClassFileStream* cfs = stream(); u1* sde_buffer = cfs->get_u1_buffer(); @@ -2337,7 +2506,13 @@ // Don't bother storing it if there is no way to retrieve it if (JvmtiExport::can_get_source_debug_extension()) { - k->set_source_debug_extension((char*)sde_buffer, length); + assert((length+1) > length, "Overflow checking"); + u1* sde = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, u1, length+1); + for (int i = 0; i < length; i++) { + sde[i] = sde_buffer[i]; + } + sde[length] = '\0'; + set_class_sde_buffer((char*)sde, length); } // Got utf8 string, set stream position forward cfs->skip_u1(length, CHECK); @@ -2353,7 +2528,7 @@ u2 enclosing_method_class_index, u2 enclosing_method_method_index, constantPoolHandle cp, - instanceKlassHandle k, TRAPS) { + TRAPS) { ClassFileStream* cfs = stream(); u1* current_mark = cfs->current(); u2 length = 0; @@ -2444,7 +2619,7 @@ assert(index == size, "wrong size"); // Update instanceKlass with inner class info. - k->set_inner_classes(inner_classes()); + set_class_inner_classes(inner_classes); // Restore buffer's current position. cfs->set_current(current_mark); @@ -2452,11 +2627,11 @@ return length; } -void ClassFileParser::parse_classfile_synthetic_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS) { - k->set_is_synthetic(); +void ClassFileParser::parse_classfile_synthetic_attribute(constantPoolHandle cp, TRAPS) { + set_class_synthetic_flag(true); } -void ClassFileParser::parse_classfile_signature_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS) { +void ClassFileParser::parse_classfile_signature_attribute(constantPoolHandle cp, TRAPS) { ClassFileStream* cfs = stream(); u2 signature_index = cfs->get_u2(CHECK); check_property( @@ -2464,10 +2639,10 @@ cp->tag_at(signature_index).is_utf8(), "Invalid constant pool index %u in Signature attribute in class file %s", signature_index, CHECK); - k->set_generic_signature(cp->symbol_at(signature_index)); + set_class_generic_signature(cp->symbol_at(signature_index)); } -void ClassFileParser::parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp, instanceKlassHandle k, +void ClassFileParser::parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp, u4 attribute_byte_length, TRAPS) { ClassFileStream* cfs = stream(); u1* current_start = cfs->current(); @@ -2539,10 +2714,12 @@ } -void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS) { +void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, + ClassFileParser::ClassAnnotationCollector* parsed_annotations, + TRAPS) { ClassFileStream* cfs = stream(); // Set inner classes attribute to default sentinel - k->set_inner_classes(Universe::the_empty_short_array()); + set_class_inner_classes(typeArrayHandle(THREAD, Universe::the_empty_short_array())); cfs->guarantee_more(2, CHECK); // attributes_count u2 attributes_count = cfs->get_u2_fast(); bool parsed_sourcefile_attribute = false; @@ -2578,10 +2755,10 @@ } else { parsed_sourcefile_attribute = true; } - parse_classfile_sourcefile_attribute(cp, k, CHECK); + parse_classfile_sourcefile_attribute(cp, CHECK); } else if (tag == vmSymbols::tag_source_debug_extension()) { // Check for SourceDebugExtension tag - parse_classfile_source_debug_extension_attribute(cp, k, (int)attribute_length, CHECK); + parse_classfile_source_debug_extension_attribute(cp, (int)attribute_length, CHECK); } else if (tag == vmSymbols::tag_inner_classes()) { // Check for InnerClasses tag if (parsed_innerclasses_attribute) { @@ -2600,7 +2777,7 @@ "Invalid Synthetic classfile attribute length %u in class file %s", attribute_length, CHECK); } - parse_classfile_synthetic_attribute(cp, k, CHECK); + parse_classfile_synthetic_attribute(cp, CHECK); } else if (tag == vmSymbols::tag_deprecated()) { // Check for Deprecatd tag - 4276120 if (attribute_length != 0) { @@ -2615,11 +2792,16 @@ "Wrong Signature attribute length %u in class file %s", attribute_length, CHECK); } - parse_classfile_signature_attribute(cp, k, CHECK); + parse_classfile_signature_attribute(cp, CHECK); } else if (tag == vmSymbols::tag_runtime_visible_annotations()) { runtime_visible_annotations_length = attribute_length; runtime_visible_annotations = cfs->get_u1_buffer(); assert(runtime_visible_annotations != NULL, "null visible annotations"); + parse_annotations(runtime_visible_annotations, + runtime_visible_annotations_length, + cp, + parsed_annotations, + CHECK); cfs->skip_u1(runtime_visible_annotations_length, CHECK); } else if (PreserveAllAnnotations && tag == vmSymbols::tag_runtime_invisible_annotations()) { runtime_invisible_annotations_length = attribute_length; @@ -2653,7 +2835,7 @@ if (parsed_bootstrap_methods_attribute) classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK); parsed_bootstrap_methods_attribute = true; - parse_classfile_bootstrap_methods_attribute(cp, k, attribute_length, CHECK); + parse_classfile_bootstrap_methods_attribute(cp, attribute_length, CHECK); } else { // Unknown attribute cfs->skip_u1(attribute_length, CHECK); @@ -2668,7 +2850,7 @@ runtime_invisible_annotations, runtime_invisible_annotations_length, CHECK); - k->set_class_annotations(annotations()); + set_class_annotations(annotations); if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) { u2 num_of_classes = parse_classfile_inner_classes_attribute( @@ -2676,7 +2858,7 @@ parsed_innerclasses_attribute, enclosing_method_class_index, enclosing_method_method_index, - cp, k, CHECK); + cp, CHECK); if (parsed_innerclasses_attribute &&_need_verify && _major_version >= JAVA_1_5_VERSION) { guarantee_property( inner_classes_attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes, @@ -2690,6 +2872,23 @@ } } +void ClassFileParser::apply_parsed_class_attributes(instanceKlassHandle k) { + if (_synthetic_flag) + k->set_is_synthetic(); + if (_sourcefile != NULL) { + _sourcefile->increment_refcount(); + k->set_source_file_name(_sourcefile); + } + if (_generic_signature != NULL) { + _generic_signature->increment_refcount(); + k->set_generic_signature(_generic_signature); + } + if (_sde_buffer != NULL) { + k->set_source_debug_extension(_sde_buffer, _sde_length); + } + k->set_inner_classes(_inner_classes()); + k->set_class_annotations(_annotations()); +} typeArrayHandle ClassFileParser::assemble_annotations(u1* runtime_visible_annotations, int runtime_visible_annotations_length, @@ -2740,8 +2939,7 @@ jt->get_thread_stat()->perf_timers_addr(), PerfClassTraceTime::PARSE_CLASS); - _has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false; - _max_bootstrap_specifier_index = -1; + init_parsed_class_attributes(); if (JvmtiExport::should_post_class_file_load_hook()) { // Get the cached class file bytes (if any) from the class that @@ -2974,6 +3172,13 @@ objArrayHandle methods_parameter_annotations(THREAD, methods_parameter_annotations_oop); objArrayHandle methods_default_annotations(THREAD, methods_default_annotations_oop); + // Additional attributes + ClassAnnotationCollector parsed_annotations; + parse_classfile_attributes(cp, &parsed_annotations, CHECK_(nullHandle)); + + // Make sure this is the end of class file stream + guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle)); + // We check super class after class file is parsed and format is checked if (super_class_index > 0 && super_klass.is_null()) { Symbol* sk = cp->klass_name_at(super_class_index); @@ -3462,11 +3667,10 @@ this_klass->set_has_miranda_methods(); // then set a flag } - // Additional attributes - parse_classfile_attributes(cp, this_klass, CHECK_(nullHandle)); - - // Make sure this is the end of class file stream - guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle)); + // Fill in field values obtained by parse_classfile_attributes + if (parsed_annotations.has_any_annotations()) + parsed_annotations.apply_to(this_klass); + apply_parsed_class_attributes(this_klass); // VerifyOops believes that once this has been set, the object is completely loaded. // Compute transitive closure of interfaces this class implements @@ -3481,6 +3685,7 @@ // Do final class setup fill_oop_maps(this_klass, nonstatic_oop_map_count, nonstatic_oop_offsets, nonstatic_oop_counts); + // Fill in has_finalizer, has_vanilla_constructor, and layout_helper set_precomputed_flags(this_klass); // reinitialize modifiers, using the InnerClasses attribute diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/classfile/classFileParser.hpp --- a/src/share/vm/classfile/classFileParser.hpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/classfile/classFileParser.hpp Mon Jul 23 12:54:20 2012 -0700 @@ -31,8 +31,8 @@ #include "oops/typeArrayOop.hpp" #include "runtime/handles.inline.hpp" #include "utilities/accessFlags.hpp" +#include "classfile/symbolTable.hpp" -class TempNewSymbol; class FieldAllocationCount; @@ -50,11 +50,80 @@ KlassHandle _host_klass; GrowableArray* _cp_patches; // overrides for CP entries + // precomputed flags bool _has_finalizer; bool _has_empty_finalizer; bool _has_vanilla_constructor; + int _max_bootstrap_specifier_index; // detects BSS values - int _max_bootstrap_specifier_index; + // class attributes parsed before the instance klass is created: + bool _synthetic_flag; + Symbol* _sourcefile; + Symbol* _generic_signature; + char* _sde_buffer; + int _sde_length; + typeArrayHandle _inner_classes; + typeArrayHandle _annotations; + + void set_class_synthetic_flag(bool x) { _synthetic_flag = x; } + void set_class_sourcefile(Symbol* x) { _sourcefile = x; } + void set_class_generic_signature(Symbol* x) { _generic_signature = x; } + void set_class_sde_buffer(char* x, int len) { _sde_buffer = x; _sde_length = len; } + void set_class_inner_classes(typeArrayHandle x) { _inner_classes = x; } + void set_class_annotations(typeArrayHandle x) { _annotations = x; } + void init_parsed_class_attributes() { + _synthetic_flag = false; + _sourcefile = NULL; + _generic_signature = NULL; + _sde_buffer = NULL; + _sde_length = 0; + // initialize the other flags too: + _has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false; + _max_bootstrap_specifier_index = -1; + } + void apply_parsed_class_attributes(instanceKlassHandle k); // update k + + class AnnotationCollector { + public: + enum Location { _in_field, _in_method, _in_class }; + enum ID { + _unknown = 0, + _method_ForceInline, + _annotation_LIMIT + }; + const Location _location; + int _annotations_present; + AnnotationCollector(Location location) + : _location(location), _annotations_present(0) + { + assert((int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte, ""); + } + // If this annotation name has an ID, report it (or _none). + ID annotation_index(Symbol* name); + // Set the annotation name: + void set_annotation(ID id) { + assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob"); + _annotations_present |= nth_bit((int)id); + } + // Report if the annotation is present. + bool has_any_annotations() { return _annotations_present != 0; } + bool has_annotation(ID id) { return (nth_bit((int)id) & _annotations_present) != 0; } + }; + class FieldAnnotationCollector: public AnnotationCollector { + public: + FieldAnnotationCollector() : AnnotationCollector(_in_field) { } + void apply_to(FieldInfo* f); + }; + class MethodAnnotationCollector: public AnnotationCollector { + public: + MethodAnnotationCollector() : AnnotationCollector(_in_method) { } + void apply_to(methodHandle m); + }; + class ClassAnnotationCollector: public AnnotationCollector { + public: + ClassAnnotationCollector() : AnnotationCollector(_in_class) { } + void apply_to(instanceKlassHandle k); + }; enum { fixed_buffer_size = 128 }; u_char linenumbertable_buffer[fixed_buffer_size]; @@ -87,7 +156,9 @@ u2* constantvalue_index_addr, bool* is_synthetic_addr, u2* generic_signature_index_addr, - typeArrayHandle* field_annotations, TRAPS); + typeArrayHandle* field_annotations, + FieldAnnotationCollector* parsed_annotations, + TRAPS); typeArrayHandle parse_fields(Symbol* class_name, constantPoolHandle cp, bool is_interface, FieldAllocationCount *fac, @@ -113,8 +184,8 @@ objArrayHandle methods_parameter_annotations, objArrayHandle methods_default_annotations, TRAPS); - typeArrayHandle parse_exception_table(u4 code_length, u4 exception_table_length, - constantPoolHandle cp, TRAPS); + u2* parse_exception_table(u4 code_length, u4 exception_table_length, + constantPoolHandle cp, TRAPS); void parse_linenumber_table( u4 code_attribute_length, u4 code_length, CompressedLineNumberWriteStream** write_stream, TRAPS); @@ -128,25 +199,32 @@ typeArrayOop parse_stackmap_table(u4 code_attribute_length, TRAPS); // Classfile attribute parsing - void parse_classfile_sourcefile_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS); - void parse_classfile_source_debug_extension_attribute(constantPoolHandle cp, - instanceKlassHandle k, int length, TRAPS); + void parse_classfile_sourcefile_attribute(constantPoolHandle cp, TRAPS); + void parse_classfile_source_debug_extension_attribute(constantPoolHandle cp, int length, TRAPS); u2 parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start, bool parsed_enclosingmethod_attribute, u2 enclosing_method_class_index, u2 enclosing_method_method_index, constantPoolHandle cp, - instanceKlassHandle k, TRAPS); - void parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS); - void parse_classfile_synthetic_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS); - void parse_classfile_signature_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS); - void parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp, instanceKlassHandle k, u4 attribute_length, TRAPS); + TRAPS); + void parse_classfile_attributes(constantPoolHandle cp, + ClassAnnotationCollector* parsed_annotations, + TRAPS); + void parse_classfile_synthetic_attribute(constantPoolHandle cp, TRAPS); + void parse_classfile_signature_attribute(constantPoolHandle cp, TRAPS); + void parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp, u4 attribute_length, TRAPS); // Annotations handling typeArrayHandle assemble_annotations(u1* runtime_visible_annotations, int runtime_visible_annotations_length, u1* runtime_invisible_annotations, int runtime_invisible_annotations_length, TRAPS); + int skip_annotation(u1* buffer, int limit, int index); + int skip_annotation_value(u1* buffer, int limit, int index); + void parse_annotations(u1* buffer, int limit, constantPoolHandle cp, + /* Results (currently, only one result is supported): */ + AnnotationCollector* result, + TRAPS); // Final setup unsigned int compute_oop_map_count(instanceKlassHandle super, diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/classfile/javaClasses.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -2738,17 +2738,6 @@ if (k != NULL) { compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_lang_invoke_MethodHandle_signature()); } - - // Disallow compilation of CallSite.setTargetNormal and CallSite.setTargetVolatile - // (For C2: keep this until we have throttling logic for uncommon traps.) - if (k != NULL) { - instanceKlass* ik = instanceKlass::cast(k); - methodOop m_normal = ik->lookup_method(vmSymbols::setTargetNormal_name(), vmSymbols::setTarget_signature()); - methodOop m_volatile = ik->lookup_method(vmSymbols::setTargetVolatile_name(), vmSymbols::setTarget_signature()); - guarantee(m_normal != NULL && m_volatile != NULL, "must exist"); - m_normal->set_not_compilable_quietly(); - m_volatile->set_not_compilable_quietly(); - } } diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/classfile/systemDictionary.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -2771,7 +2771,6 @@ nmethods++; method_size += m->size(); // class loader uses same objArray for empty vectors, so don't count these - if (m->exception_table()->length() != 0) method_size += m->exception_table()->size(); if (m->has_stackmap_table()) { method_size += m->stackmap_data()->size(); } diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/classfile/verifier.cpp --- a/src/share/vm/classfile/verifier.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/classfile/verifier.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2012, 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 @@ -1368,47 +1368,48 @@ } void ClassVerifier::verify_exception_handler_table(u4 code_length, char* code_data, int& min, int& max, TRAPS) { - typeArrayHandle exhandlers (THREAD, _method->exception_table()); + ExceptionTable exhandlers(_method()); + int exlength = exhandlers.length(); constantPoolHandle cp (THREAD, _method->constants()); - if (exhandlers() != NULL) { - for(int i = 0; i < exhandlers->length();) { - u2 start_pc = exhandlers->int_at(i++); - u2 end_pc = exhandlers->int_at(i++); - u2 handler_pc = exhandlers->int_at(i++); - if (start_pc >= code_length || code_data[start_pc] == 0) { - class_format_error("Illegal exception table start_pc %d", start_pc); + for(int i = 0; i < exlength; i++) { + //reacquire the table in case a GC happened + ExceptionTable exhandlers(_method()); + u2 start_pc = exhandlers.start_pc(i); + u2 end_pc = exhandlers.end_pc(i); + u2 handler_pc = exhandlers.handler_pc(i); + if (start_pc >= code_length || code_data[start_pc] == 0) { + class_format_error("Illegal exception table start_pc %d", start_pc); + return; + } + if (end_pc != code_length) { // special case: end_pc == code_length + if (end_pc > code_length || code_data[end_pc] == 0) { + class_format_error("Illegal exception table end_pc %d", end_pc); return; } - if (end_pc != code_length) { // special case: end_pc == code_length - if (end_pc > code_length || code_data[end_pc] == 0) { - class_format_error("Illegal exception table end_pc %d", end_pc); - return; - } - } - if (handler_pc >= code_length || code_data[handler_pc] == 0) { - class_format_error("Illegal exception table handler_pc %d", handler_pc); + } + if (handler_pc >= code_length || code_data[handler_pc] == 0) { + class_format_error("Illegal exception table handler_pc %d", handler_pc); + return; + } + int catch_type_index = exhandlers.catch_type_index(i); + if (catch_type_index != 0) { + VerificationType catch_type = cp_index_to_type( + catch_type_index, cp, CHECK_VERIFY(this)); + VerificationType throwable = + VerificationType::reference_type(vmSymbols::java_lang_Throwable()); + bool is_subclass = throwable.is_assignable_from( + catch_type, this, CHECK_VERIFY(this)); + if (!is_subclass) { + // 4286534: should throw VerifyError according to recent spec change + verify_error( + "Catch type is not a subclass of Throwable in handler %d", + handler_pc); return; } - int catch_type_index = exhandlers->int_at(i++); - if (catch_type_index != 0) { - VerificationType catch_type = cp_index_to_type( - catch_type_index, cp, CHECK_VERIFY(this)); - VerificationType throwable = - VerificationType::reference_type(vmSymbols::java_lang_Throwable()); - bool is_subclass = throwable.is_assignable_from( - catch_type, this, CHECK_VERIFY(this)); - if (!is_subclass) { - // 4286534: should throw VerifyError according to recent spec change - verify_error( - "Catch type is not a subclass of Throwable in handler %d", - handler_pc); - return; - } - } - if (start_pc < min) min = start_pc; - if (end_pc > max) max = end_pc; } + if (start_pc < min) min = start_pc; + if (end_pc > max) max = end_pc; } } @@ -1474,35 +1475,36 @@ void ClassVerifier::verify_exception_handler_targets(u2 bci, bool this_uninit, StackMapFrame* current_frame, StackMapTable* stackmap_table, TRAPS) { constantPoolHandle cp (THREAD, _method->constants()); - typeArrayHandle exhandlers (THREAD, _method->exception_table()); - if (exhandlers() != NULL) { - for(int i = 0; i < exhandlers->length();) { - u2 start_pc = exhandlers->int_at(i++); - u2 end_pc = exhandlers->int_at(i++); - u2 handler_pc = exhandlers->int_at(i++); - int catch_type_index = exhandlers->int_at(i++); - if(bci >= start_pc && bci < end_pc) { - u1 flags = current_frame->flags(); - if (this_uninit) { flags |= FLAG_THIS_UNINIT; } - StackMapFrame* new_frame = current_frame->frame_in_exception_handler(flags); - if (catch_type_index != 0) { - // We know that this index refers to a subclass of Throwable - VerificationType catch_type = cp_index_to_type( - catch_type_index, cp, CHECK_VERIFY(this)); - new_frame->push_stack(catch_type, CHECK_VERIFY(this)); - } else { - VerificationType throwable = - VerificationType::reference_type(vmSymbols::java_lang_Throwable()); - new_frame->push_stack(throwable, CHECK_VERIFY(this)); - } - bool match = stackmap_table->match_stackmap( - new_frame, handler_pc, true, false, CHECK_VERIFY(this)); - if (!match) { - verify_error(bci, - "Stack map does not match the one at exception handler %d", - handler_pc); - return; - } + ExceptionTable exhandlers(_method()); + int exlength = exhandlers.length(); + for(int i = 0; i < exlength; i++) { + //reacquire the table in case a GC happened + ExceptionTable exhandlers(_method()); + u2 start_pc = exhandlers.start_pc(i); + u2 end_pc = exhandlers.end_pc(i); + u2 handler_pc = exhandlers.handler_pc(i); + int catch_type_index = exhandlers.catch_type_index(i); + if(bci >= start_pc && bci < end_pc) { + u1 flags = current_frame->flags(); + if (this_uninit) { flags |= FLAG_THIS_UNINIT; } + StackMapFrame* new_frame = current_frame->frame_in_exception_handler(flags); + if (catch_type_index != 0) { + // We know that this index refers to a subclass of Throwable + VerificationType catch_type = cp_index_to_type( + catch_type_index, cp, CHECK_VERIFY(this)); + new_frame->push_stack(catch_type, CHECK_VERIFY(this)); + } else { + VerificationType throwable = + VerificationType::reference_type(vmSymbols::java_lang_Throwable()); + new_frame->push_stack(throwable, CHECK_VERIFY(this)); + } + bool match = stackmap_table->match_stackmap( + new_frame, handler_pc, true, false, CHECK_VERIFY(this)); + if (!match) { + verify_error(bci, + "Stack map does not match the one at exception handler %d", + handler_pc); + return; } } } diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/classfile/vmSymbols.hpp Mon Jul 23 12:54:20 2012 -0700 @@ -257,6 +257,7 @@ template(java_lang_invoke_BoundMethodHandle, "java/lang/invoke/BoundMethodHandle") \ template(java_lang_invoke_DirectMethodHandle, "java/lang/invoke/DirectMethodHandle") \ template(java_lang_invoke_CountingMethodHandle, "java/lang/invoke/CountingMethodHandle") \ + template(java_lang_invoke_ForceInline_signature, "Ljava/lang/invoke/ForceInline;") \ /* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \ template(findMethodHandleType_name, "findMethodHandleType") \ template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \ diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/code/vmreg.hpp --- a/src/share/vm/code/vmreg.hpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/code/vmreg.hpp Mon Jul 23 12:54:20 2012 -0700 @@ -131,6 +131,10 @@ assert((is_reg() && value() < stack0->value() - 1) || is_stack(), "must be"); return (VMReg)(intptr_t)(value() + 1); } + VMReg next(int i) { + assert((is_reg() && value() < stack0->value() - i) || is_stack(), "must be"); + return (VMReg)(intptr_t)(value() + i); + } VMReg prev() { assert((is_stack() && value() > stack0->value()) || (is_reg() && value() != 0), "must be"); return (VMReg)(intptr_t)(value() - 1); diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp --- a/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, 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 @@ -27,6 +27,7 @@ #include "gc_implementation/g1/concurrentG1RefineThread.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectorPolicy.hpp" +#include "gc_implementation/g1/g1GCPhaseTimes.hpp" #include "gc_implementation/g1/g1RemSet.hpp" #include "gc_implementation/g1/heapRegionSeq.inline.hpp" #include "memory/space.inline.hpp" @@ -500,11 +501,11 @@ } void ConcurrentG1Refine::clear_and_record_card_counts() { - if (G1ConcRSLogCacheSize == 0) return; + if (G1ConcRSLogCacheSize == 0) { + return; + } -#ifndef PRODUCT double start = os::elapsedTime(); -#endif if (_expand_card_counts) { int new_idx = _cache_size_index + 1; @@ -523,11 +524,8 @@ assert((this_epoch+1) <= max_jint, "to many periods"); // Update epoch _n_periods++; - -#ifndef PRODUCT - double elapsed = os::elapsedTime() - start; - _g1h->g1_policy()->record_cc_clear_time(elapsed * 1000.0); -#endif + double cc_clear_time_ms = (os::elapsedTime() - start) * 1000; + _g1h->g1_policy()->phase_times()->record_cc_clear_time_ms(cc_clear_time_ms); } void ConcurrentG1Refine::print_worker_threads_on(outputStream* st) const { diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -3156,9 +3156,6 @@ _g1h->g1_policy()->record_concurrent_pause(); } cmThread()->yield(); - if (worker_id == 0) { - _g1h->g1_policy()->record_concurrent_pause_end(); - } return true; } else { return false; diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -33,6 +33,7 @@ #include "gc_implementation/g1/g1CollectorPolicy.hpp" #include "gc_implementation/g1/g1ErgoVerbose.hpp" #include "gc_implementation/g1/g1EvacFailure.hpp" +#include "gc_implementation/g1/g1GCPhaseTimes.hpp" #include "gc_implementation/g1/g1Log.hpp" #include "gc_implementation/g1/g1MarkSweep.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" @@ -2274,7 +2275,7 @@ while (dcqs.apply_closure_to_completed_buffer(cl, worker_i, 0, true)) { n_completed_buffers++; } - g1_policy()->record_update_rs_processed_buffers(worker_i, + g1_policy()->phase_times()->record_update_rs_processed_buffers(worker_i, (double) n_completed_buffers); dcqs.clear_n_completed_buffers(); assert(!dcqs.completed_buffers_exist_dirty(), "Completed buffers exist!"); @@ -3633,10 +3634,10 @@ gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps); TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty); - GCCauseString gc_cause_str = GCCauseString("GC pause", gc_cause()) - .append(g1_policy()->gcs_are_young() ? " (young)" : " (mixed)") - .append(g1_policy()->during_initial_mark_pause() ? " (initial-mark)" : ""); - TraceTime t(gc_cause_str, G1Log::fine() && !G1Log::finer(), true, gclog_or_tty); + int active_workers = (G1CollectedHeap::use_parallel_gc_threads() ? + workers()->active_workers() : 1); + g1_policy()->phase_times()->note_gc_start(os::elapsedTime(), active_workers, + g1_policy()->gcs_are_young(), g1_policy()->during_initial_mark_pause(), gc_cause()); TraceCollectorStats tcs(g1mm()->incremental_collection_counters()); TraceMemoryManagerStats tms(false /* fullGC */, gc_cause()); @@ -3699,9 +3700,15 @@ // before the start GC event. _hr_printer.start_gc(false /* full */, (size_t) total_collections()); + // This timing is only used by the ergonomics to handle our pause target. + // It is unclear why this should not include the full pause. We will + // investigate this in CR 7178365. + // + // Preserving the old comment here if that helps the investigation: + // // The elapsed time induced by the start time below deliberately elides // the possible verification above. - double start_time_sec = os::elapsedTime(); + double sample_start_time_sec = os::elapsedTime(); size_t start_used_bytes = used(); #if YOUNG_LIST_VERBOSE @@ -3710,7 +3717,7 @@ g1_policy()->print_collection_set(g1_policy()->inc_cset_head(), gclog_or_tty); #endif // YOUNG_LIST_VERBOSE - g1_policy()->record_collection_pause_start(start_time_sec, + g1_policy()->record_collection_pause_start(sample_start_time_sec, start_used_bytes); double scan_wait_start = os::elapsedTime(); @@ -3719,11 +3726,12 @@ // objects on them have been correctly scanned before we start // moving them during the GC. bool waited = _cm->root_regions()->wait_until_scan_finished(); + double wait_time_ms = 0.0; if (waited) { double scan_wait_end = os::elapsedTime(); - double wait_time_ms = (scan_wait_end - scan_wait_start) * 1000.0; - g1_policy()->record_root_region_scan_wait_time(wait_time_ms); + wait_time_ms = (scan_wait_end - scan_wait_start) * 1000.0; } + g1_policy()->phase_times()->record_root_region_scan_wait_time(wait_time_ms); #if YOUNG_LIST_VERBOSE gclog_or_tty->print_cr("\nAfter recording pause start.\nYoung_list:"); @@ -3877,12 +3885,16 @@ true /* verify_fingers */); _cm->note_end_of_gc(); - double end_time_sec = os::elapsedTime(); - double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; - g1_policy()->record_pause_time_ms(pause_time_ms); - int active_workers = (G1CollectedHeap::use_parallel_gc_threads() ? - workers()->active_workers() : 1); - g1_policy()->record_collection_pause_end(active_workers); + // Collect thread local data to allow the ergonomics to use + // the collected information + g1_policy()->phase_times()->collapse_par_times(); + + // This timing is only used by the ergonomics to handle our pause target. + // It is unclear why this should not include the full pause. We will + // investigate this in CR 7178365. + double sample_end_time_sec = os::elapsedTime(); + double pause_time_ms = (sample_end_time_sec - sample_start_time_sec) * MILLIUNITS; + g1_policy()->record_collection_pause_end(pause_time_ms); MemoryService::track_memory_usage(); @@ -3929,9 +3941,6 @@ // RETIRE events are generated before the end GC event. _hr_printer.end_gc(false /* full */, (size_t) total_collections()); - // We have to do this after we decide whether to expand the heap or not. - g1_policy()->print_heap_transition(); - if (mark_in_progress()) { concurrent_mark()->update_g1_committed(); } @@ -3941,13 +3950,14 @@ #endif gc_epilogue(false); + + g1_policy()->phase_times()->note_gc_end(os::elapsedTime()); + + // We have to do this after we decide whether to expand the heap or not. + g1_policy()->print_heap_transition(); } - // The closing of the inner scope, immediately above, will complete - // logging at the "fine" level. The record_collection_pause_end() call - // above will complete logging at the "finer" level. - // - // It is not yet to safe, however, to tell the concurrent mark to + // It is not yet to safe to tell the concurrent mark to // start as we have some optional output below. We don't want the // output from the concurrent mark thread interfering with this // logging output either. @@ -4695,7 +4705,7 @@ if (worker_id >= _n_workers) return; // no work needed this round double start_time_ms = os::elapsedTime() * 1000.0; - _g1h->g1_policy()->record_gc_worker_start_time(worker_id, start_time_ms); + _g1h->g1_policy()->phase_times()->record_gc_worker_start_time(worker_id, start_time_ms); { ResourceMark rm; @@ -4744,8 +4754,8 @@ evac.do_void(); double elapsed_ms = (os::elapsedTime()-start)*1000.0; double term_ms = pss.term_time()*1000.0; - _g1h->g1_policy()->record_obj_copy_time(worker_id, elapsed_ms-term_ms); - _g1h->g1_policy()->record_termination(worker_id, term_ms, pss.term_attempts()); + _g1h->g1_policy()->phase_times()->record_obj_copy_time(worker_id, elapsed_ms-term_ms); + _g1h->g1_policy()->phase_times()->record_termination(worker_id, term_ms, pss.term_attempts()); } _g1h->g1_policy()->record_thread_age_table(pss.age_table()); _g1h->update_surviving_young_words(pss.surviving_young_words()+1); @@ -4763,7 +4773,7 @@ } double end_time_ms = os::elapsedTime() * 1000.0; - _g1h->g1_policy()->record_gc_worker_end_time(worker_id, end_time_ms); + _g1h->g1_policy()->phase_times()->record_gc_worker_end_time(worker_id, end_time_ms); } }; @@ -4874,15 +4884,15 @@ double ext_roots_end = os::elapsedTime(); - g1_policy()->reset_obj_copy_time(worker_i); + g1_policy()->phase_times()->reset_obj_copy_time(worker_i); double obj_copy_time_sec = buf_scan_perm.closure_app_seconds() + buf_scan_non_heap_roots.closure_app_seconds(); - g1_policy()->record_obj_copy_time(worker_i, obj_copy_time_sec * 1000.0); + g1_policy()->phase_times()->record_obj_copy_time(worker_i, obj_copy_time_sec * 1000.0); double ext_root_time_ms = ((ext_roots_end - ext_roots_start) - obj_copy_time_sec) * 1000.0; - g1_policy()->record_ext_root_scan_time(worker_i, ext_root_time_ms); + g1_policy()->phase_times()->record_ext_root_scan_time(worker_i, ext_root_time_ms); // During conc marking we have to filter the per-thread SATB buffers // to make sure we remove any oops into the CSet (which will show up @@ -4893,7 +4903,7 @@ } } double satb_filtering_ms = (os::elapsedTime() - ext_roots_end) * 1000.0; - g1_policy()->record_satb_filtering_time(worker_i, satb_filtering_ms); + g1_policy()->phase_times()->record_satb_filtering_time(worker_i, satb_filtering_ms); // Now scan the complement of the collection set. if (scan_rs != NULL) { @@ -5393,7 +5403,7 @@ assert(pss.refs()->is_empty(), "both queue and overflow should be empty"); double ref_proc_time = os::elapsedTime() - ref_proc_start; - g1_policy()->record_ref_proc_time(ref_proc_time * 1000.0); + g1_policy()->phase_times()->record_ref_proc_time(ref_proc_time * 1000.0); } // Weak Reference processing during an evacuation pause (part 2). @@ -5430,7 +5440,7 @@ // and could signicantly increase the pause time. double ref_enq_time = os::elapsedTime() - ref_enq_start; - g1_policy()->record_ref_enq_time(ref_enq_time * 1000.0); + g1_policy()->phase_times()->record_ref_enq_time(ref_enq_time * 1000.0); } void G1CollectedHeap::evacuate_collection_set() { @@ -5493,11 +5503,11 @@ } double par_time_ms = (end_par_time_sec - start_par_time_sec) * 1000.0; - g1_policy()->record_par_time(par_time_ms); + g1_policy()->phase_times()->record_par_time(par_time_ms); double code_root_fixup_time_ms = (os::elapsedTime() - end_par_time_sec) * 1000.0; - g1_policy()->record_code_root_fixup_time(code_root_fixup_time_ms); + g1_policy()->phase_times()->record_code_root_fixup_time(code_root_fixup_time_ms); set_par_threads(0); @@ -5759,7 +5769,7 @@ } double elapsed = os::elapsedTime() - start; - g1_policy()->record_clear_ct_time(elapsed * 1000.0); + g1_policy()->phase_times()->record_clear_ct_time(elapsed * 1000.0); } void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) { @@ -5868,8 +5878,8 @@ NULL /* old_proxy_set */, NULL /* humongous_proxy_set */, false /* par */); - policy->record_young_free_cset_time_ms(young_time_ms); - policy->record_non_young_free_cset_time_ms(non_young_time_ms); + policy->phase_times()->record_young_free_cset_time_ms(young_time_ms); + policy->phase_times()->record_non_young_free_cset_time_ms(non_young_time_ms); } // This routine is similar to the above but does not record diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -29,6 +29,7 @@ #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectorPolicy.hpp" #include "gc_implementation/g1/g1ErgoVerbose.hpp" +#include "gc_implementation/g1/g1GCPhaseTimes.hpp" #include "gc_implementation/g1/g1Log.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp" #include "gc_implementation/shared/gcPolicyCounters.hpp" @@ -77,57 +78,6 @@ 1.0, 0.7, 0.7, 0.5, 0.5, 0.42, 0.42, 0.30 }; -// Help class for avoiding interleaved logging -class LineBuffer: public StackObj { - -private: - static const int BUFFER_LEN = 1024; - static const int INDENT_CHARS = 3; - char _buffer[BUFFER_LEN]; - int _indent_level; - int _cur; - - void vappend(const char* format, va_list ap) { - int res = vsnprintf(&_buffer[_cur], BUFFER_LEN - _cur, format, ap); - if (res != -1) { - _cur += res; - } else { - DEBUG_ONLY(warning("buffer too small in LineBuffer");) - _buffer[BUFFER_LEN -1] = 0; - _cur = BUFFER_LEN; // vsnprintf above should not add to _buffer if we are called again - } - } - -public: - explicit LineBuffer(int indent_level): _indent_level(indent_level), _cur(0) { - for (; (_cur < BUFFER_LEN && _cur < (_indent_level * INDENT_CHARS)); _cur++) { - _buffer[_cur] = ' '; - } - } - -#ifndef PRODUCT - ~LineBuffer() { - assert(_cur == _indent_level * INDENT_CHARS, "pending data in buffer - append_and_print_cr() not called?"); - } -#endif - - void append(const char* format, ...) { - va_list ap; - va_start(ap, format); - vappend(format, ap); - va_end(ap); - } - - void append_and_print_cr(const char* format, ...) { - va_list ap; - va_start(ap, format); - vappend(format, ap); - va_end(ap); - gclog_or_tty->print_cr("%s", _buffer); - _cur = _indent_level * INDENT_CHARS; - } -}; - G1CollectorPolicy::G1CollectorPolicy() : _parallel_gc_threads(G1CollectedHeap::use_parallel_gc_threads() ? ParallelGCThreads : 1), @@ -135,20 +85,6 @@ _recent_gc_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), _stop_world_start(0.0), - _cur_clear_ct_time_ms(0.0), - _root_region_scan_wait_time_ms(0.0), - - _cur_ref_proc_time_ms(0.0), - _cur_ref_enq_time_ms(0.0), - -#ifndef PRODUCT - _min_clear_cc_time_ms(-1.0), - _max_clear_cc_time_ms(-1.0), - _cur_clear_cc_time_ms(0.0), - _cum_clear_cc_time_ms(0.0), - _num_cc_clears(0L), -#endif - _concurrent_mark_remark_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), _concurrent_mark_cleanup_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), @@ -257,30 +193,9 @@ _recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime()); _prev_collection_pause_end_ms = os::elapsedTime() * 1000.0; - _par_last_gc_worker_start_times_ms = new double[_parallel_gc_threads]; - _par_last_ext_root_scan_times_ms = new double[_parallel_gc_threads]; - _par_last_satb_filtering_times_ms = new double[_parallel_gc_threads]; - - _par_last_update_rs_times_ms = new double[_parallel_gc_threads]; - _par_last_update_rs_processed_buffers = new double[_parallel_gc_threads]; - - _par_last_scan_rs_times_ms = new double[_parallel_gc_threads]; - - _par_last_obj_copy_times_ms = new double[_parallel_gc_threads]; + _phase_times = new G1GCPhaseTimes(_parallel_gc_threads); - _par_last_termination_times_ms = new double[_parallel_gc_threads]; - _par_last_termination_attempts = new double[_parallel_gc_threads]; - _par_last_gc_worker_end_times_ms = new double[_parallel_gc_threads]; - _par_last_gc_worker_times_ms = new double[_parallel_gc_threads]; - _par_last_gc_worker_other_times_ms = new double[_parallel_gc_threads]; - - int index; - if (ParallelGCThreads == 0) - index = 0; - else if (ParallelGCThreads > 8) - index = 7; - else - index = ParallelGCThreads - 1; + int index = MIN2(_parallel_gc_threads - 1, 7); _pending_card_diff_seq->add(0.0); _rs_length_diff_seq->add(rs_length_diff_defaults[index]); @@ -824,7 +739,7 @@ #endif // PRODUCT void G1CollectorPolicy::record_full_collection_start() { - _cur_collection_start_sec = os::elapsedTime(); + _full_collection_start_sec = os::elapsedTime(); // Release the future to-space so that it is available for compaction into. _g1->set_full_collection(); } @@ -833,7 +748,7 @@ // Consider this like a collection pause for the purposes of allocation // since last pause. double end_sec = os::elapsedTime(); - double full_gc_time_sec = end_sec - _cur_collection_start_sec; + double full_gc_time_sec = end_sec - _full_collection_start_sec; double full_gc_time_ms = full_gc_time_sec * 1000.0; _trace_gen1_time_data.record_full_collection(full_gc_time_ms); @@ -869,12 +784,6 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec, size_t start_used) { - if (G1Log::finer()) { - gclog_or_tty->stamp(PrintGCTimeStamps); - gclog_or_tty->print("[%s", (const char*)GCCauseString("GC pause", _g1->gc_cause()) - .append(gcs_are_young() ? " (young)" : " (mixed)")); - } - // We only need to do this here as the policy will only be applied // to the GC we're about to start. so, no point is calculating this // every time we calculate / recalculate the target young length. @@ -888,7 +797,7 @@ _trace_gen0_time_data.record_start_collection(s_w_t_ms); _stop_world_start = 0.0; - _cur_collection_start_sec = start_time_sec; + phase_times()->_cur_collection_start_sec = start_time_sec; _cur_collection_pause_used_at_start_bytes = start_used; _cur_collection_pause_used_regions_at_start = _g1->used_regions(); _pending_cards = _g1->pending_card_num(); @@ -902,30 +811,6 @@ _survivor_bytes_before_gc = young_list->survivor_used_bytes(); _capacity_before_gc = _g1->capacity(); -#ifdef DEBUG - // initialise these to something well known so that we can spot - // if they are not set properly - - for (int i = 0; i < _parallel_gc_threads; ++i) { - _par_last_gc_worker_start_times_ms[i] = -1234.0; - _par_last_ext_root_scan_times_ms[i] = -1234.0; - _par_last_satb_filtering_times_ms[i] = -1234.0; - _par_last_update_rs_times_ms[i] = -1234.0; - _par_last_update_rs_processed_buffers[i] = -1234.0; - _par_last_scan_rs_times_ms[i] = -1234.0; - _par_last_obj_copy_times_ms[i] = -1234.0; - _par_last_termination_times_ms[i] = -1234.0; - _par_last_termination_attempts[i] = -1234.0; - _par_last_gc_worker_end_times_ms[i] = -1234.0; - _par_last_gc_worker_times_ms[i] = -1234.0; - _par_last_gc_worker_other_times_ms[i] = -1234.0; - } -#endif - - // This is initialized to zero here and is set during the evacuation - // pause if we actually waited for the root region scanning to finish. - _root_region_scan_wait_time_ms = 0.0; - _last_gc_was_young = false; // do that for any other surv rate groups @@ -974,127 +859,6 @@ } } -void G1CollectorPolicy::record_concurrent_pause_end() { -} - -template -T sum_of(T* sum_arr, int start, int n, int N) { - T sum = (T)0; - for (int i = 0; i < n; i++) { - int j = (start + i) % N; - sum += sum_arr[j]; - } - return sum; -} - -void G1CollectorPolicy::print_par_stats(int level, - const char* str, - double* data, - bool showDecimals) { - double min = data[0], max = data[0]; - double total = 0.0; - LineBuffer buf(level); - buf.append("[%s (ms):", str); - for (uint i = 0; i < no_of_gc_threads(); ++i) { - double val = data[i]; - if (val < min) - min = val; - if (val > max) - max = val; - total += val; - if (G1Log::finest()) { - if (showDecimals) { - buf.append(" %.1lf", val); - } else { - buf.append(" %d", (int)val); - } - } - } - - if (G1Log::finest()) { - buf.append_and_print_cr(""); - } - double avg = total / (double) no_of_gc_threads(); - if (showDecimals) { - buf.append_and_print_cr(" Min: %.1lf, Avg: %.1lf, Max: %.1lf, Diff: %.1lf, Sum: %.1lf]", - min, avg, max, max - min, total); - } else { - buf.append_and_print_cr(" Min: %d, Avg: %d, Max: %d, Diff: %d, Sum: %d]", - (int)min, (int)avg, (int)max, (int)max - (int)min, (int)total); - } -} - -void G1CollectorPolicy::print_stats(int level, - const char* str, - double value) { - LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value); -} - -void G1CollectorPolicy::print_stats(int level, - const char* str, - double value, - int workers) { - LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %d]", str, value, workers); -} - -void G1CollectorPolicy::print_stats(int level, - const char* str, - int value) { - LineBuffer(level).append_and_print_cr("[%s: %d]", str, value); -} - -double G1CollectorPolicy::avg_value(double* data) { - if (G1CollectedHeap::use_parallel_gc_threads()) { - double ret = 0.0; - for (uint i = 0; i < no_of_gc_threads(); ++i) { - ret += data[i]; - } - return ret / (double) no_of_gc_threads(); - } else { - return data[0]; - } -} - -double G1CollectorPolicy::max_value(double* data) { - if (G1CollectedHeap::use_parallel_gc_threads()) { - double ret = data[0]; - for (uint i = 1; i < no_of_gc_threads(); ++i) { - if (data[i] > ret) { - ret = data[i]; - } - } - return ret; - } else { - return data[0]; - } -} - -double G1CollectorPolicy::sum_of_values(double* data) { - if (G1CollectedHeap::use_parallel_gc_threads()) { - double sum = 0.0; - for (uint i = 0; i < no_of_gc_threads(); i++) { - sum += data[i]; - } - return sum; - } else { - return data[0]; - } -} - -double G1CollectorPolicy::max_sum(double* data1, double* data2) { - double ret = data1[0] + data2[0]; - - if (G1CollectedHeap::use_parallel_gc_threads()) { - for (uint i = 1; i < no_of_gc_threads(); ++i) { - double data = data1[i] + data2[i]; - if (data > ret) { - ret = data; - } - } - } - return ret; -} - bool G1CollectorPolicy::need_to_start_conc_mark(const char* source, size_t alloc_word_size) { if (_g1->concurrent_mark()->cmThread()->during_cycle()) { return false; @@ -1142,10 +906,8 @@ // Anything below that is considered to be zero #define MIN_TIMER_GRANULARITY 0.0000001 -void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) { +void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) { double end_time_sec = os::elapsedTime(); - double elapsed_ms = _last_pause_time_ms; - bool parallel = G1CollectedHeap::use_parallel_gc_threads(); assert(_cur_collection_pause_used_regions_at_start >= cset_region_length(), "otherwise, the subtraction below does not make sense"); size_t rs_size = @@ -1154,7 +916,6 @@ assert(cur_used_bytes == _g1->recalculate_used(), "It should!"); bool last_pause_included_initial_mark = false; bool update_stats = !_g1->evacuation_failed(); - set_no_of_gc_threads(no_of_gc_threads); #ifndef PRODUCT if (G1YoungSurvRateVerbose) { @@ -1174,7 +935,7 @@ set_initiate_conc_mark_if_possible(); } - _mmu_tracker->add_pause(end_time_sec - elapsed_ms/1000.0, + _mmu_tracker->add_pause(end_time_sec - pause_time_ms/1000.0, end_time_sec, false); size_t freed_bytes = @@ -1185,58 +946,11 @@ (double)surviving_bytes/ (double)_collection_set_bytes_used_before; - // These values are used to update the summary information that is - // displayed when TraceGen0Time is enabled, and are output as part - // of the "finer" output, in the non-parallel case. - - double ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms); - double satb_filtering_time = avg_value(_par_last_satb_filtering_times_ms); - double update_rs_time = avg_value(_par_last_update_rs_times_ms); - double update_rs_processed_buffers = - sum_of_values(_par_last_update_rs_processed_buffers); - double scan_rs_time = avg_value(_par_last_scan_rs_times_ms); - double obj_copy_time = avg_value(_par_last_obj_copy_times_ms); - double termination_time = avg_value(_par_last_termination_times_ms); - - double known_time = ext_root_scan_time + - satb_filtering_time + - update_rs_time + - scan_rs_time + - obj_copy_time; - - double other_time_ms = elapsed_ms; - - // Subtract the root region scanning wait time. It's initialized to - // zero at the start of the pause. - other_time_ms -= _root_region_scan_wait_time_ms; - - if (parallel) { - other_time_ms -= _cur_collection_par_time_ms; - } else { - other_time_ms -= known_time; - } - - // Now subtract the time taken to fix up roots in generated code - other_time_ms -= _cur_collection_code_root_fixup_time_ms; - - // Subtract the time taken to clean the card table from the - // current value of "other time" - other_time_ms -= _cur_clear_ct_time_ms; - - // TraceGen0Time and TraceGen1Time summary info updating. - if (update_stats) { - double parallel_known_time = known_time + termination_time; - double parallel_other_time = _cur_collection_par_time_ms - parallel_known_time; - - _trace_gen0_time_data.record_end_collection( - elapsed_ms, other_time_ms, _root_region_scan_wait_time_ms, _cur_collection_par_time_ms, - ext_root_scan_time, satb_filtering_time, update_rs_time, scan_rs_time, obj_copy_time, - termination_time, parallel_other_time, _cur_clear_ct_time_ms); - + _trace_gen0_time_data.record_end_collection(pause_time_ms, phase_times()); // this is where we update the allocation rate of the application double app_time_ms = - (_cur_collection_start_sec * 1000.0 - _prev_collection_pause_end_ms); + (phase_times()->_cur_collection_start_sec * 1000.0 - _prev_collection_pause_end_ms); if (app_time_ms < MIN_TIMER_GRANULARITY) { // This usually happens due to the timer not having the required // granularity. Some Linuxes are the usual culprits. @@ -1257,7 +971,7 @@ double interval_ms = (end_time_sec - _recent_prev_end_times_for_all_gcs_sec->oldest()) * 1000.0; - update_recent_gc_times(end_time_sec, elapsed_ms); + update_recent_gc_times(end_time_sec, pause_time_ms); _recent_avg_pause_time_ratio = _recent_gc_times_ms->sum()/interval_ms; if (recent_avg_pause_time_ratio() < 0.0 || (recent_avg_pause_time_ratio() - 1.0 > 0.0)) { @@ -1284,90 +998,6 @@ } } } - - if (G1Log::finer()) { - bool print_marking_info = - _g1->mark_in_progress() && !last_pause_included_initial_mark; - - gclog_or_tty->print_cr("%s, %1.8lf secs]", - (last_pause_included_initial_mark) ? " (initial-mark)" : "", - elapsed_ms / 1000.0); - - if (_root_region_scan_wait_time_ms > 0.0) { - print_stats(1, "Root Region Scan Waiting", _root_region_scan_wait_time_ms); - } - if (parallel) { - print_stats(1, "Parallel Time", _cur_collection_par_time_ms, no_of_gc_threads); - print_par_stats(2, "GC Worker Start", _par_last_gc_worker_start_times_ms); - print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms); - if (print_marking_info) { - print_par_stats(2, "SATB Filtering", _par_last_satb_filtering_times_ms); - } - print_par_stats(2, "Update RS", _par_last_update_rs_times_ms); - if (G1Log::finest()) { - print_par_stats(3, "Processed Buffers", _par_last_update_rs_processed_buffers, - false /* showDecimals */); - } - print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms); - print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms); - print_par_stats(2, "Termination", _par_last_termination_times_ms); - if (G1Log::finest()) { - print_par_stats(3, "Termination Attempts", _par_last_termination_attempts, - false /* showDecimals */); - } - - for (int i = 0; i < _parallel_gc_threads; i++) { - _par_last_gc_worker_times_ms[i] = _par_last_gc_worker_end_times_ms[i] - - _par_last_gc_worker_start_times_ms[i]; - - double worker_known_time = _par_last_ext_root_scan_times_ms[i] + - _par_last_satb_filtering_times_ms[i] + - _par_last_update_rs_times_ms[i] + - _par_last_scan_rs_times_ms[i] + - _par_last_obj_copy_times_ms[i] + - _par_last_termination_times_ms[i]; - - _par_last_gc_worker_other_times_ms[i] = _par_last_gc_worker_times_ms[i] - - worker_known_time; - } - - print_par_stats(2, "GC Worker Other", _par_last_gc_worker_other_times_ms); - print_par_stats(2, "GC Worker Total", _par_last_gc_worker_times_ms); - print_par_stats(2, "GC Worker End", _par_last_gc_worker_end_times_ms); - } else { - print_stats(1, "Ext Root Scanning", ext_root_scan_time); - if (print_marking_info) { - print_stats(1, "SATB Filtering", satb_filtering_time); - } - print_stats(1, "Update RS", update_rs_time); - if (G1Log::finest()) { - print_stats(2, "Processed Buffers", (int)update_rs_processed_buffers); - } - print_stats(1, "Scan RS", scan_rs_time); - print_stats(1, "Object Copying", obj_copy_time); - } - print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms); - print_stats(1, "Clear CT", _cur_clear_ct_time_ms); -#ifndef PRODUCT - print_stats(1, "Cur Clear CC", _cur_clear_cc_time_ms); - print_stats(1, "Cum Clear CC", _cum_clear_cc_time_ms); - print_stats(1, "Min Clear CC", _min_clear_cc_time_ms); - print_stats(1, "Max Clear CC", _max_clear_cc_time_ms); - if (_num_cc_clears > 0) { - print_stats(1, "Avg Clear CC", _cum_clear_cc_time_ms / ((double)_num_cc_clears)); - } -#endif - print_stats(1, "Other", other_time_ms); - print_stats(2, "Choose CSet", - (_recorded_young_cset_choice_time_ms + - _recorded_non_young_cset_choice_time_ms)); - print_stats(2, "Ref Proc", _cur_ref_proc_time_ms); - print_stats(2, "Ref Enq", _cur_ref_enq_time_ms); - print_stats(2, "Free CSet", - (_recorded_young_free_cset_time_ms + - _recorded_non_young_free_cset_time_ms)); - } - bool new_in_marking_window = _in_marking_window; bool new_in_marking_window_im = false; if (during_initial_mark_pause()) { @@ -1406,8 +1036,6 @@ // do that for any other surv rate groupsx if (update_stats) { - double pause_time_ms = elapsed_ms; - size_t diff = 0; if (_max_pending_cards >= _pending_cards) { diff = _max_pending_cards - _pending_cards; @@ -1416,7 +1044,7 @@ double cost_per_card_ms = 0.0; if (_pending_cards > 0) { - cost_per_card_ms = update_rs_time / (double) _pending_cards; + cost_per_card_ms = phase_times()->_update_rs_time / (double) _pending_cards; _cost_per_card_ms_seq->add(cost_per_card_ms); } @@ -1424,7 +1052,7 @@ double cost_per_entry_ms = 0.0; if (cards_scanned > 10) { - cost_per_entry_ms = scan_rs_time / (double) cards_scanned; + cost_per_entry_ms = phase_times()->_scan_rs_time / (double) cards_scanned; if (_last_gc_was_young) { _cost_per_entry_ms_seq->add(cost_per_entry_ms); } else { @@ -1464,7 +1092,7 @@ size_t copied_bytes = surviving_bytes; double cost_per_byte_ms = 0.0; if (copied_bytes > 0) { - cost_per_byte_ms = obj_copy_time / (double) copied_bytes; + cost_per_byte_ms = phase_times()->_obj_copy_time / (double) copied_bytes; if (_in_marking_window) { _cost_per_byte_ms_during_cm_seq->add(cost_per_byte_ms); } else { @@ -1473,21 +1101,21 @@ } double all_other_time_ms = pause_time_ms - - (update_rs_time + scan_rs_time + obj_copy_time + termination_time); + (phase_times()->_update_rs_time + phase_times()->_scan_rs_time + phase_times()->_obj_copy_time + phase_times()->_termination_time); double young_other_time_ms = 0.0; if (young_cset_region_length() > 0) { young_other_time_ms = - _recorded_young_cset_choice_time_ms + - _recorded_young_free_cset_time_ms; + phase_times()->_recorded_young_cset_choice_time_ms + + phase_times()->_recorded_young_free_cset_time_ms; _young_other_cost_per_region_ms_seq->add(young_other_time_ms / (double) young_cset_region_length()); } double non_young_other_time_ms = 0.0; if (old_cset_region_length() > 0) { non_young_other_time_ms = - _recorded_non_young_cset_choice_time_ms + - _recorded_non_young_free_cset_time_ms; + phase_times()->_recorded_non_young_cset_choice_time_ms + + phase_times()->_recorded_non_young_free_cset_time_ms; _non_young_other_cost_per_region_ms_seq->add(non_young_other_time_ms / (double) old_cset_region_length()); @@ -1514,7 +1142,7 @@ // Note that _mmu_tracker->max_gc_time() returns the time in seconds. double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0; - adjust_concurrent_refinement(update_rs_time, update_rs_processed_buffers, update_rs_time_goal_ms); + adjust_concurrent_refinement(phase_times()->_update_rs_time, phase_times()->_update_rs_processed_buffers, update_rs_time_goal_ms); _collectionSetChooser->verify(); } @@ -2323,7 +1951,7 @@ set_recorded_rs_lengths(_inc_cset_recorded_rs_lengths); double young_end_time_sec = os::elapsedTime(); - _recorded_young_cset_choice_time_ms = + phase_times()->_recorded_young_cset_choice_time_ms = (young_end_time_sec - young_start_time_sec) * 1000.0; // We are doing young collections so reset this. @@ -2439,7 +2067,7 @@ predicted_pause_time_ms, target_pause_time_ms); double non_young_end_time_sec = os::elapsedTime(); - _recorded_non_young_cset_choice_time_ms = + phase_times()->_recorded_non_young_cset_choice_time_ms = (non_young_end_time_sec - non_young_start_time_sec) * 1000.0; } @@ -2455,33 +2083,29 @@ } } -void TraceGen0TimeData::record_end_collection( - double total_ms, - double other_ms, - double root_region_scan_wait_ms, - double parallel_ms, - double ext_root_scan_ms, - double satb_filtering_ms, - double update_rs_ms, - double scan_rs_ms, - double obj_copy_ms, - double termination_ms, - double parallel_other_ms, - double clear_ct_ms) -{ +void TraceGen0TimeData::record_end_collection(double pause_time_ms, G1GCPhaseTimes* phase_times) { if(TraceGen0Time) { - _total.add(total_ms); - _other.add(other_ms); - _root_region_scan_wait.add(root_region_scan_wait_ms); - _parallel.add(parallel_ms); - _ext_root_scan.add(ext_root_scan_ms); - _satb_filtering.add(satb_filtering_ms); - _update_rs.add(update_rs_ms); - _scan_rs.add(scan_rs_ms); - _obj_copy.add(obj_copy_ms); - _termination.add(termination_ms); - _parallel_other.add(parallel_other_ms); - _clear_ct.add(clear_ct_ms); + _total.add(pause_time_ms); + _other.add(pause_time_ms - phase_times->accounted_time_ms()); + _root_region_scan_wait.add(phase_times->_root_region_scan_wait_time_ms); + _parallel.add(phase_times->_cur_collection_par_time_ms); + _ext_root_scan.add(phase_times->_ext_root_scan_time); + _satb_filtering.add(phase_times->_satb_filtering_time); + _update_rs.add(phase_times->_update_rs_time); + _scan_rs.add(phase_times->_scan_rs_time); + _obj_copy.add(phase_times->_obj_copy_time); + _termination.add(phase_times->_termination_time); + + double parallel_known_time = phase_times->_ext_root_scan_time + + phase_times->_satb_filtering_time + + phase_times->_update_rs_time + + phase_times->_scan_rs_time + + phase_times->_obj_copy_time + + + phase_times->_termination_time; + + double parallel_other_time = phase_times->_cur_collection_par_time_ms - parallel_known_time; + _parallel_other.add(parallel_other_time); + _clear_ct.add(phase_times->_cur_clear_ct_time_ms); } } @@ -2497,20 +2121,18 @@ } } -void TraceGen0TimeData::print_summary(int level, - const char* str, +void TraceGen0TimeData::print_summary(const char* str, const NumberSeq* seq) const { double sum = seq->sum(); - LineBuffer(level + 1).append_and_print_cr("%-24s = %8.2lf s (avg = %8.2lf ms)", + gclog_or_tty->print_cr("%-27s = %8.2lf s (avg = %8.2lf ms)", str, sum / 1000.0, seq->avg()); } -void TraceGen0TimeData::print_summary_sd(int level, - const char* str, +void TraceGen0TimeData::print_summary_sd(const char* str, const NumberSeq* seq) const { - print_summary(level, str, seq); - LineBuffer(level + 6).append_and_print_cr("(num = %5d, std dev = %8.2lf ms, max = %8.2lf ms)", - seq->num(), seq->sd(), seq->maximum()); + print_summary(str, seq); + gclog_or_tty->print_cr("%+45s = %5d, std dev = %8.2lf ms, max = %8.2lf ms)", + "(num", seq->num(), seq->sd(), seq->maximum()); } void TraceGen0TimeData::print() const { @@ -2519,7 +2141,7 @@ } gclog_or_tty->print_cr("ALL PAUSES"); - print_summary_sd(0, "Total", &_total); + print_summary_sd(" Total", &_total); gclog_or_tty->print_cr(""); gclog_or_tty->print_cr(""); gclog_or_tty->print_cr(" Young GC Pauses: %8d", _young_pause_num); @@ -2531,24 +2153,24 @@ if (_young_pause_num == 0 && _mixed_pause_num == 0) { gclog_or_tty->print_cr("none"); } else { - print_summary_sd(0, "Evacuation Pauses", &_total); - print_summary(1, "Root Region Scan Wait", &_root_region_scan_wait); - print_summary(1, "Parallel Time", &_parallel); - print_summary(2, "Ext Root Scanning", &_ext_root_scan); - print_summary(2, "SATB Filtering", &_satb_filtering); - print_summary(2, "Update RS", &_update_rs); - print_summary(2, "Scan RS", &_scan_rs); - print_summary(2, "Object Copy", &_obj_copy); - print_summary(2, "Termination", &_termination); - print_summary(2, "Parallel Other", &_parallel_other); - print_summary(1, "Clear CT", &_clear_ct); - print_summary(1, "Other", &_other); + print_summary_sd(" Evacuation Pauses", &_total); + print_summary(" Root Region Scan Wait", &_root_region_scan_wait); + print_summary(" Parallel Time", &_parallel); + print_summary(" Ext Root Scanning", &_ext_root_scan); + print_summary(" SATB Filtering", &_satb_filtering); + print_summary(" Update RS", &_update_rs); + print_summary(" Scan RS", &_scan_rs); + print_summary(" Object Copy", &_obj_copy); + print_summary(" Termination", &_termination); + print_summary(" Parallel Other", &_parallel_other); + print_summary(" Clear CT", &_clear_ct); + print_summary(" Other", &_other); } gclog_or_tty->print_cr(""); gclog_or_tty->print_cr("MISC"); - print_summary_sd(0, "Stop World", &_all_stop_world_times_ms); - print_summary_sd(0, "Yields", &_all_yield_times_ms); + print_summary_sd(" Stop World", &_all_stop_world_times_ms); + print_summary_sd(" Yields", &_all_yield_times_ms); } void TraceGen1TimeData::record_full_collection(double full_gc_time_ms) { diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Mon Jul 23 12:54:20 2012 -0700 @@ -36,6 +36,7 @@ class HeapRegion; class CollectionSetChooser; +class G1GCPhaseTimes; // TraceGen0Time collects data on _both_ young and mixed evacuation pauses // (the latter may contain non-young regions - i.e. regions that are @@ -61,26 +62,14 @@ NumberSeq _parallel_other; NumberSeq _clear_ct; - void print_summary (int level, const char* str, const NumberSeq* seq) const; - void print_summary_sd (int level, const char* str, const NumberSeq* seq) const; + void print_summary(const char* str, const NumberSeq* seq) const; + void print_summary_sd(const char* str, const NumberSeq* seq) const; public: TraceGen0TimeData() : _young_pause_num(0), _mixed_pause_num(0) {}; void record_start_collection(double time_to_stop_the_world_ms); void record_yield_time(double yield_time_ms); - void record_end_collection( - double total_ms, - double other_ms, - double root_region_scan_wait_ms, - double parallel_ms, - double ext_root_scan_ms, - double satb_filtering_ms, - double update_rs_ms, - double scan_rs_ms, - double obj_copy_ms, - double termination_ms, - double parallel_other_ms, - double clear_ct_ms); + void record_end_collection(double pause_time_ms, G1GCPhaseTimes* phase_times); void increment_young_collection_count(); void increment_mixed_collection_count(); void print() const; @@ -186,25 +175,9 @@ CollectionSetChooser* _collectionSetChooser; - double _cur_collection_start_sec; + double _full_collection_start_sec; size_t _cur_collection_pause_used_at_start_bytes; uint _cur_collection_pause_used_regions_at_start; - double _cur_collection_par_time_ms; - - double _cur_collection_code_root_fixup_time_ms; - - double _cur_clear_ct_time_ms; - double _cur_ref_proc_time_ms; - double _cur_ref_enq_time_ms; - -#ifndef PRODUCT - // Card Table Count Cache stats - double _min_clear_cc_time_ms; // min - double _max_clear_cc_time_ms; // max - double _cur_clear_cc_time_ms; // clearing time during current pause - double _cum_clear_cc_time_ms; // cummulative clearing time - jlong _num_cc_clears; // number of times the card count cache has been cleared -#endif // These exclude marking times. TruncatedSeq* _recent_gc_times_ms; @@ -217,23 +190,6 @@ double _stop_world_start; - double* _par_last_gc_worker_start_times_ms; - double* _par_last_ext_root_scan_times_ms; - double* _par_last_satb_filtering_times_ms; - double* _par_last_update_rs_times_ms; - double* _par_last_update_rs_processed_buffers; - double* _par_last_scan_rs_times_ms; - double* _par_last_obj_copy_times_ms; - double* _par_last_termination_times_ms; - double* _par_last_termination_attempts; - double* _par_last_gc_worker_end_times_ms; - double* _par_last_gc_worker_times_ms; - - // Each workers 'other' time i.e. the elapsed time of the parallel - // code executed by a worker minus the sum of the individual sub-phase - // times for that worker thread. - double* _par_last_gc_worker_other_times_ms; - // indicates whether we are in young or mixed GC mode bool _gcs_are_young; @@ -306,10 +262,6 @@ size_t _recorded_rs_lengths; size_t _max_rs_lengths; - - double _recorded_young_free_cset_time_ms; - double _recorded_non_young_free_cset_time_ms; - double _sigma; size_t _rs_lengths_prediction; @@ -341,8 +293,7 @@ void set_no_of_gc_threads(uintx v) { _no_of_gc_threads = v; } double _pause_time_target_ms; - double _recorded_young_cset_choice_time_ms; - double _recorded_non_young_cset_choice_time_ms; + size_t _pending_cards; size_t _max_pending_cards; @@ -497,14 +448,6 @@ uint young_cset_region_length() { return eden_cset_region_length() + survivor_cset_region_length(); } - void record_young_free_cset_time_ms(double time_ms) { - _recorded_young_free_cset_time_ms = time_ms; - } - - void record_non_young_free_cset_time_ms(double time_ms) { - _recorded_non_young_free_cset_time_ms = time_ms; - } - double predict_survivor_regions_evac_time(); void cset_regions_freed() { @@ -552,19 +495,6 @@ } private: - void print_stats(int level, const char* str, double value); - void print_stats(int level, const char* str, double value, int workers); - void print_stats(int level, const char* str, int value); - - void print_par_stats(int level, const char* str, double* data, bool showDecimals = true); - - double avg_value (double* data); - double max_value (double* data); - double sum_of_values (double* data); - double max_sum (double* data1, double* data2); - - double _last_pause_time_ms; - size_t _bytes_in_collection_set_before_gc; size_t _bytes_copied_during_gc; @@ -638,6 +568,8 @@ // Stash a pointer to the g1 heap. G1CollectedHeap* _g1; + G1GCPhaseTimes* _phase_times; + // The ratio of gc time to elapsed time, computed over recent pauses. double _recent_avg_pause_time_ratio; @@ -677,7 +609,6 @@ double _cur_mark_stop_world_time_ms; double _mark_remark_start_sec; double _mark_cleanup_start_sec; - double _root_region_scan_wait_time_ms; // Update the young list target length either by setting it to the // desired fixed value or by calculating it using G1's pause @@ -728,6 +659,8 @@ return CollectorPolicy::G1CollectorPolicyKind; } + G1GCPhaseTimes* phase_times() const { return _phase_times; } + // Check the current value of the young list RSet lengths and // compare it against the last prediction. If the current value is // higher, recalculate the young list target length prediction. @@ -772,10 +705,6 @@ void record_concurrent_mark_init_end(double mark_init_elapsed_time_ms); - void record_root_region_scan_wait_time(double time_ms) { - _root_region_scan_wait_time_ms = time_ms; - } - void record_concurrent_mark_remark_start(); void record_concurrent_mark_remark_end(); @@ -784,97 +713,14 @@ void record_concurrent_mark_cleanup_completed(); void record_concurrent_pause(); - void record_concurrent_pause_end(); - void record_collection_pause_end(int no_of_gc_threads); + void record_collection_pause_end(double pause_time); void print_heap_transition(); // Record the fact that a full collection occurred. void record_full_collection_start(); void record_full_collection_end(); - void record_gc_worker_start_time(int worker_i, double ms) { - _par_last_gc_worker_start_times_ms[worker_i] = ms; - } - - void record_ext_root_scan_time(int worker_i, double ms) { - _par_last_ext_root_scan_times_ms[worker_i] = ms; - } - - void record_satb_filtering_time(int worker_i, double ms) { - _par_last_satb_filtering_times_ms[worker_i] = ms; - } - - void record_update_rs_time(int thread, double ms) { - _par_last_update_rs_times_ms[thread] = ms; - } - - void record_update_rs_processed_buffers (int thread, - double processed_buffers) { - _par_last_update_rs_processed_buffers[thread] = processed_buffers; - } - - void record_scan_rs_time(int thread, double ms) { - _par_last_scan_rs_times_ms[thread] = ms; - } - - void reset_obj_copy_time(int thread) { - _par_last_obj_copy_times_ms[thread] = 0.0; - } - - void reset_obj_copy_time() { - reset_obj_copy_time(0); - } - - void record_obj_copy_time(int thread, double ms) { - _par_last_obj_copy_times_ms[thread] += ms; - } - - void record_termination(int thread, double ms, size_t attempts) { - _par_last_termination_times_ms[thread] = ms; - _par_last_termination_attempts[thread] = (double) attempts; - } - - void record_gc_worker_end_time(int worker_i, double ms) { - _par_last_gc_worker_end_times_ms[worker_i] = ms; - } - - void record_pause_time_ms(double ms) { - _last_pause_time_ms = ms; - } - - void record_clear_ct_time(double ms) { - _cur_clear_ct_time_ms = ms; - } - - void record_par_time(double ms) { - _cur_collection_par_time_ms = ms; - } - - void record_code_root_fixup_time(double ms) { - _cur_collection_code_root_fixup_time_ms = ms; - } - - void record_ref_proc_time(double ms) { - _cur_ref_proc_time_ms = ms; - } - - void record_ref_enq_time(double ms) { - _cur_ref_enq_time_ms = ms; - } - -#ifndef PRODUCT - void record_cc_clear_time(double ms) { - if (_min_clear_cc_time_ms < 0.0 || ms <= _min_clear_cc_time_ms) - _min_clear_cc_time_ms = ms; - if (_max_clear_cc_time_ms < 0.0 || ms >= _max_clear_cc_time_ms) - _max_clear_cc_time_ms = ms; - _cur_clear_cc_time_ms = ms; - _cum_clear_cc_time_ms += ms; - _num_cc_clears++; - } -#endif - // Record how much space we copied during a GC. This is typically // called when a GC alloc region is being retired. void record_bytes_copied_during_gc(size_t bytes) { diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2012, 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 "gc_implementation/g1/g1CollectedHeap.inline.hpp" +#include "gc_implementation/g1/g1GCPhaseTimes.hpp" +#include "gc_implementation/g1/g1Log.hpp" + +// Helper class for avoiding interleaved logging +class LineBuffer: public StackObj { + +private: + static const int BUFFER_LEN = 1024; + static const int INDENT_CHARS = 3; + char _buffer[BUFFER_LEN]; + int _indent_level; + int _cur; + + void vappend(const char* format, va_list ap) { + int res = vsnprintf(&_buffer[_cur], BUFFER_LEN - _cur, format, ap); + if (res != -1) { + _cur += res; + } else { + DEBUG_ONLY(warning("buffer too small in LineBuffer");) + _buffer[BUFFER_LEN -1] = 0; + _cur = BUFFER_LEN; // vsnprintf above should not add to _buffer if we are called again + } + } + +public: + explicit LineBuffer(int indent_level): _indent_level(indent_level), _cur(0) { + for (; (_cur < BUFFER_LEN && _cur < (_indent_level * INDENT_CHARS)); _cur++) { + _buffer[_cur] = ' '; + } + } + +#ifndef PRODUCT + ~LineBuffer() { + assert(_cur == _indent_level * INDENT_CHARS, "pending data in buffer - append_and_print_cr() not called?"); + } +#endif + + void append(const char* format, ...) { + va_list ap; + va_start(ap, format); + vappend(format, ap); + va_end(ap); + } + + void append_and_print_cr(const char* format, ...) { + va_list ap; + va_start(ap, format); + vappend(format, ap); + va_end(ap); + gclog_or_tty->print_cr("%s", _buffer); + _cur = _indent_level * INDENT_CHARS; + } +}; + +G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : + _max_gc_threads(max_gc_threads), + _min_clear_cc_time_ms(-1.0), + _max_clear_cc_time_ms(-1.0), + _cur_clear_cc_time_ms(0.0), + _cum_clear_cc_time_ms(0.0), + _num_cc_clears(0L) +{ + assert(max_gc_threads > 0, "Must have some GC threads"); + _par_last_gc_worker_start_times_ms = new double[_max_gc_threads]; + _par_last_ext_root_scan_times_ms = new double[_max_gc_threads]; + _par_last_satb_filtering_times_ms = new double[_max_gc_threads]; + _par_last_update_rs_times_ms = new double[_max_gc_threads]; + _par_last_update_rs_processed_buffers = new double[_max_gc_threads]; + _par_last_scan_rs_times_ms = new double[_max_gc_threads]; + _par_last_obj_copy_times_ms = new double[_max_gc_threads]; + _par_last_termination_times_ms = new double[_max_gc_threads]; + _par_last_termination_attempts = new double[_max_gc_threads]; + _par_last_gc_worker_end_times_ms = new double[_max_gc_threads]; + _par_last_gc_worker_times_ms = new double[_max_gc_threads]; + _par_last_gc_worker_other_times_ms = new double[_max_gc_threads]; +} + +void G1GCPhaseTimes::note_gc_start(double pause_start_time_sec, uint active_gc_threads, + bool is_young_gc, bool is_initial_mark_gc, GCCause::Cause gc_cause) { + assert(active_gc_threads > 0, "The number of threads must be > 0"); + assert(active_gc_threads <= _max_gc_threads, "The number of active threads must be <= the max nubmer of threads"); + _active_gc_threads = active_gc_threads; + _pause_start_time_sec = pause_start_time_sec; + _is_young_gc = is_young_gc; + _is_initial_mark_gc = is_initial_mark_gc; + _gc_cause = gc_cause; + +#ifdef ASSERT + // initialise the timing data to something well known so that we can spot + // if something is not set properly + + for (uint i = 0; i < _max_gc_threads; ++i) { + _par_last_gc_worker_start_times_ms[i] = -1234.0; + _par_last_ext_root_scan_times_ms[i] = -1234.0; + _par_last_satb_filtering_times_ms[i] = -1234.0; + _par_last_update_rs_times_ms[i] = -1234.0; + _par_last_update_rs_processed_buffers[i] = -1234.0; + _par_last_scan_rs_times_ms[i] = -1234.0; + _par_last_obj_copy_times_ms[i] = -1234.0; + _par_last_termination_times_ms[i] = -1234.0; + _par_last_termination_attempts[i] = -1234.0; + _par_last_gc_worker_end_times_ms[i] = -1234.0; + _par_last_gc_worker_times_ms[i] = -1234.0; + _par_last_gc_worker_other_times_ms[i] = -1234.0; + } +#endif +} + +void G1GCPhaseTimes::note_gc_end(double pause_end_time_sec) { + if (G1Log::fine()) { + double pause_time_ms = (pause_end_time_sec - _pause_start_time_sec) * MILLIUNITS; + + for (uint i = 0; i < _active_gc_threads; i++) { + _par_last_gc_worker_times_ms[i] = _par_last_gc_worker_end_times_ms[i] - + _par_last_gc_worker_start_times_ms[i]; + + double worker_known_time = _par_last_ext_root_scan_times_ms[i] + + _par_last_satb_filtering_times_ms[i] + + _par_last_update_rs_times_ms[i] + + _par_last_scan_rs_times_ms[i] + + _par_last_obj_copy_times_ms[i] + + _par_last_termination_times_ms[i]; + + _par_last_gc_worker_other_times_ms[i] = _par_last_gc_worker_times_ms[i] - + worker_known_time; + } + + print(pause_time_ms); + } + +} + +void G1GCPhaseTimes::print_par_stats(int level, + const char* str, + double* data, + bool showDecimals) { + double min = data[0], max = data[0]; + double total = 0.0; + LineBuffer buf(level); + buf.append("[%s (ms):", str); + for (uint i = 0; i < _active_gc_threads; ++i) { + double val = data[i]; + if (val < min) + min = val; + if (val > max) + max = val; + total += val; + if (G1Log::finest()) { + if (showDecimals) { + buf.append(" %.1lf", val); + } else { + buf.append(" %d", (int)val); + } + } + } + + if (G1Log::finest()) { + buf.append_and_print_cr(""); + } + double avg = total / (double) _active_gc_threads; + if (showDecimals) { + buf.append_and_print_cr(" Min: %.1lf, Avg: %.1lf, Max: %.1lf, Diff: %.1lf, Sum: %.1lf]", + min, avg, max, max - min, total); + } else { + buf.append_and_print_cr(" Min: %d, Avg: %d, Max: %d, Diff: %d, Sum: %d]", + (int)min, (int)avg, (int)max, (int)max - (int)min, (int)total); + } +} + +void G1GCPhaseTimes::print_stats(int level, const char* str, double value) { + LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value); +} + +void G1GCPhaseTimes::print_stats(int level, const char* str, double value, int workers) { + LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %d]", str, value, workers); +} + +void G1GCPhaseTimes::print_stats(int level, const char* str, int value) { + LineBuffer(level).append_and_print_cr("[%s: %d]", str, value); +} + +double G1GCPhaseTimes::avg_value(double* data) { + if (G1CollectedHeap::use_parallel_gc_threads()) { + double ret = 0.0; + for (uint i = 0; i < _active_gc_threads; ++i) { + ret += data[i]; + } + return ret / (double) _active_gc_threads; + } else { + return data[0]; + } +} + +double G1GCPhaseTimes::max_value(double* data) { + if (G1CollectedHeap::use_parallel_gc_threads()) { + double ret = data[0]; + for (uint i = 1; i < _active_gc_threads; ++i) { + if (data[i] > ret) { + ret = data[i]; + } + } + return ret; + } else { + return data[0]; + } +} + +double G1GCPhaseTimes::sum_of_values(double* data) { + if (G1CollectedHeap::use_parallel_gc_threads()) { + double sum = 0.0; + for (uint i = 0; i < _active_gc_threads; i++) { + sum += data[i]; + } + return sum; + } else { + return data[0]; + } +} + +double G1GCPhaseTimes::max_sum(double* data1, double* data2) { + double ret = data1[0] + data2[0]; + + if (G1CollectedHeap::use_parallel_gc_threads()) { + for (uint i = 1; i < _active_gc_threads; ++i) { + double data = data1[i] + data2[i]; + if (data > ret) { + ret = data; + } + } + } + return ret; +} + +void G1GCPhaseTimes::collapse_par_times() { + _ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms); + _satb_filtering_time = avg_value(_par_last_satb_filtering_times_ms); + _update_rs_time = avg_value(_par_last_update_rs_times_ms); + _update_rs_processed_buffers = + sum_of_values(_par_last_update_rs_processed_buffers); + _scan_rs_time = avg_value(_par_last_scan_rs_times_ms); + _obj_copy_time = avg_value(_par_last_obj_copy_times_ms); + _termination_time = avg_value(_par_last_termination_times_ms); +} + +double G1GCPhaseTimes::accounted_time_ms() { + // Subtract the root region scanning wait time. It's initialized to + // zero at the start of the pause. + double misc_time_ms = _root_region_scan_wait_time_ms; + + misc_time_ms += _cur_collection_par_time_ms; + + // Now subtract the time taken to fix up roots in generated code + misc_time_ms += _cur_collection_code_root_fixup_time_ms; + + // Subtract the time taken to clean the card table from the + // current value of "other time" + misc_time_ms += _cur_clear_ct_time_ms; + + return misc_time_ms; +} + +void G1GCPhaseTimes::print(double pause_time_ms) { + + if (PrintGCTimeStamps) { + gclog_or_tty->stamp(); + gclog_or_tty->print(": "); + } + + GCCauseString gc_cause_str = GCCauseString("GC pause", _gc_cause) + .append(_is_young_gc ? " (young)" : " (mixed)") + .append(_is_initial_mark_gc ? " (initial-mark)" : ""); + gclog_or_tty->print_cr("[%s, %3.7f secs]", (const char*)gc_cause_str, pause_time_ms / 1000.0); + + if (!G1Log::finer()) { + return; + } + + if (_root_region_scan_wait_time_ms > 0.0) { + print_stats(1, "Root Region Scan Waiting", _root_region_scan_wait_time_ms); + } + if (G1CollectedHeap::use_parallel_gc_threads()) { + print_stats(1, "Parallel Time", _cur_collection_par_time_ms, _active_gc_threads); + print_par_stats(2, "GC Worker Start", _par_last_gc_worker_start_times_ms); + print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms); + if (_satb_filtering_time > 0.0) { + print_par_stats(2, "SATB Filtering", _par_last_satb_filtering_times_ms); + } + print_par_stats(2, "Update RS", _par_last_update_rs_times_ms); + if (G1Log::finest()) { + print_par_stats(3, "Processed Buffers", _par_last_update_rs_processed_buffers, + false /* showDecimals */); + } + print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms); + print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms); + print_par_stats(2, "Termination", _par_last_termination_times_ms); + if (G1Log::finest()) { + print_par_stats(3, "Termination Attempts", _par_last_termination_attempts, + false /* showDecimals */); + } + print_par_stats(2, "GC Worker Other", _par_last_gc_worker_other_times_ms); + print_par_stats(2, "GC Worker Total", _par_last_gc_worker_times_ms); + print_par_stats(2, "GC Worker End", _par_last_gc_worker_end_times_ms); + } else { + print_stats(1, "Ext Root Scanning", _ext_root_scan_time); + if (_satb_filtering_time > 0.0) { + print_stats(1, "SATB Filtering", _satb_filtering_time); + } + print_stats(1, "Update RS", _update_rs_time); + if (G1Log::finest()) { + print_stats(2, "Processed Buffers", (int)_update_rs_processed_buffers); + } + print_stats(1, "Scan RS", _scan_rs_time); + print_stats(1, "Object Copying", _obj_copy_time); + } + print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms); + print_stats(1, "Clear CT", _cur_clear_ct_time_ms); + if (Verbose && G1Log::finest()) { + print_stats(1, "Cur Clear CC", _cur_clear_cc_time_ms); + print_stats(1, "Cum Clear CC", _cum_clear_cc_time_ms); + print_stats(1, "Min Clear CC", _min_clear_cc_time_ms); + print_stats(1, "Max Clear CC", _max_clear_cc_time_ms); + if (_num_cc_clears > 0) { + print_stats(1, "Avg Clear CC", _cum_clear_cc_time_ms / ((double)_num_cc_clears)); + } + } + double misc_time_ms = pause_time_ms - accounted_time_ms(); + print_stats(1, "Other", misc_time_ms); + print_stats(2, "Choose CSet", + (_recorded_young_cset_choice_time_ms + + _recorded_non_young_cset_choice_time_ms)); + print_stats(2, "Ref Proc", _cur_ref_proc_time_ms); + print_stats(2, "Ref Enq", _cur_ref_enq_time_ms); + print_stats(2, "Free CSet", + (_recorded_young_free_cset_time_ms + + _recorded_non_young_free_cset_time_ms)); +} + +void G1GCPhaseTimes::record_cc_clear_time_ms(double ms) { + if (!(Verbose && G1Log::finest())) { + return; + } + + if (_min_clear_cc_time_ms < 0.0 || ms <= _min_clear_cc_time_ms) { + _min_clear_cc_time_ms = ms; + } + if (_max_clear_cc_time_ms < 0.0 || ms >= _max_clear_cc_time_ms) { + _max_clear_cc_time_ms = ms; + } + _cur_clear_cc_time_ms = ms; + _cum_clear_cc_time_ms += ms; + _num_cc_clears++; +} diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Mon Jul 23 12:54:20 2012 -0700 @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP +#define SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP + +#include "memory/allocation.hpp" +#include "gc_interface/gcCause.hpp" + +class G1GCPhaseTimes : public CHeapObj { + friend class G1CollectorPolicy; + friend class TraceGen0TimeData; + + private: + uint _active_gc_threads; + uint _max_gc_threads; + + GCCause::Cause _gc_cause; + bool _is_young_gc; + bool _is_initial_mark_gc; + + double _pause_start_time_sec; + + double* _par_last_gc_worker_start_times_ms; + double* _par_last_ext_root_scan_times_ms; + double* _par_last_satb_filtering_times_ms; + double* _par_last_update_rs_times_ms; + double* _par_last_update_rs_processed_buffers; + double* _par_last_scan_rs_times_ms; + double* _par_last_obj_copy_times_ms; + double* _par_last_termination_times_ms; + double* _par_last_termination_attempts; + double* _par_last_gc_worker_end_times_ms; + double* _par_last_gc_worker_times_ms; + double* _par_last_gc_worker_other_times_ms; + + double _cur_collection_par_time_ms; + + double _cur_collection_code_root_fixup_time_ms; + + double _cur_clear_ct_time_ms; + double _cur_ref_proc_time_ms; + double _cur_ref_enq_time_ms; + + // Helper methods for detailed logging + void print_par_stats(int level, const char* str, double* data, bool showDecimals = true); + void print_stats(int level, const char* str, double value); + void print_stats(int level, const char* str, double value, int workers); + void print_stats(int level, const char* str, int value); + double avg_value(double* data); + double max_value(double* data); + double sum_of_values(double* data); + double max_sum(double* data1, double* data2); + double accounted_time_ms(); + + // Card Table Count Cache stats + double _min_clear_cc_time_ms; // min + double _max_clear_cc_time_ms; // max + double _cur_clear_cc_time_ms; // clearing time during current pause + double _cum_clear_cc_time_ms; // cummulative clearing time + jlong _num_cc_clears; // number of times the card count cache has been cleared + + // The following insance variables are directly accessed by G1CollectorPolicy + // and TraceGen0TimeData. This is why those classes are declared friends. + // An alternative is to add getters and setters for all of these fields. + // It might also be possible to restructure the code to reduce these + // dependencies. + double _ext_root_scan_time; + double _satb_filtering_time; + double _update_rs_time; + double _update_rs_processed_buffers; + double _scan_rs_time; + double _obj_copy_time; + double _termination_time; + + double _cur_collection_start_sec; + double _root_region_scan_wait_time_ms; + + double _recorded_young_cset_choice_time_ms; + double _recorded_non_young_cset_choice_time_ms; + + double _recorded_young_free_cset_time_ms; + double _recorded_non_young_free_cset_time_ms; + + void print(double pause_time_ms); + + public: + G1GCPhaseTimes(uint max_gc_threads); + void note_gc_start(double pause_start_time_sec, uint active_gc_threads, + bool is_young_gc, bool is_initial_mark_gc, GCCause::Cause gc_cause); + void note_gc_end(double pause_end_time_sec); + void collapse_par_times(); + + void record_gc_worker_start_time(uint worker_i, double ms) { + assert(worker_i >= 0, "worker index must be > 0"); + assert(worker_i < _active_gc_threads, "worker index out of bounds"); + _par_last_gc_worker_start_times_ms[worker_i] = ms; + } + + void record_ext_root_scan_time(uint worker_i, double ms) { + assert(worker_i >= 0, "worker index must be > 0"); + assert(worker_i < _active_gc_threads, "worker index out of bounds"); + _par_last_ext_root_scan_times_ms[worker_i] = ms; + } + + void record_satb_filtering_time(uint worker_i, double ms) { + assert(worker_i >= 0, "worker index must be > 0"); + assert(worker_i < _active_gc_threads, "worker index out of bounds"); + _par_last_satb_filtering_times_ms[worker_i] = ms; + } + + void record_update_rs_time(uint worker_i, double ms) { + assert(worker_i >= 0, "worker index must be > 0"); + assert(worker_i < _active_gc_threads, "worker index out of bounds"); + _par_last_update_rs_times_ms[worker_i] = ms; + } + + void record_update_rs_processed_buffers (uint worker_i, + double processed_buffers) { + assert(worker_i >= 0, "worker index must be > 0"); + assert(worker_i < _active_gc_threads, "worker index out of bounds"); + _par_last_update_rs_processed_buffers[worker_i] = processed_buffers; + } + + void record_scan_rs_time(uint worker_i, double ms) { + assert(worker_i >= 0, "worker index must be > 0"); + assert(worker_i < _active_gc_threads, "worker index out of bounds"); + _par_last_scan_rs_times_ms[worker_i] = ms; + } + + void reset_obj_copy_time(uint worker_i) { + assert(worker_i >= 0, "worker index must be > 0"); + assert(worker_i < _active_gc_threads, "worker index out of bounds"); + _par_last_obj_copy_times_ms[worker_i] = 0.0; + } + + void reset_obj_copy_time() { + reset_obj_copy_time(0); + } + + void record_obj_copy_time(uint worker_i, double ms) { + assert(worker_i >= 0, "worker index must be > 0"); + assert(worker_i < _active_gc_threads, "worker index out of bounds"); + _par_last_obj_copy_times_ms[worker_i] += ms; + } + + void record_termination(uint worker_i, double ms, size_t attempts) { + assert(worker_i >= 0, "worker index must be > 0"); + assert(worker_i < _active_gc_threads, "worker index out of bounds"); + _par_last_termination_times_ms[worker_i] = ms; + _par_last_termination_attempts[worker_i] = (double) attempts; + } + + void record_gc_worker_end_time(uint worker_i, double ms) { + assert(worker_i >= 0, "worker index must be > 0"); + assert(worker_i < _active_gc_threads, "worker index out of bounds"); + _par_last_gc_worker_end_times_ms[worker_i] = ms; + } + + void record_clear_ct_time(double ms) { + _cur_clear_ct_time_ms = ms; + } + + void record_par_time(double ms) { + _cur_collection_par_time_ms = ms; + } + + void record_code_root_fixup_time(double ms) { + _cur_collection_code_root_fixup_time_ms = ms; + } + + void record_ref_proc_time(double ms) { + _cur_ref_proc_time_ms = ms; + } + + void record_ref_enq_time(double ms) { + _cur_ref_enq_time_ms = ms; + } + + void record_root_region_scan_wait_time(double time_ms) { + _root_region_scan_wait_time_ms = time_ms; + } + + void record_cc_clear_time_ms(double ms); + + void record_young_free_cset_time_ms(double time_ms) { + _recorded_young_free_cset_time_ms = time_ms; + } + + void record_non_young_free_cset_time_ms(double time_ms) { + _recorded_non_young_free_cset_time_ms = time_ms; + } +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/gc_implementation/g1/g1RemSet.cpp --- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -29,6 +29,7 @@ #include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectorPolicy.hpp" +#include "gc_implementation/g1/g1GCPhaseTimes.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" #include "gc_implementation/g1/g1RemSet.inline.hpp" #include "gc_implementation/g1/heapRegionSeq.inline.hpp" @@ -224,7 +225,7 @@ assert( _cards_scanned != NULL, "invariant" ); _cards_scanned[worker_i] = scanRScl.cards_done(); - _g1p->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0); + _g1p->phase_times()->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0); } // Closure used for updating RSets and recording references that @@ -276,7 +277,7 @@ guarantee(cl.n() == 0, "Card table should be clean."); } - _g1p->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0); + _g1p->phase_times()->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0); } class CountRSSizeClosure: public HeapRegionClosure { @@ -390,13 +391,13 @@ if (G1UseParallelRSetUpdating || (worker_i == 0)) { updateRS(&into_cset_dcq, worker_i); } else { - _g1p->record_update_rs_processed_buffers(worker_i, 0.0); - _g1p->record_update_rs_time(worker_i, 0.0); + _g1p->phase_times()->record_update_rs_processed_buffers(worker_i, 0.0); + _g1p->phase_times()->record_update_rs_time(worker_i, 0.0); } if (G1UseParallelRSetScanning || (worker_i == 0)) { scanRS(oc, worker_i); } else { - _g1p->record_scan_rs_time(worker_i, 0.0); + _g1p->phase_times()->record_scan_rs_time(worker_i, 0.0); } // We now clear the cached values of _cset_rs_update_cl for this worker diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/interpreter/interpreterRuntime.cpp --- a/src/share/vm/interpreter/interpreterRuntime.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, 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 @@ -375,7 +375,6 @@ Handle h_exception(thread, exception); methodHandle h_method (thread, method(thread)); constantPoolHandle h_constants(thread, h_method->constants()); - typeArrayHandle h_extable (thread, h_method->exception_table()); bool should_repeat; int handler_bci; int current_bci = bci(thread); @@ -547,23 +546,6 @@ } } - if (is_put && !is_static && klass->is_subclass_of(SystemDictionary::CallSite_klass()) && (info.name() == vmSymbols::target_name())) { - const jint direction = frame::interpreter_frame_expression_stack_direction(); - Handle call_site (THREAD, *((oop*) thread->last_frame().interpreter_frame_tos_at(-1 * direction))); - Handle method_handle(THREAD, *((oop*) thread->last_frame().interpreter_frame_tos_at( 0 * direction))); - assert(call_site ->is_a(SystemDictionary::CallSite_klass()), "must be"); - assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "must be"); - - { - // Walk all nmethods depending on this call site. - MutexLocker mu(Compile_lock, thread); - Universe::flush_dependents_on(call_site, method_handle); - } - - // Don't allow fast path for setting CallSite.target and sub-classes. - put_code = (Bytecodes::Code) 0; - } - cache_entry(thread)->set_field( get_code, put_code, diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/memory/dump.cpp --- a/src/share/vm/memory/dump.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/memory/dump.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -231,8 +231,6 @@ if (obj->is_constMethod()) { mark_object(obj); mark_object(constMethodOop(obj)->stackmap_data()); - // Exception tables are needed by ci code during compilation. - mark_object(constMethodOop(obj)->exception_table()); } // Mark objects referenced by klass objects which are read-only. @@ -513,7 +511,6 @@ for(i = 0; i < methods->length(); i++) { methodOop m = methodOop(methods->obj_at(i)); mark_and_move_for_policy(OP_favor_startup, m->constMethod(), _move_ro); - mark_and_move_for_policy(OP_favor_runtime, m->constMethod()->exception_table(), _move_ro); mark_and_move_for_policy(OP_favor_runtime, m->constMethod()->stackmap_data(), _move_ro); } diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/memory/oopFactory.cpp --- a/src/share/vm/memory/oopFactory.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/memory/oopFactory.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -140,14 +140,15 @@ constMethodOop oopFactory::new_constMethod(int byte_code_size, int compressed_line_number_size, int localvariable_table_length, + int exception_table_length, int checked_exceptions_length, bool is_conc_safe, TRAPS) { klassOop cmkObj = Universe::constMethodKlassObj(); constMethodKlass* cmk = constMethodKlass::cast(cmkObj); return cmk->allocate(byte_code_size, compressed_line_number_size, - localvariable_table_length, checked_exceptions_length, - is_conc_safe, + localvariable_table_length, exception_table_length, + checked_exceptions_length, is_conc_safe, CHECK_NULL); } @@ -155,6 +156,7 @@ methodOop oopFactory::new_method(int byte_code_size, AccessFlags access_flags, int compressed_line_number_size, int localvariable_table_length, + int exception_table_length, int checked_exceptions_length, bool is_conc_safe, TRAPS) { @@ -164,6 +166,7 @@ constMethodOop cm = new_constMethod(byte_code_size, compressed_line_number_size, localvariable_table_length, + exception_table_length, checked_exceptions_length, is_conc_safe, CHECK_NULL); constMethodHandle rw(THREAD, cm); diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/memory/oopFactory.hpp --- a/src/share/vm/memory/oopFactory.hpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/memory/oopFactory.hpp Mon Jul 23 12:54:20 2012 -0700 @@ -86,6 +86,7 @@ static constMethodOop new_constMethod(int byte_code_size, int compressed_line_number_size, int localvariable_table_length, + int exception_table_length, int checked_exceptions_length, bool is_conc_safe, TRAPS); @@ -97,6 +98,7 @@ AccessFlags access_flags, int compressed_line_number_size, int localvariable_table_length, + int exception_table_length, int checked_exceptions_length, bool is_conc_safe, TRAPS); diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/oops/constMethodKlass.cpp --- a/src/share/vm/oops/constMethodKlass.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/oops/constMethodKlass.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -65,6 +65,7 @@ constMethodOop constMethodKlass::allocate(int byte_code_size, int compressed_line_number_size, int localvariable_table_length, + int exception_table_length, int checked_exceptions_length, bool is_conc_safe, TRAPS) { @@ -72,6 +73,7 @@ int size = constMethodOopDesc::object_size(byte_code_size, compressed_line_number_size, localvariable_table_length, + exception_table_length, checked_exceptions_length); KlassHandle h_k(THREAD, as_klassOop()); constMethodOop cm = (constMethodOop) @@ -82,12 +84,12 @@ cm->init_fingerprint(); cm->set_constants(NULL); cm->set_stackmap_data(NULL); - cm->set_exception_table(NULL); cm->set_code_size(byte_code_size); cm->set_constMethod_size(size); cm->set_inlined_tables_length(checked_exceptions_length, compressed_line_number_size, - localvariable_table_length); + localvariable_table_length, + exception_table_length); assert(cm->size() == size, "wrong size for object"); cm->set_is_conc_safe(is_conc_safe); cm->set_partially_loaded(); @@ -100,7 +102,6 @@ constMethodOop cm = constMethodOop(obj); MarkSweep::mark_and_push(cm->adr_constants()); MarkSweep::mark_and_push(cm->adr_stackmap_data()); - MarkSweep::mark_and_push(cm->adr_exception_table()); // Performance tweak: We skip iterating over the klass pointer since we // know that Universe::constMethodKlassObj never moves. } @@ -112,7 +113,6 @@ constMethodOop cm_oop = constMethodOop(obj); PSParallelCompact::mark_and_push(cm, cm_oop->adr_constants()); PSParallelCompact::mark_and_push(cm, cm_oop->adr_stackmap_data()); - PSParallelCompact::mark_and_push(cm, cm_oop->adr_exception_table()); // Performance tweak: We skip iterating over the klass pointer since we // know that Universe::constMethodKlassObj never moves. } @@ -123,7 +123,6 @@ constMethodOop cm = constMethodOop(obj); blk->do_oop(cm->adr_constants()); blk->do_oop(cm->adr_stackmap_data()); - blk->do_oop(cm->adr_exception_table()); // Get size before changing pointers. // Don't call size() or oop_size() since that is a virtual call. int size = cm->object_size(); @@ -139,8 +138,6 @@ if (mr.contains(adr)) blk->do_oop(adr); adr = cm->adr_stackmap_data(); if (mr.contains(adr)) blk->do_oop(adr); - adr = cm->adr_exception_table(); - if (mr.contains(adr)) blk->do_oop(adr); // Get size before changing pointers. // Don't call size() or oop_size() since that is a virtual call. int size = cm->object_size(); @@ -155,7 +152,6 @@ constMethodOop cm = constMethodOop(obj); MarkSweep::adjust_pointer(cm->adr_constants()); MarkSweep::adjust_pointer(cm->adr_stackmap_data()); - MarkSweep::adjust_pointer(cm->adr_exception_table()); // Get size before changing pointers. // Don't call size() or oop_size() since that is a virtual call. int size = cm->object_size(); @@ -190,7 +186,6 @@ constMethodOop m = constMethodOop(obj); st->print(" - constants: " INTPTR_FORMAT " ", (address)m->constants()); m->constants()->print_value_on(st); st->cr(); - st->print(" - exceptions: " INTPTR_FORMAT "\n", (address)m->exception_table()); if (m->has_stackmap_table()) { st->print(" - stackmap data: "); m->stackmap_data()->print_value_on(st); @@ -228,8 +223,6 @@ typeArrayOop stackmap_data = m->stackmap_data(); guarantee(stackmap_data == NULL || stackmap_data->is_perm(), "should be in permspace"); - guarantee(m->exception_table()->is_perm(), "should be in permspace"); - guarantee(m->exception_table()->is_typeArray(), "should be type array"); address m_end = (address)((oop*) m + m->size()); address compressed_table_start = m->code_end(); @@ -244,11 +237,15 @@ compressed_table_end += stream.position(); } guarantee(compressed_table_end <= m_end, "invalid method layout"); - // Verify checked exceptions and local variable tables + // Verify checked exceptions, exception table and local variable tables if (m->has_checked_exceptions()) { u2* addr = m->checked_exceptions_length_addr(); guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout"); } + if (m->has_exception_handler()) { + u2* addr = m->exception_table_length_addr(); + guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout"); + } if (m->has_localvariable_table()) { u2* addr = m->localvariable_table_length_addr(); guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout"); @@ -257,12 +254,12 @@ u2* uncompressed_table_start; if (m->has_localvariable_table()) { uncompressed_table_start = (u2*) m->localvariable_table_start(); - } else { - if (m->has_checked_exceptions()) { + } else if (m->has_exception_handler()) { + uncompressed_table_start = (u2*) m->exception_table_start(); + } else if (m->has_checked_exceptions()) { uncompressed_table_start = (u2*) m->checked_exceptions_start(); - } else { + } else { uncompressed_table_start = (u2*) m_end; - } } int gap = (intptr_t) uncompressed_table_start - (intptr_t) compressed_table_end; int max_gap = align_object_size(1)*BytesPerWord; @@ -273,8 +270,8 @@ bool constMethodKlass::oop_partially_loaded(oop obj) const { assert(obj->is_constMethod(), "object must be klass"); constMethodOop m = constMethodOop(obj); - // check whether exception_table points to self (flag for partially loaded) - return m->exception_table() == (typeArrayOop)obj; + // check whether stackmap_data points to self (flag for partially loaded) + return m->stackmap_data() == (typeArrayOop)obj; } @@ -282,6 +279,6 @@ void constMethodKlass::oop_set_partially_loaded(oop obj) { assert(obj->is_constMethod(), "object must be klass"); constMethodOop m = constMethodOop(obj); - // Temporarily set exception_table to point to self - m->set_exception_table((typeArrayOop)obj); + // Temporarily set stackmap_data to point to self + m->set_stackmap_data((typeArrayOop)obj); } diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/oops/constMethodKlass.hpp --- a/src/share/vm/oops/constMethodKlass.hpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/oops/constMethodKlass.hpp Mon Jul 23 12:54:20 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, 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 @@ DEFINE_ALLOCATE_PERMANENT(constMethodKlass); constMethodOop allocate(int byte_code_size, int compressed_line_number_size, int localvariable_table_length, + int exception_table_length, int checked_exceptions_length, bool is_conc_safe, TRAPS); diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/oops/constMethodOop.cpp --- a/src/share/vm/oops/constMethodOop.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/oops/constMethodOop.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -35,6 +35,7 @@ int constMethodOopDesc::object_size(int code_size, int compressed_line_number_size, int local_variable_table_length, + int exception_table_length, int checked_exceptions_length) { int extra_bytes = code_size; if (compressed_line_number_size > 0) { @@ -49,6 +50,10 @@ extra_bytes += local_variable_table_length * sizeof(LocalVariableTableElement); } + if (exception_table_length > 0) { + extra_bytes += sizeof(u2); + extra_bytes += exception_table_length * sizeof(ExceptionTableElement); + } int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord; return align_object_size(header_size() + extra_words); } @@ -73,23 +78,40 @@ return last_u2_element(); } -u2* constMethodOopDesc::localvariable_table_length_addr() const { - assert(has_localvariable_table(), "called only if table is present"); +u2* constMethodOopDesc::exception_table_length_addr() const { + assert(has_exception_handler(), "called only if table is present"); if (has_checked_exceptions()) { // If checked_exception present, locate immediately before them. return (u2*) checked_exceptions_start() - 1; } else { - // Else, the linenumber table is at the end of the constMethod. + // Else, the exception table is at the end of the constMethod. return last_u2_element(); } } +u2* constMethodOopDesc::localvariable_table_length_addr() const { + assert(has_localvariable_table(), "called only if table is present"); + if (has_exception_handler()) { + // If exception_table present, locate immediately before them. + return (u2*) exception_table_start() - 1; + } else { + if (has_checked_exceptions()) { + // If checked_exception present, locate immediately before them. + return (u2*) checked_exceptions_start() - 1; + } else { + // Else, the linenumber table is at the end of the constMethod. + return last_u2_element(); + } + } +} + // Update the flags to indicate the presence of these optional fields. void constMethodOopDesc::set_inlined_tables_length( int checked_exceptions_len, int compressed_line_number_size, - int localvariable_table_len) { + int localvariable_table_len, + int exception_table_len) { // Must be done in the order below, otherwise length_addr accessors // will not work. Only set bit in header if length is positive. assert(_flags == 0, "Error"); @@ -100,6 +122,10 @@ _flags |= _has_checked_exceptions; *(checked_exceptions_length_addr()) = checked_exceptions_len; } + if (exception_table_len > 0) { + _flags |= _has_exception_table; + *(exception_table_length_addr()) = exception_table_len; + } if (localvariable_table_len > 0) { _flags |= _has_localvariable_table; *(localvariable_table_length_addr()) = localvariable_table_len; @@ -133,3 +159,15 @@ addr -= length * sizeof(LocalVariableTableElement) / sizeof(u2); return (LocalVariableTableElement*) addr; } + +int constMethodOopDesc::exception_table_length() const { + return has_exception_handler() ? *(exception_table_length_addr()) : 0; +} + +ExceptionTableElement* constMethodOopDesc::exception_table_start() const { + u2* addr = exception_table_length_addr(); + u2 length = *addr; + assert(length > 0, "should only be called if table is present"); + addr -= length * sizeof(ExceptionTableElement) / sizeof(u2); + return (ExceptionTableElement*)addr; +} diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/oops/constMethodOop.hpp --- a/src/share/vm/oops/constMethodOop.hpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/oops/constMethodOop.hpp Mon Jul 23 12:54:20 2012 -0700 @@ -43,7 +43,6 @@ // | fingerprint 2 | // | constants (oop) | // | stackmap_data (oop) | -// | exception_table (oop) | // | constMethod_size | // | interp_kind | flags | code_size | // | name index | signature index | @@ -64,7 +63,13 @@ // | (length is u2, elements are 6-tuples of u2) | // | (see class LocalVariableTableElement) | // | (access flags bit tells whether table is present) | -// | (indexed from end of contMethodOop) | +// | (indexed from end of constMethodOop) | +// |------------------------------------------------------| +// | exception table + length (length last) | +// | (length is u2, elements are 4-tuples of u2) | +// | (see class ExceptionTableElement) | +// | (access flags bit tells whether table is present) | +// | (indexed from end of constMethodOop) | // |------------------------------------------------------| // | checked exceptions elements + length (length last) | // | (length is u2, elements are u2) | @@ -93,6 +98,15 @@ }; +// Utitily class describing elements in exception table +class ExceptionTableElement VALUE_OBJ_CLASS_SPEC { + public: + u2 start_pc; + u2 end_pc; + u2 handler_pc; + u2 catch_type_index; +}; + class constMethodOopDesc : public oopDesc { friend class constMethodKlass; friend class VMStructs; @@ -100,7 +114,8 @@ enum { _has_linenumber_table = 1, _has_checked_exceptions = 2, - _has_localvariable_table = 4 + _has_localvariable_table = 4, + _has_exception_table = 8 }; // Bit vector of signature @@ -114,7 +129,7 @@ public: oop* oop_block_beg() const { return adr_constants(); } - oop* oop_block_end() const { return adr_exception_table() + 1; } + oop* oop_block_end() const { return adr_stackmap_data() + 1; } private: // @@ -126,11 +141,6 @@ // Raw stackmap data for the method typeArrayOop _stackmap_data; - // The exception handler table. 4-tuples of ints [start_pc, end_pc, - // handler_pc, catch_type index] For methods with no exceptions the - // table is pointing to Universe::the_empty_int_array - typeArrayOop _exception_table; - // // End of the oop block. // @@ -152,7 +162,8 @@ // Inlined tables void set_inlined_tables_length(int checked_exceptions_len, int compressed_line_number_size, - int localvariable_table_len); + int localvariable_table_len, + int exception_table_len); bool has_linenumber_table() const { return (_flags & _has_linenumber_table) != 0; } @@ -163,6 +174,9 @@ bool has_localvariable_table() const { return (_flags & _has_localvariable_table) != 0; } + bool has_exception_handler() const + { return (_flags & _has_exception_table) != 0; } + void set_interpreter_kind(int kind) { _interpreter_kind = kind; } int interpreter_kind(void) const { return _interpreter_kind; } @@ -181,11 +195,6 @@ } bool has_stackmap_table() const { return _stackmap_data != NULL; } - // exception handler table - typeArrayOop exception_table() const { return _exception_table; } - void set_exception_table(typeArrayOop e) { oop_store_without_check((oop*) &_exception_table, (oop) e); } - bool has_exception_handler() const { return exception_table() != NULL && exception_table()->length() > 0; } - void init_fingerprint() { const uint64_t initval = CONST64(0x8000000000000000); _fingerprint = initval; @@ -235,6 +244,7 @@ // Object size needed static int object_size(int code_size, int compressed_line_number_size, int local_variable_table_length, + int exception_table_length, int checked_exceptions_length); int object_size() const { return _constMethod_size; } @@ -256,6 +266,7 @@ u_char* compressed_linenumber_table() const; // not preserved by gc u2* checked_exceptions_length_addr() const; u2* localvariable_table_length_addr() const; + u2* exception_table_length_addr() const; // checked exceptions int checked_exceptions_length() const; @@ -265,6 +276,10 @@ int localvariable_table_length() const; LocalVariableTableElement* localvariable_table_start() const; + // exception table + int exception_table_length() const; + ExceptionTableElement* exception_table_start() const; + // byte codes void set_code(address code) { if (code_size() > 0) { @@ -282,13 +297,10 @@ // interpreter support static ByteSize constants_offset() { return byte_offset_of(constMethodOopDesc, _constants); } - static ByteSize exception_table_offset() - { return byte_offset_of(constMethodOopDesc, _exception_table); } // Garbage collection support oop* adr_constants() const { return (oop*)&_constants; } oop* adr_stackmap_data() const { return (oop*)&_stackmap_data; } - oop* adr_exception_table() const { return (oop*)&_exception_table; } bool is_conc_safe() { return _is_conc_safe; } void set_is_conc_safe(bool v) { _is_conc_safe = v; } diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/oops/generateOopMap.cpp --- a/src/share/vm/oops/generateOopMap.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/oops/generateOopMap.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, 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 @@ -400,10 +400,9 @@ bool fellThrough = false; // False to get first BB marked. // First mark all exception handlers as start of a basic-block - typeArrayOop excps = method()->exception_table(); - for(int i = 0; i < excps->length(); i += 4) { - int handler_pc_idx = i+2; - bb_mark_fct(this, excps->int_at(handler_pc_idx), NULL); + ExceptionTable excps(method()); + for(int i = 0; i < excps.length(); i ++) { + bb_mark_fct(this, excps.handler_pc(i), NULL); } // Then iterate through the code @@ -450,10 +449,9 @@ // Mark entry basic block as alive and all exception handlers _basic_blocks[0].mark_as_alive(); - typeArrayOop excps = method()->exception_table(); - for(int i = 0; i < excps->length(); i += 4) { - int handler_pc_idx = i+2; - BasicBlock *bb = get_basic_block_at(excps->int_at(handler_pc_idx)); + ExceptionTable excps(method()); + for(int i = 0; i < excps.length(); i++) { + BasicBlock *bb = get_basic_block_at(excps.handler_pc(i)); // If block is not already alive (due to multiple exception handlers to same bb), then // make it alive if (bb->is_dead()) bb->mark_as_alive(); @@ -1181,12 +1179,12 @@ if (_has_exceptions) { int bci = itr->bci(); - typeArrayOop exct = method()->exception_table(); - for(int i = 0; i< exct->length(); i+=4) { - int start_pc = exct->int_at(i); - int end_pc = exct->int_at(i+1); - int handler_pc = exct->int_at(i+2); - int catch_type = exct->int_at(i+3); + ExceptionTable exct(method()); + for(int i = 0; i< exct.length(); i++) { + int start_pc = exct.start_pc(i); + int end_pc = exct.end_pc(i); + int handler_pc = exct.handler_pc(i); + int catch_type = exct.catch_type_index(i); if (start_pc <= bci && bci < end_pc) { BasicBlock *excBB = get_basic_block_at(handler_pc); @@ -2055,7 +2053,7 @@ _conflict = false; _max_locals = method()->max_locals(); _max_stack = method()->max_stack(); - _has_exceptions = (method()->exception_table()->length() > 0); + _has_exceptions = (method()->has_exception_handler()); _nof_refval_conflicts = 0; _init_vars = new GrowableArray(5); // There are seldom more than 5 init_vars _report_result = false; @@ -2070,9 +2068,10 @@ if (Verbose) { _method->print_codes(); tty->print_cr("Exception table:"); - typeArrayOop excps = method()->exception_table(); - for(int i = 0; i < excps->length(); i += 4) { - tty->print_cr("[%d - %d] -> %d", excps->int_at(i + 0), excps->int_at(i + 1), excps->int_at(i + 2)); + ExceptionTable excps(method()); + for(int i = 0; i < excps.length(); i ++) { + tty->print_cr("[%d - %d] -> %d", + excps.start_pc(i), excps.end_pc(i), excps.handler_pc(i)); } } } diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/oops/methodOop.cpp --- a/src/share/vm/oops/methodOop.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/oops/methodOop.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -111,25 +111,21 @@ int methodOopDesc::fast_exception_handler_bci_for(KlassHandle ex_klass, int throw_bci, TRAPS) { // exception table holds quadruple entries of the form (beg_bci, end_bci, handler_bci, klass_index) - const int beg_bci_offset = 0; - const int end_bci_offset = 1; - const int handler_bci_offset = 2; - const int klass_index_offset = 3; - const int entry_size = 4; // access exception table - typeArrayHandle table (THREAD, constMethod()->exception_table()); - int length = table->length(); - assert(length % entry_size == 0, "exception table format has changed"); + ExceptionTable table(this); + int length = table.length(); // iterate through all entries sequentially constantPoolHandle pool(THREAD, constants()); - for (int i = 0; i < length; i += entry_size) { - int beg_bci = table->int_at(i + beg_bci_offset); - int end_bci = table->int_at(i + end_bci_offset); + for (int i = 0; i < length; i ++) { + //reacquire the table in case a GC happened + ExceptionTable table(this); + int beg_bci = table.start_pc(i); + int end_bci = table.end_pc(i); assert(beg_bci <= end_bci, "inconsistent exception table"); if (beg_bci <= throw_bci && throw_bci < end_bci) { // exception handler bci range covers throw_bci => investigate further - int handler_bci = table->int_at(i + handler_bci_offset); - int klass_index = table->int_at(i + klass_index_offset); + int handler_bci = table.handler_pc(i); + int klass_index = table.catch_type_index(i); if (klass_index == 0) { return handler_bci; } else if (ex_klass.is_null()) { @@ -980,7 +976,7 @@ { int flags_bits = (JVM_MH_INVOKE_BITS | JVM_ACC_PUBLIC | JVM_ACC_FINAL); methodOop m_oop = oopFactory::new_method(0, accessFlags_from(flags_bits), - 0, 0, 0, IsSafeConc, CHECK_(empty)); + 0, 0, 0, 0, IsSafeConc, CHECK_(empty)); m = methodHandle(THREAD, m_oop); } m->set_constants(cp()); @@ -994,7 +990,6 @@ m->set_result_index(rtf.type()); #endif m->compute_size_of_parameters(THREAD); - m->set_exception_table(Universe::the_empty_int_array()); m->init_intrinsic_id(); assert(m->intrinsic_id() == vmIntrinsics::_invokeExact || m->intrinsic_id() == vmIntrinsics::_invokeGeneric, "must be an invoker"); @@ -1038,6 +1033,7 @@ AccessFlags flags = m->access_flags(); int checked_exceptions_len = m->checked_exceptions_length(); int localvariable_len = m->localvariable_table_length(); + int exception_table_len = m->exception_table_length(); // Allocate newm_oop with the is_conc_safe parameter set // to IsUnsafeConc to indicate that newm_oop is not yet // safe for concurrent processing by a GC. @@ -1045,6 +1041,7 @@ flags, new_compressed_linenumber_size, localvariable_len, + exception_table_len, checked_exceptions_len, IsUnsafeConc, CHECK_(methodHandle())); @@ -1085,6 +1082,7 @@ newm->set_method_size(new_method_size); assert(newm->code_size() == new_code_length, "check"); assert(newm->checked_exceptions_length() == checked_exceptions_len, "check"); + assert(newm->exception_table_length() == exception_table_len, "check"); assert(newm->localvariable_table_length() == localvariable_len, "check"); // Copy new byte codes memcpy(newm->code_base(), new_code, new_code_length); @@ -1100,6 +1098,12 @@ m->checked_exceptions_start(), checked_exceptions_len * sizeof(CheckedExceptionElement)); } + // Copy exception table + if (exception_table_len > 0) { + memcpy(newm->exception_table_start(), + m->exception_table_start(), + exception_table_len * sizeof(ExceptionTableElement)); + } // Copy local variable number table if (localvariable_len > 0) { memcpy(newm->localvariable_table_start(), diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/oops/methodOop.hpp --- a/src/share/vm/oops/methodOop.hpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/oops/methodOop.hpp Mon Jul 23 12:54:20 2012 -0700 @@ -122,8 +122,9 @@ u2 _max_locals; // Number of local variables used by this method u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words u1 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none) - u1 _jfr_towrite : 1, // Flags - : 7; + u1 _jfr_towrite : 1, // Flags + _force_inline : 1, + : 6; u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting u2 _number_of_breakpoints; // fullspeed debugging support InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations @@ -282,12 +283,12 @@ } // exception handler table - typeArrayOop exception_table() const - { return constMethod()->exception_table(); } - void set_exception_table(typeArrayOop e) - { constMethod()->set_exception_table(e); } bool has_exception_handler() const { return constMethod()->has_exception_handler(); } + int exception_table_length() const + { return constMethod()->exception_table_length(); } + ExceptionTableElement* exception_table_start() const + { return constMethod()->exception_table_start(); } // Finds the first entry point bci of an exception handler for an // exception of klass ex_klass thrown at throw_bci. A value of NULL @@ -655,6 +656,9 @@ bool jfr_towrite() { return _jfr_towrite; } void set_jfr_towrite(bool towrite) { _jfr_towrite = towrite; } + bool force_inline() { return _force_inline; } + void set_force_inline(bool fi) { _force_inline = fi; } + // On-stack replacement support bool has_osr_nmethod(int level, bool match_level) { return instanceKlass::cast(method_holder())->lookup_osr_nmethod(this, InvocationEntryBci, level, match_level) != NULL; @@ -835,4 +839,66 @@ void clear(methodOop method); }; +// Utility class for access exception handlers +class ExceptionTable : public StackObj { + private: + ExceptionTableElement* _table; + u2 _length; + + public: + ExceptionTable(methodOop m) { + if (m->has_exception_handler()) { + _table = m->exception_table_start(); + _length = m->exception_table_length(); + } else { + _table = NULL; + _length = 0; + } + } + + int length() const { + return _length; + } + + u2 start_pc(int idx) const { + assert(idx < _length, "out of bounds"); + return _table[idx].start_pc; + } + + void set_start_pc(int idx, u2 value) { + assert(idx < _length, "out of bounds"); + _table[idx].start_pc = value; + } + + u2 end_pc(int idx) const { + assert(idx < _length, "out of bounds"); + return _table[idx].end_pc; + } + + void set_end_pc(int idx, u2 value) { + assert(idx < _length, "out of bounds"); + _table[idx].end_pc = value; + } + + u2 handler_pc(int idx) const { + assert(idx < _length, "out of bounds"); + return _table[idx].handler_pc; + } + + void set_handler_pc(int idx, u2 value) { + assert(idx < _length, "out of bounds"); + _table[idx].handler_pc = value; + } + + u2 catch_type_index(int idx) const { + assert(idx < _length, "out of bounds"); + return _table[idx].catch_type_index; + } + + void set_catch_type_index(int idx, u2 value) { + assert(idx < _length, "out of bounds"); + _table[idx].catch_type_index = value; + } +}; + #endif // SHARE_VM_OOPS_METHODOOP_HPP diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/opto/stringopts.cpp --- a/src/share/vm/opto/stringopts.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/opto/stringopts.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -533,7 +533,17 @@ if (arg->is_Proj() && arg->in(0)->is_CallStaticJava()) { CallStaticJavaNode* csj = arg->in(0)->as_CallStaticJava(); if (csj->method() != NULL && - csj->method()->intrinsic_id() == vmIntrinsics::_Integer_toString) { + csj->method()->intrinsic_id() == vmIntrinsics::_Integer_toString && + arg->outcnt() == 1) { + // _control is the list of StringBuilder calls nodes which + // will be replaced by new String code after this optimization. + // Integer::toString() call is not part of StringBuilder calls + // chain. It could be eliminated only if its result is used + // only by this SB calls chain. + // Another limitation: it should be used only once because + // it is unknown that it is used only by this SB calls chain + // until all related SB calls nodes are collected. + assert(arg->unique_out() == cnode, "sanity"); sc->add_control(csj); sc->push_int(csj->in(TypeFunc::Parms)); continue; diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/prims/jvm.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -35,6 +35,7 @@ #include "oops/fieldStreams.hpp" #include "oops/instanceKlass.hpp" #include "oops/objArrayKlass.hpp" +#include "oops/methodOop.hpp" #include "prims/jvm.h" #include "prims/jvm_misc.hpp" #include "prims/jvmtiExport.hpp" @@ -2183,11 +2184,11 @@ klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); oop method = instanceKlass::cast(k)->methods()->obj_at(method_index); - typeArrayOop extable = methodOop(method)->exception_table(); - entry->start_pc = extable->int_at(entry_index * 4); - entry->end_pc = extable->int_at(entry_index * 4 + 1); - entry->handler_pc = extable->int_at(entry_index * 4 + 2); - entry->catchType = extable->int_at(entry_index * 4 + 3); + ExceptionTable extable((methodOop(method))); + entry->start_pc = extable.start_pc(entry_index); + entry->end_pc = extable.end_pc(entry_index); + entry->handler_pc = extable.handler_pc(entry_index); + entry->catchType = extable.catch_type_index(entry_index); JVM_END @@ -2196,7 +2197,7 @@ klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); oop method = instanceKlass::cast(k)->methods()->obj_at(method_index); - return methodOop(method)->exception_table()->length() / 4; + return methodOop(method)->exception_table_length(); JVM_END diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/prims/jvmtiClassFileReconstituter.cpp --- a/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -191,15 +191,14 @@ } } - typeArrayHandle exception_table(thread(), const_method->exception_table()); - int exception_table_length = exception_table->length(); - int exception_table_entries = exception_table_length / 4; + ExceptionTable exception_table(method()); + int exception_table_length = exception_table.length(); int code_size = const_method->code_size(); int size = 2+2+4 + // max_stack, max_locals, code_length code_size + // code 2 + // exception_table_length - (2+2+2+2) * exception_table_entries + // exception_table + (2+2+2+2) * exception_table_length + // exception_table 2 + // attributes_count attr_size; // attributes @@ -209,12 +208,12 @@ write_u2(method->max_locals()); write_u4(code_size); copy_bytecodes(method, (unsigned char*)writeable_address(code_size)); - write_u2(exception_table_entries); - for (int index = 0; index < exception_table_length; ) { - write_u2(exception_table->int_at(index++)); - write_u2(exception_table->int_at(index++)); - write_u2(exception_table->int_at(index++)); - write_u2(exception_table->int_at(index++)); + write_u2(exception_table_length); + for (int index = 0; index < exception_table_length; index++) { + write_u2(exception_table.start_pc(index)); + write_u2(exception_table.end_pc(index)); + write_u2(exception_table.handler_pc(index)); + write_u2(exception_table.catch_type_index(index)); } write_u2(attr_count); if (line_num_cnt != 0) { diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -2478,23 +2478,17 @@ // to use new constant pool indices as needed. The exception table // holds quadruple entries of the form: // (beg_bci, end_bci, handler_bci, klass_index) - const int beg_bci_offset = 0; - const int end_bci_offset = 1; - const int handler_bci_offset = 2; - const int klass_index_offset = 3; - const int entry_size = 4; - - typeArrayHandle ex_table (THREAD, method->exception_table()); - int ext_length = ex_table->length(); - assert(ext_length % entry_size == 0, "exception table format has changed"); - - for (int j = 0; j < ext_length; j += entry_size) { - int cur_index = ex_table->int_at(j + klass_index_offset); + + ExceptionTable ex_table(method()); + int ext_length = ex_table.length(); + + for (int j = 0; j < ext_length; j ++) { + int cur_index = ex_table.catch_type_index(j); int new_index = find_new_index(cur_index); if (new_index != 0) { RC_TRACE_WITH_THREAD(0x00080000, THREAD, ("ext-klass_index change: %d to %d", cur_index, new_index)); - ex_table->int_at_put(j + klass_index_offset, new_index); + ex_table.set_catch_type_index(j, new_index); } } // end for each exception table entry diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/prims/methodHandleWalk.cpp --- a/src/share/vm/prims/methodHandleWalk.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/prims/methodHandleWalk.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2012, 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 @@ -1796,7 +1796,7 @@ { methodOop m_oop = oopFactory::new_method(bytecode_length(), accessFlags_from(flags_bits), - 0, 0, 0, oopDesc::IsSafeConc, CHECK_(empty)); + 0, 0, 0, 0, oopDesc::IsSafeConc, CHECK_(empty)); m = methodHandle(THREAD, m_oop); } @@ -1812,9 +1812,6 @@ m->set_max_locals(max_locals()); m->set_size_of_parameters(_num_params); - typeArrayHandle exception_handlers(THREAD, Universe::the_empty_int_array()); - m->set_exception_table(exception_handlers()); - // Rewrite the method and set up the constant pool cache. objArrayOop m_array = oopFactory::new_system_objArray(1, CHECK_(empty)); objArrayHandle methods(THREAD, m_array); diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/prims/methodHandles.cpp --- a/src/share/vm/prims/methodHandles.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/prims/methodHandles.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -3180,17 +3180,15 @@ jclass MH_class = env->FindClass(MH_name); status = env->RegisterNatives(MH_class, invoke_methods, sizeof(invoke_methods)/sizeof(JNINativeMethod)); } + if (!env->ExceptionOccurred()) { + status = env->RegisterNatives(MHN_class, call_site_methods, sizeof(call_site_methods)/sizeof(JNINativeMethod)); + } if (env->ExceptionOccurred()) { warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); enable_MH = false; env->ExceptionClear(); } - status = env->RegisterNatives(MHN_class, call_site_methods, sizeof(call_site_methods)/sizeof(JNINativeMethod)); - if (env->ExceptionOccurred()) { - // Exception is okay until 7087357 - env->ExceptionClear(); - } } if (enable_MH) { diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/prims/unsafe.cpp --- a/src/share/vm/prims/unsafe.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/prims/unsafe.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -178,17 +178,6 @@ v = *(oop*)index_oop_from_field_offset_long(p, offset); \ } -#define GET_OOP_FIELD_VOLATILE(obj, offset, v) \ - oop p = JNIHandles::resolve(obj); \ - volatile oop v; \ - if (UseCompressedOops) { \ - volatile narrowOop n = *(volatile narrowOop*)index_oop_from_field_offset_long(p, offset); \ - v = oopDesc::decode_heap_oop(n); \ - } else { \ - v = *(volatile oop*)index_oop_from_field_offset_long(p, offset); \ - } \ - OrderAccess::acquire(); - // Get/SetObject must be special-cased, since it works with handles. @@ -296,28 +285,21 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) UnsafeWrapper("Unsafe_GetObjectVolatile"); - GET_OOP_FIELD_VOLATILE(obj, offset, v) + oop p = JNIHandles::resolve(obj); + void* addr = index_oop_from_field_offset_long(p, offset); + volatile oop v; + if (UseCompressedOops) { + volatile narrowOop n = *(volatile narrowOop*) addr; + v = oopDesc::decode_heap_oop(n); + } else { + v = *(volatile oop*) addr; + } + OrderAccess::acquire(); return JNIHandles::make_local(env, v); UNSAFE_END UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) UnsafeWrapper("Unsafe_SetObjectVolatile"); - { - // Catch VolatileCallSite.target stores (via - // CallSite.setTargetVolatile) and check call site dependencies. - oop p = JNIHandles::resolve(obj); - if ((offset == java_lang_invoke_CallSite::target_offset_in_bytes()) && p->is_a(SystemDictionary::CallSite_klass())) { - Handle call_site (THREAD, p); - Handle method_handle(THREAD, JNIHandles::resolve(x_h)); - assert(call_site ->is_a(SystemDictionary::CallSite_klass()), "must be"); - assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "must be"); - { - // Walk all nmethods depending on this call site. - MutexLocker mu(Compile_lock, thread); - Universe::flush_dependents_on(call_site(), method_handle()); - } - } - } oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); void* addr = index_oop_from_field_offset_long(p, offset); diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/runtime/relocator.cpp --- a/src/share/vm/runtime/relocator.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/runtime/relocator.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, 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 @@ -392,16 +392,16 @@ // The width of instruction at "pc" is changing by "delta". Adjust the // exception table, if any, of "rc->mb". void Relocator::adjust_exception_table(int bci, int delta) { - typeArrayOop table = method()->exception_table(); - for (int index = 0; index < table->length(); index +=4) { - if (table->int_at(index) > bci) { - table->int_at_put(index+0, table->int_at(index+0) + delta); - table->int_at_put(index+1, table->int_at(index+1) + delta); - } else if (bci < table->int_at(index+1)) { - table->int_at_put(index+1, table->int_at(index+1) + delta); + ExceptionTable table(_method()); + for (int index = 0; index < table.length(); index ++) { + if (table.start_pc(index) > bci) { + table.set_start_pc(index, table.start_pc(index) + delta); + table.set_end_pc(index, table.end_pc(index) + delta); + } else if (bci < table.end_pc(index)) { + table.set_end_pc(index, table.end_pc(index) + delta); } - if (table->int_at(index+2) > bci) - table->int_at_put(index+2, table->int_at(index+2) + delta); + if (table.handler_pc(index) > bci) + table.set_handler_pc(index, table.handler_pc(index) + delta); } } diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/runtime/vmStructs.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -388,7 +388,6 @@ volatile_nonstatic_field(constMethodOopDesc, _fingerprint, uint64_t) \ nonstatic_field(constMethodOopDesc, _constants, constantPoolOop) \ nonstatic_field(constMethodOopDesc, _stackmap_data, typeArrayOop) \ - nonstatic_field(constMethodOopDesc, _exception_table, typeArrayOop) \ nonstatic_field(constMethodOopDesc, _constMethod_size, int) \ nonstatic_field(constMethodOopDesc, _interpreter_kind, jbyte) \ nonstatic_field(constMethodOopDesc, _flags, jbyte) \ @@ -425,6 +424,10 @@ nonstatic_field(LocalVariableTableElement, descriptor_cp_index, u2) \ nonstatic_field(LocalVariableTableElement, signature_cp_index, u2) \ nonstatic_field(LocalVariableTableElement, slot, u2) \ + nonstatic_field(ExceptionTableElement, start_pc, u2) \ + nonstatic_field(ExceptionTableElement, end_pc, u2) \ + nonstatic_field(ExceptionTableElement, handler_pc, u2) \ + nonstatic_field(ExceptionTableElement, catch_type_index, u2) \ nonstatic_field(BreakpointInfo, _orig_bytecode, Bytecodes::Code) \ nonstatic_field(BreakpointInfo, _bci, int) \ nonstatic_field(BreakpointInfo, _name_index, u2) \ @@ -1460,6 +1463,7 @@ \ declare_toplevel_type(CheckedExceptionElement) \ declare_toplevel_type(LocalVariableTableElement) \ + declare_toplevel_type(ExceptionTableElement) \ \ /******************************************/ \ /* Generation and space hierarchies */ \ @@ -2301,6 +2305,7 @@ declare_constant(constMethodOopDesc::_has_linenumber_table) \ declare_constant(constMethodOopDesc::_has_checked_exceptions) \ declare_constant(constMethodOopDesc::_has_localvariable_table) \ + declare_constant(constMethodOopDesc::_has_exception_table) \ \ /*************************************/ \ /* instanceKlass enum */ \ diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/services/memRecorder.cpp --- a/src/share/vm/services/memRecorder.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/services/memRecorder.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -45,11 +45,11 @@ } -debug_only(volatile jint MemRecorder::_instance_count = 0;) +volatile jint MemRecorder::_instance_count = 0; MemRecorder::MemRecorder() { assert(MemTracker::is_on(), "Native memory tracking is off"); - debug_only(Atomic::inc(&_instance_count);) + Atomic::inc(&_instance_count); debug_only(set_generation();) if (MemTracker::track_callsite()) { @@ -83,9 +83,7 @@ delete _next; } -#ifdef ASSERT Atomic::dec(&_instance_count); -#endif } // Sorting order: diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/services/memRecorder.hpp --- a/src/share/vm/services/memRecorder.hpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/services/memRecorder.hpp Mon Jul 23 12:54:20 2012 -0700 @@ -249,9 +249,9 @@ SequencedRecordIterator pointer_itr(); - public: + protected: // number of MemRecorder instance - debug_only(static volatile jint _instance_count;) + static volatile jint _instance_count; private: // sorting function, sort records into following order diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/services/memSnapshot.cpp --- a/src/share/vm/services/memSnapshot.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/services/memSnapshot.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -173,7 +173,7 @@ _staging_area = new (std::nothrow)MemPointerArrayImpl(); } - _lock = new (std::nothrow) Mutex(Monitor::native, "memSnapshotLock"); + _lock = new (std::nothrow) Mutex(Monitor::max_nonleaf - 1, "memSnapshotLock"); NOT_PRODUCT(_untracked_count = 0;) } diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/services/memTrackWorker.hpp --- a/src/share/vm/services/memTrackWorker.hpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/services/memTrackWorker.hpp Mon Jul 23 12:54:20 2012 -0700 @@ -67,7 +67,7 @@ NOT_PRODUCT(int _last_gen_in_use;) inline int generations_in_use() const { - return (_tail <= _head ? (_head - _tail + 1) : (MAX_GENERATIONS - (_tail - _head) + 1)); + return (_tail >= _head ? (_tail - _head + 1) : (MAX_GENERATIONS - (_head - _tail) + 1)); } }; diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/services/memTracker.cpp --- a/src/share/vm/services/memTracker.cpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/services/memTracker.cpp Mon Jul 23 12:54:20 2012 -0700 @@ -54,7 +54,7 @@ MemRecorder* MemTracker::_global_recorder = NULL; MemSnapshot* MemTracker::_snapshot = NULL; MemBaseline MemTracker::_baseline; -Mutex MemTracker::_query_lock(Monitor::native, "NMT_queryLock"); +Mutex* MemTracker::_query_lock = NULL; volatile MemRecorder* MemTracker::_merge_pending_queue = NULL; volatile MemRecorder* MemTracker::_pooled_recorders = NULL; MemTrackWorker* MemTracker::_worker_thread = NULL; @@ -89,6 +89,12 @@ return; } + _query_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf, "NMT_queryLock"); + if (_query_lock == NULL) { + shutdown(NMT_out_of_memory); + return; + } + debug_only(_main_thread_tid = os::current_thread_id();) _state = NMT_bootstrapping_single_thread; NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack()); @@ -164,7 +170,7 @@ { // shared baseline and snapshot are the only objects needed to // create query results - MutexLockerEx locker(&_query_lock, true); + MutexLockerEx locker(_query_lock, true); // cleanup baseline data and snapshot _baseline.clear(); delete _snapshot; @@ -351,21 +357,17 @@ } if (thread != NULL) { -#ifdef ASSERT - // cause assertion on stack base. This ensures that threads call - // Thread::record_stack_base_and_size() method, which will create - // thread native stack records. - thread->stack_base(); -#endif - // for a JavaThread, if it is running in native state, we need to transition it to - // VM state, so it can stop at safepoint. JavaThread running in VM state does not - // need lock to write records. if (thread->is_Java_thread() && ((JavaThread*)thread)->is_safepoint_visible()) { - if (((JavaThread*)thread)->thread_state() == _thread_in_native) { - ThreadInVMfromNative trans((JavaThread*)thread); - create_record_in_recorder(addr, flags, size, pc, thread); + JavaThread* java_thread = static_cast(thread); + JavaThreadState state = java_thread->thread_state(); + if (SafepointSynchronize::safepoint_safe(java_thread, state)) { + // JavaThreads that are safepoint safe, can run through safepoint, + // so ThreadCritical is needed to ensure no threads at safepoint create + // new records while the records are being gathered and the sequence number is changing + ThreadCritical tc; + create_record_in_recorder(addr, flags, size, pc, java_thread); } else { - create_record_in_recorder(addr, flags, size, pc, thread); + create_record_in_recorder(addr, flags, size, pc, java_thread); } } else { // other threads, such as worker and watcher threads, etc. need to @@ -390,10 +392,9 @@ // write a record to proper recorder. No lock can be taken from this method // down. void MemTracker::create_record_in_recorder(address addr, MEMFLAGS flags, - size_t size, address pc, Thread* thread) { - assert(thread == NULL || thread->is_Java_thread(), "wrong thread"); + size_t size, address pc, JavaThread* thread) { - MemRecorder* rc = get_thread_recorder((JavaThread*)thread); + MemRecorder* rc = get_thread_recorder(thread); if (rc != NULL) { rc->record(addr, flags, size, pc); } @@ -460,17 +461,18 @@ } } _sync_point_skip_count = 0; - // walk all JavaThreads to collect recorders - SyncThreadRecorderClosure stc; - Threads::threads_do(&stc); - - _thread_count = stc.get_thread_count(); - MemRecorder* pending_recorders = get_pending_recorders(); - { // This method is running at safepoint, with ThreadCritical lock, // it should guarantee that NMT is fully sync-ed. ThreadCritical tc; + + // walk all JavaThreads to collect recorders + SyncThreadRecorderClosure stc; + Threads::threads_do(&stc); + + _thread_count = stc.get_thread_count(); + MemRecorder* pending_recorders = get_pending_recorders(); + if (_global_recorder != NULL) { _global_recorder->set_next(pending_recorders); pending_recorders = _global_recorder; @@ -486,8 +488,6 @@ // now, it is the time to shut whole things off if (_state == NMT_final_shutdown) { - _tracking_level = NMT_off; - // walk all JavaThreads to delete all recorders SyncThreadRecorderClosure stc; Threads::threads_do(&stc); @@ -499,8 +499,16 @@ _global_recorder = NULL; } } - - _state = NMT_shutdown; + MemRecorder* pending_recorders = get_pending_recorders(); + if (pending_recorders != NULL) { + delete pending_recorders; + } + // try at a later sync point to ensure MemRecorder instance drops to zero to + // completely shutdown NMT + if (MemRecorder::_instance_count == 0) { + _state = NMT_shutdown; + _tracking_level = NMT_off; + } } } @@ -534,7 +542,7 @@ // baseline current memory snapshot bool MemTracker::baseline() { - MutexLockerEx lock(&_query_lock, true); + MutexLockerEx lock(_query_lock, true); MemSnapshot* snapshot = get_snapshot(); if (snapshot != NULL) { return _baseline.baseline(*snapshot, false); @@ -545,7 +553,7 @@ // print memory usage from current snapshot bool MemTracker::print_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { MemBaseline baseline; - MutexLockerEx lock(&_query_lock, true); + MutexLockerEx lock(_query_lock, true); MemSnapshot* snapshot = get_snapshot(); if (snapshot != NULL && baseline.baseline(*snapshot, summary_only)) { BaselineReporter reporter(out, unit); @@ -557,7 +565,7 @@ // compare memory usage between current snapshot and baseline bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { - MutexLockerEx lock(&_query_lock, true); + MutexLockerEx lock(_query_lock, true); if (_baseline.baselined()) { MemBaseline baseline; MemSnapshot* snapshot = get_snapshot(); diff -r e3619706a725 -r bd54fe36b5e5 src/share/vm/services/memTracker.hpp --- a/src/share/vm/services/memTracker.hpp Mon Jul 23 12:38:08 2012 -0700 +++ b/src/share/vm/services/memTracker.hpp Mon Jul 23 12:54:20 2012 -0700 @@ -126,6 +126,8 @@ return "Native memory tracking has been shutdown by user"; case NMT_normal: return "Native memory tracking has been shutdown due to process exiting"; + case NMT_out_of_memory: + return "Native memory tracking has been shutdown due to out of native memory"; case NMT_initialization: return "Native memory tracking failed to initialize"; case NMT_error_reporting: @@ -326,7 +328,7 @@ static void create_memory_record(address addr, MEMFLAGS type, size_t size, address pc, Thread* thread); static void create_record_in_recorder(address addr, MEMFLAGS type, - size_t size, address pc, Thread* thread); + size_t size, address pc, JavaThread* thread); private: // global memory snapshot @@ -336,7 +338,7 @@ static MemBaseline _baseline; // query lock - static Mutex _query_lock; + static Mutex* _query_lock; // a thread can start to allocate memory before it is attached // to VM 'Thread', those memory activities are recorded here. diff -r e3619706a725 -r bd54fe36b5e5 test/runtime/6294277/SourceDebugExtension.java --- a/test/runtime/6294277/SourceDebugExtension.java Mon Jul 23 12:38:08 2012 -0700 +++ b/test/runtime/6294277/SourceDebugExtension.java Mon Jul 23 12:54:20 2012 -0700 @@ -25,6 +25,7 @@ * @test * @bug 6294277 * @summary java -Xdebug crashes on SourceDebugExtension attribute larger than 64K + * @run main/othervm -Xdebug -Xrunjdwp:transport=dt_socket,address=8888,server=y,suspend=n SourceDebugExtension */ import java.io.*; diff -r e3619706a725 -r bd54fe36b5e5 test/runtime/6294277/Test6294277.sh --- a/test/runtime/6294277/Test6294277.sh Mon Jul 23 12:38:08 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -# -# Copyright (c) 2012, 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 Test6294277.sh -# @bug 6294277 -# @summary java -Xdebug crashes on SourceDebugExtension attribute larger than 64K -# @run shell Test6294277.sh -# - - -if [ "${TESTSRC}" = "" ] -then TESTSRC=. -fi - -if [ "${TESTJAVA}" = "" ] -then - PARENT=`dirname \`which java\`` - TESTJAVA=`dirname ${PARENT}` - echo "TESTJAVA not set, selecting " ${TESTJAVA} - echo "If this is incorrect, try setting the variable manually." -fi - -BIT_FLAG="" - -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - SunOS | Linux ) - NULL=/dev/null - PS=":" - FS="/" - ## for solaris, linux it's HOME - FILE_LOCATION=$HOME - if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" -a `uname -p`='sparc' ] - then - BIT_FLAG="-d64" - fi - ;; - Windows_* | Darwin ) - NULL=NUL - PS=";" - FS="\\" - echo "Test skipped" - exit 0 - ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; -esac - -cp ${TESTSRC}${FS}*.java . - -${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -fullversion - -${TESTJAVA}${FS}bin${FS}javac *.java - -${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -classpath . -Xdebug -Xrunjdwp:transport=dt_socket,address=8888,server=y,suspend=n SourceDebugExtension > test.out 2>&1 & - -P_PID=$! - -sleep 60 -STATUS=1 - -grep "Test PASSES" test.out > ${NULL} -if [ $? = 0 ]; then - cat test.out - STATUS=0 -fi - -exit $STATUS diff -r e3619706a725 -r bd54fe36b5e5 test/runtime/7020373/Test7020373.sh --- a/test/runtime/7020373/Test7020373.sh Mon Jul 23 12:38:08 2012 -0700 +++ b/test/runtime/7020373/Test7020373.sh Mon Jul 23 12:54:20 2012 -0700 @@ -2,10 +2,9 @@ ## ## @test -## @bug 7020373 7055247 +## @bug 7020373 7055247 7053586 ## @key cte_test ## @summary JSR rewriting can overflow memory address size variables -## @ignore Ignore it until 7053586 fixed ## @run shell Test7020373.sh ## @@ -30,7 +29,7 @@ # set platform-dependent variables OS=`uname -s` case "$OS" in - SunOS | Linux ) + SunOS | Linux | Darwin ) NULL=/dev/null PS=":" FS="/" @@ -66,7 +65,7 @@ echo "Test Failed" exit 1 else - grep "java.lang.LinkageError" test.out + egrep "java.lang.LinkageError|java.lang.NoSuchMethodError|Main method not found in class OOMCrashClass4000_1|insufficient memory" test.out if [ $? = 0 ] then echo "Test Passed"