Fri, 09 Sep 2011 16:17:16 -0700
Merge
.hgtags | file | annotate | diff | comparison | revisions | |
agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64Frame.java | file | annotate | diff | comparison | revisions | |
agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64RegisterMap.java | file | annotate | diff | comparison | revisions | |
make/solaris/makefiles/mapfile-vers-nonproduct | file | annotate | diff | comparison | revisions | |
src/share/vm/runtime/reflectionCompat.hpp | file | annotate | diff | comparison | revisions |
1.1 --- a/.hgtags Thu Sep 08 16:59:27 2011 -0700 1.2 +++ b/.hgtags Fri Sep 09 16:17:16 2011 -0700 1.3 @@ -178,3 +178,7 @@ 1.4 31e253c1da429124bb87570ab095d9bc89850d0a jdk8-b02 1.5 3a2fb61165dfc72e398179a2796d740c8da5b8c0 jdk8-b03 1.6 0fa3ace511fe98fe948e751531f3e2b7c60c8376 jdk8-b04 1.7 +0cc8a70952c368e06de2adab1f2649a408f5e577 hs22-b01 1.8 +7c29742c41b44fb0cd5a13c7ac8834f3f2ca649e hs22-b02 1.9 +3a2fb61165dfc72e398179a2796d740c8da5b8c0 hs22-b03 1.10 +ce9bde819dcba4a5d2822229d9183e69c74326ca hs22-b04
2.1 --- a/agent/src/share/classes/sun/jvm/hotspot/HSDB.java Thu Sep 08 16:59:27 2011 -0700 2.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/HSDB.java Fri Sep 09 16:17:16 2011 -0700 2.3 @@ -1740,7 +1740,7 @@ 2.4 else if (f.isCompiledFrame()) { tty.print("compiled"); } 2.5 else if (f.isEntryFrame()) { tty.print("entry"); } 2.6 else if (f.isNativeFrame()) { tty.print("native"); } 2.7 - else if (f.isGlueFrame()) { tty.print("glue"); } 2.8 + else if (f.isRuntimeFrame()) { tty.print("runtime"); } 2.9 else { tty.print("external"); } 2.10 tty.print(" frame with PC = " + f.getPC() + ", SP = " + f.getSP() + ", FP = " + f.getFP()); 2.11 if (f.isSignalHandlerFrameDbg()) {
3.1 --- a/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java Thu Sep 08 16:59:27 2011 -0700 3.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java Fri Sep 09 16:17:16 2011 -0700 3.3 @@ -102,6 +102,11 @@ 3.4 /** On-Stack Replacement method */ 3.5 public boolean isOSRMethod() { return false; } 3.6 3.7 + public NMethod asNMethodOrNull() { 3.8 + if (isNMethod()) return (NMethod)this; 3.9 + return null; 3.10 + } 3.11 + 3.12 // Boundaries 3.13 public Address headerBegin() { 3.14 return addr; 3.15 @@ -195,7 +200,7 @@ 3.16 } 3.17 3.18 // Returns true, if the next frame is responsible for GC'ing oops passed as arguments 3.19 - public boolean callerMustGCArguments(JavaThread thread) { return false; } 3.20 + public boolean callerMustGCArguments() { return false; } 3.21 3.22 public String getName() { 3.23 return CStringUtilities.getString(nameField.getValue(addr));
4.1 --- a/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java Thu Sep 08 16:59:27 2011 -0700 4.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java Fri Sep 09 16:17:16 2011 -0700 4.3 @@ -59,6 +59,7 @@ 4.4 virtualConstructor.addMapping("RuntimeStub", RuntimeStub.class); 4.5 virtualConstructor.addMapping("RicochetBlob", RicochetBlob.class); 4.6 virtualConstructor.addMapping("AdapterBlob", AdapterBlob.class); 4.7 + virtualConstructor.addMapping("MethodHandlesAdapterBlob", MethodHandlesAdapterBlob.class); 4.8 virtualConstructor.addMapping("SafepointBlob", SafepointBlob.class); 4.9 virtualConstructor.addMapping("DeoptimizationBlob", DeoptimizationBlob.class); 4.10 if (VM.getVM().isServerCompiler()) { 4.11 @@ -126,6 +127,10 @@ 4.12 Assert.that(result.blobContains(start) || result.blobContains(start.addOffsetTo(8)), 4.13 "found wrong CodeBlob"); 4.14 } 4.15 + if (result.isRicochetBlob()) { 4.16 + // This should probably be done for other SingletonBlobs 4.17 + return VM.getVM().ricochetBlob(); 4.18 + } 4.19 return result; 4.20 } 4.21
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/MethodHandlesAdapterBlob.java Fri Sep 09 16:17:16 2011 -0700 5.3 @@ -0,0 +1,58 @@ 5.4 +/* 5.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.23 + * or visit www.oracle.com if you need additional information or have any 5.24 + * questions. 5.25 + * 5.26 + */ 5.27 + 5.28 +package sun.jvm.hotspot.code; 5.29 + 5.30 +import java.util.*; 5.31 +import sun.jvm.hotspot.debugger.*; 5.32 +import sun.jvm.hotspot.runtime.*; 5.33 +import sun.jvm.hotspot.types.*; 5.34 + 5.35 +public class MethodHandlesAdapterBlob extends AdapterBlob { 5.36 + static { 5.37 + VM.registerVMInitializedObserver(new Observer() { 5.38 + public void update(Observable o, Object data) { 5.39 + initialize(VM.getVM().getTypeDataBase()); 5.40 + } 5.41 + }); 5.42 + } 5.43 + 5.44 + private static void initialize(TypeDataBase db) { 5.45 + Type type = db.lookupType("MethodHandlesAdapterBlob"); 5.46 + 5.47 + // FIXME: add any needed fields 5.48 + } 5.49 + 5.50 + public MethodHandlesAdapterBlob(Address addr) { 5.51 + super(addr); 5.52 + } 5.53 + 5.54 + public boolean isMethodHandlesAdapterBlob() { 5.55 + return true; 5.56 + } 5.57 + 5.58 + public String getName() { 5.59 + return "MethodHandlesAdapterBlob: " + super.getName(); 5.60 + } 5.61 +}
6.1 --- a/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Thu Sep 08 16:59:27 2011 -0700 6.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Fri Sep 09 16:17:16 2011 -0700 6.3 @@ -46,6 +46,7 @@ 6.4 /** Offsets for different nmethod parts */ 6.5 private static CIntegerField exceptionOffsetField; 6.6 private static CIntegerField deoptOffsetField; 6.7 + private static CIntegerField deoptMhOffsetField; 6.8 private static CIntegerField origPCOffsetField; 6.9 private static CIntegerField stubOffsetField; 6.10 private static CIntegerField oopsOffsetField; 6.11 @@ -95,6 +96,7 @@ 6.12 6.13 exceptionOffsetField = type.getCIntegerField("_exception_offset"); 6.14 deoptOffsetField = type.getCIntegerField("_deoptimize_offset"); 6.15 + deoptMhOffsetField = type.getCIntegerField("_deoptimize_mh_offset"); 6.16 origPCOffsetField = type.getCIntegerField("_orig_pc_offset"); 6.17 stubOffsetField = type.getCIntegerField("_stub_offset"); 6.18 oopsOffsetField = type.getCIntegerField("_oops_offset"); 6.19 @@ -136,10 +138,11 @@ 6.20 /** Boundaries for different parts */ 6.21 public Address constantsBegin() { return contentBegin(); } 6.22 public Address constantsEnd() { return getEntryPoint(); } 6.23 - public Address instsBegin() { return codeBegin(); } 6.24 + public Address instsBegin() { return codeBegin(); } 6.25 public Address instsEnd() { return headerBegin().addOffsetTo(getStubOffset()); } 6.26 public Address exceptionBegin() { return headerBegin().addOffsetTo(getExceptionOffset()); } 6.27 - public Address deoptBegin() { return headerBegin().addOffsetTo(getDeoptOffset()); } 6.28 + public Address deoptHandlerBegin() { return headerBegin().addOffsetTo(getDeoptOffset()); } 6.29 + public Address deoptMhHandlerBegin() { return headerBegin().addOffsetTo(getDeoptMhOffset()); } 6.30 public Address stubBegin() { return headerBegin().addOffsetTo(getStubOffset()); } 6.31 public Address stubEnd() { return headerBegin().addOffsetTo(getOopsOffset()); } 6.32 public Address oopsBegin() { return headerBegin().addOffsetTo(getOopsOffset()); } 6.33 @@ -250,6 +253,22 @@ 6.34 return (int) scavengeRootStateField.getValue(addr); 6.35 } 6.36 6.37 + // MethodHandle 6.38 + public boolean isMethodHandleReturn(Address returnPc) { 6.39 + // Hard to read a bit fields from Java and it's only there for performance 6.40 + // so just go directly to the PCDesc 6.41 + // if (!hasMethodHandleInvokes()) return false; 6.42 + PCDesc pd = getPCDescAt(returnPc); 6.43 + if (pd == null) 6.44 + return false; 6.45 + return pd.isMethodHandleInvoke(); 6.46 + } 6.47 + 6.48 + // Deopt 6.49 + // Return true is the PC is one would expect if the frame is being deopted. 6.50 + public boolean isDeoptPc (Address pc) { return isDeoptEntry(pc) || isDeoptMhEntry(pc); } 6.51 + public boolean isDeoptEntry (Address pc) { return pc == deoptHandlerBegin(); } 6.52 + public boolean isDeoptMhEntry (Address pc) { return pc == deoptMhHandlerBegin(); } 6.53 6.54 /** Tells whether frames described by this nmethod can be 6.55 deoptimized. Note: native wrappers cannot be deoptimized. */ 6.56 @@ -388,6 +407,7 @@ 6.57 private int getEntryBCI() { return (int) entryBCIField .getValue(addr); } 6.58 private int getExceptionOffset() { return (int) exceptionOffsetField .getValue(addr); } 6.59 private int getDeoptOffset() { return (int) deoptOffsetField .getValue(addr); } 6.60 + private int getDeoptMhOffset() { return (int) deoptMhOffsetField .getValue(addr); } 6.61 private int getStubOffset() { return (int) stubOffsetField .getValue(addr); } 6.62 private int getOopsOffset() { return (int) oopsOffsetField .getValue(addr); } 6.63 private int getScopesDataOffset() { return (int) scopesDataOffsetField .getValue(addr); }
7.1 --- a/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java Thu Sep 08 16:59:27 2011 -0700 7.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java Fri Sep 09 16:17:16 2011 -0700 7.3 @@ -38,6 +38,9 @@ 7.4 private static CIntegerField scopeDecodeOffsetField; 7.5 private static CIntegerField objDecodeOffsetField; 7.6 private static CIntegerField pcFlagsField; 7.7 + private static int reexecuteMask; 7.8 + private static int isMethodHandleInvokeMask; 7.9 + private static int returnOopMask; 7.10 7.11 static { 7.12 VM.registerVMInitializedObserver(new Observer() { 7.13 @@ -54,6 +57,10 @@ 7.14 scopeDecodeOffsetField = type.getCIntegerField("_scope_decode_offset"); 7.15 objDecodeOffsetField = type.getCIntegerField("_obj_decode_offset"); 7.16 pcFlagsField = type.getCIntegerField("_flags"); 7.17 + 7.18 + reexecuteMask = db.lookupIntConstant("PcDesc::PCDESC_reexecute"); 7.19 + isMethodHandleInvokeMask = db.lookupIntConstant("PcDesc::PCDESC_is_method_handle_invoke"); 7.20 + returnOopMask = db.lookupIntConstant("PcDesc::PCDESC_return_oop"); 7.21 } 7.22 7.23 public PCDesc(Address addr) { 7.24 @@ -81,7 +88,12 @@ 7.25 7.26 public boolean getReexecute() { 7.27 int flags = (int)pcFlagsField.getValue(addr); 7.28 - return ((flags & 0x1)== 1); //first is the reexecute bit 7.29 + return (flags & reexecuteMask) != 0; 7.30 + } 7.31 + 7.32 + public boolean isMethodHandleInvoke() { 7.33 + int flags = (int)pcFlagsField.getValue(addr); 7.34 + return (flags & isMethodHandleInvokeMask) != 0; 7.35 } 7.36 7.37 public void print(NMethod code) {
8.1 --- a/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java Thu Sep 08 16:59:27 2011 -0700 8.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/RicochetBlob.java Fri Sep 09 16:17:16 2011 -0700 8.3 @@ -41,11 +41,15 @@ 8.4 } 8.5 8.6 private static void initialize(TypeDataBase db) { 8.7 - // Type type = db.lookupType("RicochetBlob"); 8.8 + Type type = db.lookupType("RicochetBlob"); 8.9 8.10 - // FIXME: add any needed fields 8.11 + bounceOffsetField = type.getCIntegerField("_bounce_offset"); 8.12 + exceptionOffsetField = type.getCIntegerField("_exception_offset"); 8.13 } 8.14 8.15 + private static CIntegerField bounceOffsetField; 8.16 + private static CIntegerField exceptionOffsetField; 8.17 + 8.18 public RicochetBlob(Address addr) { 8.19 super(addr); 8.20 } 8.21 @@ -53,4 +57,14 @@ 8.22 public boolean isRicochetBlob() { 8.23 return true; 8.24 } 8.25 + 8.26 + public Address bounceAddr() { 8.27 + return codeBegin().addOffsetTo(bounceOffsetField.getValue(addr)); 8.28 + } 8.29 + 8.30 + public boolean returnsToBounceAddr(Address pc) { 8.31 + Address bouncePc = bounceAddr(); 8.32 + return (pc.equals(bouncePc) || pc.addOffsetTo(Frame.pcReturnOffset()).equals(bouncePc)); 8.33 + } 8.34 + 8.35 }
9.1 --- a/agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java Thu Sep 08 16:59:27 2011 -0700 9.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/RuntimeStub.java Fri Sep 09 16:17:16 2011 -0700 9.3 @@ -30,6 +30,8 @@ 9.4 import sun.jvm.hotspot.types.*; 9.5 9.6 public class RuntimeStub extends CodeBlob { 9.7 + private static CIntegerField callerMustGCArgumentsField; 9.8 + 9.9 static { 9.10 VM.registerVMInitializedObserver(new Observer() { 9.11 public void update(Observable o, Object data) { 9.12 @@ -40,6 +42,7 @@ 9.13 9.14 private static void initialize(TypeDataBase db) { 9.15 Type type = db.lookupType("RuntimeStub"); 9.16 + callerMustGCArgumentsField = type.getCIntegerField("_caller_must_gc_arguments"); 9.17 9.18 // FIXME: add any needed fields 9.19 } 9.20 @@ -52,6 +55,11 @@ 9.21 return true; 9.22 } 9.23 9.24 + public boolean callerMustGCArguments() { 9.25 + return callerMustGCArgumentsField.getValue(addr) != 0; 9.26 + } 9.27 + 9.28 + 9.29 public String getName() { 9.30 return "RuntimeStub: " + super.getName(); 9.31 }
10.1 --- a/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java Thu Sep 08 16:59:27 2011 -0700 10.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java Fri Sep 09 16:17:16 2011 -0700 10.3 @@ -246,7 +246,7 @@ 10.4 } 10.5 10.6 // Check if caller must update oop argument 10.7 - regMap.setIncludeArgumentOops(cb.callerMustGCArguments(regMap.getThread())); 10.8 + regMap.setIncludeArgumentOops(cb.callerMustGCArguments()); 10.9 10.10 int nofCallee = 0; 10.11 Address[] locs = new Address[2 * REG_COUNT + 1];
11.1 --- a/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java Thu Sep 08 16:59:27 2011 -0700 11.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java Fri Sep 09 16:17:16 2011 -0700 11.3 @@ -90,7 +90,7 @@ 11.4 jcode == Bytecodes._ldc2_w; 11.5 if (! codeOk) return false; 11.6 11.7 - ConstantTag ctag = method().getConstants().getTagAt(rawIndex()); 11.8 + ConstantTag ctag = method().getConstants().getTagAt(poolIndex()); 11.9 if (jcode == Bytecodes._ldc2_w) { 11.10 // has to be double or long 11.11 return (ctag.isDouble() || ctag.isLong()) ? true: false;
12.1 --- a/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java Thu Sep 08 16:59:27 2011 -0700 12.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java Fri Sep 09 16:17:16 2011 -0700 12.3 @@ -28,11 +28,13 @@ 12.4 12.5 import com.sun.jdi.*; 12.6 12.7 +import sun.jvm.hotspot.memory.SystemDictionary; 12.8 import sun.jvm.hotspot.oops.Instance; 12.9 import sun.jvm.hotspot.oops.InstanceKlass; 12.10 import sun.jvm.hotspot.oops.ArrayKlass; 12.11 import sun.jvm.hotspot.oops.JVMDIClassStatus; 12.12 import sun.jvm.hotspot.oops.Klass; 12.13 +import sun.jvm.hotspot.oops.ObjArray; 12.14 import sun.jvm.hotspot.oops.Oop; 12.15 import sun.jvm.hotspot.oops.Symbol; 12.16 import sun.jvm.hotspot.oops.DefaultHeapVisitor; 12.17 @@ -53,6 +55,7 @@ 12.18 private SoftReference methodsCache; 12.19 private SoftReference allMethodsCache; 12.20 private SoftReference nestedTypesCache; 12.21 + private SoftReference methodInvokesCache; 12.22 12.23 /* to mark when no info available */ 12.24 static final SDE NO_SDE_INFO_MARK = new SDE(); 12.25 @@ -82,6 +85,27 @@ 12.26 return method; 12.27 } 12.28 } 12.29 + if (ref.getMethodHolder().equals(SystemDictionary.getMethodHandleKlass())) { 12.30 + // invoke methods are generated as needed, so make mirrors as needed 12.31 + List mis = null; 12.32 + if (methodInvokesCache == null) { 12.33 + mis = new ArrayList(); 12.34 + methodInvokesCache = new SoftReference(mis); 12.35 + } else { 12.36 + mis = (List)methodInvokesCache.get(); 12.37 + } 12.38 + it = mis.iterator(); 12.39 + while (it.hasNext()) { 12.40 + MethodImpl method = (MethodImpl)it.next(); 12.41 + if (ref.equals(method.ref())) { 12.42 + return method; 12.43 + } 12.44 + } 12.45 + 12.46 + MethodImpl method = MethodImpl.createMethodImpl(vm, this, ref); 12.47 + mis.add(method); 12.48 + return method; 12.49 + } 12.50 throw new IllegalArgumentException("Invalid method id: " + ref); 12.51 } 12.52
13.1 --- a/agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java Thu Sep 08 16:59:27 2011 -0700 13.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/jdi/StackFrameImpl.java Fri Sep 09 16:17:16 2011 -0700 13.3 @@ -123,6 +123,9 @@ 13.4 Assert.that(values.size() > 0, "this is missing"); 13.5 } 13.6 // 'this' at index 0. 13.7 + if (values.get(0).getType() == BasicType.getTConflict()) { 13.8 + return null; 13.9 + } 13.10 OopHandle handle = values.oopHandleAt(0); 13.11 ObjectHeap heap = vm.saObjectHeap(); 13.12 thisObject = vm.objectMirror(heap.newOop(handle)); 13.13 @@ -210,6 +213,8 @@ 13.14 validateStackFrame(); 13.15 StackValueCollection values = saFrame.getLocals(); 13.16 MethodImpl mmm = (MethodImpl)location.method(); 13.17 + if (mmm.isNative()) 13.18 + return null; 13.19 List argSigs = mmm.argumentSignatures(); 13.20 int count = argSigs.size(); 13.21 List res = new ArrayList(0); 13.22 @@ -231,34 +236,67 @@ 13.23 ValueImpl valueImpl = null; 13.24 OopHandle handle = null; 13.25 ObjectHeap heap = vm.saObjectHeap(); 13.26 - if (variableType == BasicType.T_BOOLEAN) { 13.27 + if (values.get(ss).getType() == BasicType.getTConflict()) { 13.28 + // Dead locals, so just represent them as a zero of the appropriate type 13.29 + if (variableType == BasicType.T_BOOLEAN) { 13.30 + valueImpl = (BooleanValueImpl) vm.mirrorOf(false); 13.31 + } else if (variableType == BasicType.T_CHAR) { 13.32 + valueImpl = (CharValueImpl) vm.mirrorOf((char)0); 13.33 + } else if (variableType == BasicType.T_FLOAT) { 13.34 + valueImpl = (FloatValueImpl) vm.mirrorOf((float)0); 13.35 + } else if (variableType == BasicType.T_DOUBLE) { 13.36 + valueImpl = (DoubleValueImpl) vm.mirrorOf((double)0); 13.37 + } else if (variableType == BasicType.T_BYTE) { 13.38 + valueImpl = (ByteValueImpl) vm.mirrorOf((byte)0); 13.39 + } else if (variableType == BasicType.T_SHORT) { 13.40 + valueImpl = (ShortValueImpl) vm.mirrorOf((short)0); 13.41 + } else if (variableType == BasicType.T_INT) { 13.42 + valueImpl = (IntegerValueImpl) vm.mirrorOf((int)0); 13.43 + } else if (variableType == BasicType.T_LONG) { 13.44 + valueImpl = (LongValueImpl) vm.mirrorOf((long)0); 13.45 + } else if (variableType == BasicType.T_OBJECT) { 13.46 + // we may have an [Ljava/lang/Object; - i.e., Object[] with the 13.47 + // elements themselves may be arrays because every array is an Object. 13.48 + handle = null; 13.49 + valueImpl = (ObjectReferenceImpl) vm.objectMirror(heap.newOop(handle)); 13.50 + } else if (variableType == BasicType.T_ARRAY) { 13.51 + handle = null; 13.52 + valueImpl = vm.arrayMirror((Array)heap.newOop(handle)); 13.53 + } else if (variableType == BasicType.T_VOID) { 13.54 + valueImpl = new VoidValueImpl(vm); 13.55 + } else { 13.56 + throw new RuntimeException("Should not read here"); 13.57 + } 13.58 + } else { 13.59 + if (variableType == BasicType.T_BOOLEAN) { 13.60 valueImpl = (BooleanValueImpl) vm.mirrorOf(values.booleanAt(ss)); 13.61 - } else if (variableType == BasicType.T_CHAR) { 13.62 + } else if (variableType == BasicType.T_CHAR) { 13.63 valueImpl = (CharValueImpl) vm.mirrorOf(values.charAt(ss)); 13.64 - } else if (variableType == BasicType.T_FLOAT) { 13.65 + } else if (variableType == BasicType.T_FLOAT) { 13.66 valueImpl = (FloatValueImpl) vm.mirrorOf(values.floatAt(ss)); 13.67 - } else if (variableType == BasicType.T_DOUBLE) { 13.68 + } else if (variableType == BasicType.T_DOUBLE) { 13.69 valueImpl = (DoubleValueImpl) vm.mirrorOf(values.doubleAt(ss)); 13.70 - } else if (variableType == BasicType.T_BYTE) { 13.71 + } else if (variableType == BasicType.T_BYTE) { 13.72 valueImpl = (ByteValueImpl) vm.mirrorOf(values.byteAt(ss)); 13.73 - } else if (variableType == BasicType.T_SHORT) { 13.74 + } else if (variableType == BasicType.T_SHORT) { 13.75 valueImpl = (ShortValueImpl) vm.mirrorOf(values.shortAt(ss)); 13.76 - } else if (variableType == BasicType.T_INT) { 13.77 + } else if (variableType == BasicType.T_INT) { 13.78 valueImpl = (IntegerValueImpl) vm.mirrorOf(values.intAt(ss)); 13.79 - } else if (variableType == BasicType.T_LONG) { 13.80 + } else if (variableType == BasicType.T_LONG) { 13.81 valueImpl = (LongValueImpl) vm.mirrorOf(values.longAt(ss)); 13.82 - } else if (variableType == BasicType.T_OBJECT) { 13.83 + } else if (variableType == BasicType.T_OBJECT) { 13.84 // we may have an [Ljava/lang/Object; - i.e., Object[] with the 13.85 // elements themselves may be arrays because every array is an Object. 13.86 handle = values.oopHandleAt(ss); 13.87 valueImpl = (ObjectReferenceImpl) vm.objectMirror(heap.newOop(handle)); 13.88 - } else if (variableType == BasicType.T_ARRAY) { 13.89 + } else if (variableType == BasicType.T_ARRAY) { 13.90 handle = values.oopHandleAt(ss); 13.91 valueImpl = vm.arrayMirror((Array)heap.newOop(handle)); 13.92 - } else if (variableType == BasicType.T_VOID) { 13.93 + } else if (variableType == BasicType.T_VOID) { 13.94 valueImpl = new VoidValueImpl(vm); 13.95 - } else { 13.96 + } else { 13.97 throw new RuntimeException("Should not read here"); 13.98 + } 13.99 } 13.100 13.101 return valueImpl;
14.1 --- a/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java Thu Sep 08 16:59:27 2011 -0700 14.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java Fri Sep 09 16:17:16 2011 -0700 14.3 @@ -44,6 +44,7 @@ 14.4 private static sun.jvm.hotspot.types.OopField systemKlassField; 14.5 private static sun.jvm.hotspot.types.OopField threadKlassField; 14.6 private static sun.jvm.hotspot.types.OopField threadGroupKlassField; 14.7 + private static sun.jvm.hotspot.types.OopField methodHandleKlassField; 14.8 14.9 static { 14.10 VM.registerVMInitializedObserver(new Observer() { 14.11 @@ -69,6 +70,7 @@ 14.12 systemKlassField = type.getOopField(WK_KLASS("System_klass")); 14.13 threadKlassField = type.getOopField(WK_KLASS("Thread_klass")); 14.14 threadGroupKlassField = type.getOopField(WK_KLASS("ThreadGroup_klass")); 14.15 + methodHandleKlassField = type.getOopField(WK_KLASS("MethodHandle_klass")); 14.16 } 14.17 14.18 // This WK functions must follow the definitions in systemDictionary.hpp: 14.19 @@ -127,6 +129,10 @@ 14.20 return (InstanceKlass) newOop(systemKlassField.getValue()); 14.21 } 14.22 14.23 + public static InstanceKlass getMethodHandleKlass() { 14.24 + return (InstanceKlass) newOop(methodHandleKlassField.getValue()); 14.25 + } 14.26 + 14.27 public InstanceKlass getAbstractOwnableSynchronizerKlass() { 14.28 return (InstanceKlass) find("java/util/concurrent/locks/AbstractOwnableSynchronizer", 14.29 null, null);
15.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java Thu Sep 08 16:59:27 2011 -0700 15.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java Fri Sep 09 16:17:16 2011 -0700 15.3 @@ -93,6 +93,8 @@ 15.4 } 15.5 15.6 public StackValueCollection getLocals() { 15.7 + if (getScope() == null) 15.8 + return new StackValueCollection(); 15.9 List scvList = getScope().getLocals(); 15.10 if (scvList == null) 15.11 return new StackValueCollection(); 15.12 @@ -108,6 +110,8 @@ 15.13 } 15.14 15.15 public StackValueCollection getExpressions() { 15.16 + if (getScope() == null) 15.17 + return new StackValueCollection(); 15.18 List scvList = getScope().getExpressions(); 15.19 if (scvList == null) 15.20 return new StackValueCollection();
16.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java Thu Sep 08 16:59:27 2011 -0700 16.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java Fri Sep 09 16:17:16 2011 -0700 16.3 @@ -33,6 +33,7 @@ 16.4 import sun.jvm.hotspot.debugger.*; 16.5 import sun.jvm.hotspot.interpreter.*; 16.6 import sun.jvm.hotspot.oops.*; 16.7 +import sun.jvm.hotspot.runtime.sparc.SPARCFrame; 16.8 import sun.jvm.hotspot.types.*; 16.9 import sun.jvm.hotspot.utilities.*; 16.10 16.11 @@ -74,11 +75,19 @@ 16.12 /** Size of constMethodOopDesc for computing BCI from BCP (FIXME: hack) */ 16.13 private static long constMethodOopDescSize; 16.14 16.15 + private static int pcReturnOffset; 16.16 + 16.17 + public static int pcReturnOffset() { 16.18 + return pcReturnOffset; 16.19 + } 16.20 + 16.21 private static synchronized void initialize(TypeDataBase db) { 16.22 Type constMethodOopType = db.lookupType("constMethodOopDesc"); 16.23 // FIXME: not sure whether alignment here is correct or how to 16.24 // force it (round up to address size?) 16.25 constMethodOopDescSize = constMethodOopType.getSize(); 16.26 + 16.27 + pcReturnOffset = db.lookupIntConstant("frame::pc_return_offset").intValue(); 16.28 } 16.29 16.30 protected int bcpToBci(Address bcp, ConstMethod cm) { 16.31 @@ -106,6 +115,10 @@ 16.32 public void setPC(Address newpc) { pc = newpc; } 16.33 public boolean isDeoptimized() { return deoptimized; } 16.34 16.35 + public CodeBlob cb() { 16.36 + return VM.getVM().getCodeCache().findBlob(getPC()); 16.37 + } 16.38 + 16.39 public abstract Address getSP(); 16.40 public abstract Address getID(); 16.41 public abstract Address getFP(); 16.42 @@ -134,6 +147,12 @@ 16.43 } 16.44 } 16.45 16.46 + public boolean isRicochetFrame() { 16.47 + CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC()); 16.48 + RicochetBlob rcb = VM.getVM().ricochetBlob(); 16.49 + return (cb == rcb && rcb != null && rcb.returnsToBounceAddr(getPC())); 16.50 + } 16.51 + 16.52 public boolean isCompiledFrame() { 16.53 if (Assert.ASSERTS_ENABLED) { 16.54 Assert.that(!VM.getVM().isCore(), "noncore builds only"); 16.55 @@ -142,7 +161,7 @@ 16.56 return (cb != null && cb.isJavaMethod()); 16.57 } 16.58 16.59 - public boolean isGlueFrame() { 16.60 + public boolean isRuntimeFrame() { 16.61 if (Assert.ASSERTS_ENABLED) { 16.62 Assert.that(!VM.getVM().isCore(), "noncore builds only"); 16.63 } 16.64 @@ -197,7 +216,8 @@ 16.65 public Frame realSender(RegisterMap map) { 16.66 if (!VM.getVM().isCore()) { 16.67 Frame result = sender(map); 16.68 - while (result.isGlueFrame()) { 16.69 + while (result.isRuntimeFrame() || 16.70 + result.isRicochetFrame()) { 16.71 result = result.sender(map); 16.72 } 16.73 return result; 16.74 @@ -611,6 +631,9 @@ 16.75 if (Assert.ASSERTS_ENABLED) { 16.76 Assert.that(cb != null, "sanity check"); 16.77 } 16.78 + if (cb == VM.getVM().ricochetBlob()) { 16.79 + oopsRicochetDo(oopVisitor, regMap); 16.80 + } 16.81 if (cb.getOopMaps() != null) { 16.82 OopMapSet.oopsDo(this, cb, regMap, oopVisitor, VM.getVM().isDebugging()); 16.83 16.84 @@ -627,6 +650,10 @@ 16.85 // } 16.86 } 16.87 16.88 + private void oopsRicochetDo (AddressVisitor oopVisitor, RegisterMap regMap) { 16.89 + // XXX Empty for now 16.90 + } 16.91 + 16.92 // FIXME: implement the above routines, plus add 16.93 // oops_interpreted_arguments_do and oops_compiled_arguments_do 16.94 }
17.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java Thu Sep 08 16:59:27 2011 -0700 17.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaVFrame.java Fri Sep 09 16:17:16 2011 -0700 17.3 @@ -128,14 +128,14 @@ 17.4 } 17.5 17.6 // dynamic part - we just compare the frame pointer 17.7 - if (! getFrame().getFP().equals(other.getFrame().getFP())) { 17.8 + if (! getFrame().equals(other.getFrame())) { 17.9 return false; 17.10 } 17.11 return true; 17.12 } 17.13 17.14 public int hashCode() { 17.15 - return getMethod().hashCode() ^ getBCI() ^ getFrame().getFP().hashCode(); 17.16 + return getMethod().hashCode() ^ getBCI() ^ getFrame().hashCode(); 17.17 } 17.18 17.19 /** Structural compare */
18.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java Thu Sep 08 16:59:27 2011 -0700 18.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java Fri Sep 09 16:17:16 2011 -0700 18.3 @@ -100,7 +100,7 @@ 18.4 18.5 public int hashCode() { 18.6 if (type == BasicType.getTObject()) { 18.7 - return handleValue.hashCode(); 18.8 + return handleValue != null ? handleValue.hashCode() : 5; 18.9 } else { 18.10 // Returns 0 for conflict type 18.11 return (int) integerValue;
19.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java Thu Sep 08 16:59:27 2011 -0700 19.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VFrame.java Fri Sep 09 16:17:16 2011 -0700 19.3 @@ -77,7 +77,7 @@ 19.4 return new CompiledVFrame(f, regMap, thread, scope, mayBeImprecise); 19.5 } 19.6 19.7 - if (f.isGlueFrame()) { 19.8 + if (f.isRuntimeFrame()) { 19.9 // This is a conversion frame. Skip this frame and try again. 19.10 RegisterMap tempMap = regMap.copy(); 19.11 Frame s = f.sender(tempMap);
20.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Thu Sep 08 16:59:27 2011 -0700 20.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Fri Sep 09 16:17:16 2011 -0700 20.3 @@ -30,6 +30,7 @@ 20.4 import java.util.regex.*; 20.5 import sun.jvm.hotspot.code.*; 20.6 import sun.jvm.hotspot.c1.*; 20.7 +import sun.jvm.hotspot.code.*; 20.8 import sun.jvm.hotspot.debugger.*; 20.9 import sun.jvm.hotspot.interpreter.*; 20.10 import sun.jvm.hotspot.memory.*; 20.11 @@ -85,6 +86,9 @@ 20.12 private Interpreter interpreter; 20.13 private StubRoutines stubRoutines; 20.14 private Bytes bytes; 20.15 + 20.16 + private RicochetBlob ricochetBlob; 20.17 + 20.18 /** Flags indicating whether we are attached to a core, C1, or C2 build */ 20.19 private boolean usingClientCompiler; 20.20 private boolean usingServerCompiler; 20.21 @@ -618,6 +622,18 @@ 20.22 return stubRoutines; 20.23 } 20.24 20.25 + public RicochetBlob ricochetBlob() { 20.26 + if (ricochetBlob == null) { 20.27 + Type ricochetType = db.lookupType("SharedRuntime"); 20.28 + AddressField ricochetBlobAddress = ricochetType.getAddressField("_ricochet_blob"); 20.29 + Address addr = ricochetBlobAddress.getValue(); 20.30 + if (addr != null) { 20.31 + ricochetBlob = new RicochetBlob(addr); 20.32 + } 20.33 + } 20.34 + return ricochetBlob; 20.35 + } 20.36 + 20.37 public VMRegImpl getVMRegImplInfo() { 20.38 if (vmregImpl == null) { 20.39 vmregImpl = new VMRegImpl();
21.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java Thu Sep 08 16:59:27 2011 -0700 21.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java Fri Sep 09 16:17:16 2011 -0700 21.3 @@ -29,6 +29,7 @@ 21.4 import sun.jvm.hotspot.code.*; 21.5 import sun.jvm.hotspot.interpreter.*; 21.6 import sun.jvm.hotspot.runtime.*; 21.7 +import sun.jvm.hotspot.runtime.x86.*; 21.8 21.9 /** <P> Should be able to be used on all amd64 platforms we support 21.10 (Linux/amd64) to implement JavaThread's 21.11 @@ -123,7 +124,7 @@ 21.12 offset += vm.getAddressSize()) { 21.13 try { 21.14 Address curSP = sp.addOffsetTo(offset); 21.15 - Frame frame = new AMD64Frame(curSP, null, pc); 21.16 + Frame frame = new X86Frame(curSP, null, pc); 21.17 RegisterMap map = thread.newRegisterMap(false); 21.18 while (frame != null) { 21.19 if (frame.isEntryFrame() && frame.entryFrameIsFirst()) {
22.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64Frame.java Thu Sep 08 16:59:27 2011 -0700 22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 22.3 @@ -1,528 +0,0 @@ 22.4 -/* 22.5 - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. 22.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 22.7 - * 22.8 - * This code is free software; you can redistribute it and/or modify it 22.9 - * under the terms of the GNU General Public License version 2 only, as 22.10 - * published by the Free Software Foundation. 22.11 - * 22.12 - * This code is distributed in the hope that it will be useful, but WITHOUT 22.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 22.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 22.15 - * version 2 for more details (a copy is included in the LICENSE file that 22.16 - * accompanied this code). 22.17 - * 22.18 - * You should have received a copy of the GNU General Public License version 22.19 - * 2 along with this work; if not, write to the Free Software Foundation, 22.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22.21 - * 22.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22.23 - * or visit www.oracle.com if you need additional information or have any 22.24 - * questions. 22.25 - * 22.26 - */ 22.27 - 22.28 -package sun.jvm.hotspot.runtime.amd64; 22.29 - 22.30 -import java.util.*; 22.31 -import sun.jvm.hotspot.code.*; 22.32 -import sun.jvm.hotspot.compiler.*; 22.33 -import sun.jvm.hotspot.debugger.*; 22.34 -import sun.jvm.hotspot.oops.*; 22.35 -import sun.jvm.hotspot.runtime.*; 22.36 -import sun.jvm.hotspot.types.*; 22.37 -import sun.jvm.hotspot.utilities.*; 22.38 - 22.39 -/** Specialization of and implementation of abstract methods of the 22.40 - Frame class for the amd64 CPU. */ 22.41 - 22.42 -public class AMD64Frame extends Frame { 22.43 - private static final boolean DEBUG; 22.44 - static { 22.45 - DEBUG = System.getProperty("sun.jvm.hotspot.runtime.amd64.AMD64Frame.DEBUG") != null; 22.46 - } 22.47 - 22.48 - // refer to frame_amd64.hpp 22.49 - private static final int PC_RETURN_OFFSET = 0; 22.50 - // All frames 22.51 - private static final int LINK_OFFSET = 0; 22.52 - private static final int RETURN_ADDR_OFFSET = 1; 22.53 - private static final int SENDER_SP_OFFSET = 2; 22.54 - 22.55 - // Interpreter frames 22.56 - private static final int INTERPRETER_FRAME_MIRROR_OFFSET = 2; // for native calls only 22.57 - private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -1; 22.58 - private static final int INTERPRETER_FRAME_LAST_SP_OFFSET = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1; 22.59 - private static final int INTERPRETER_FRAME_METHOD_OFFSET = INTERPRETER_FRAME_LAST_SP_OFFSET - 1; 22.60 - private static int INTERPRETER_FRAME_MDX_OFFSET; // Non-core builds only 22.61 - private static int INTERPRETER_FRAME_CACHE_OFFSET; 22.62 - private static int INTERPRETER_FRAME_LOCALS_OFFSET; 22.63 - private static int INTERPRETER_FRAME_BCX_OFFSET; 22.64 - private static int INTERPRETER_FRAME_INITIAL_SP_OFFSET; 22.65 - private static int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET; 22.66 - private static int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET; 22.67 - 22.68 - // Entry frames 22.69 - private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET = -6; 22.70 - 22.71 - // Native frames 22.72 - private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET = 2; 22.73 - 22.74 - static { 22.75 - VM.registerVMInitializedObserver(new Observer() { 22.76 - public void update(Observable o, Object data) { 22.77 - initialize(VM.getVM().getTypeDataBase()); 22.78 - } 22.79 - }); 22.80 - } 22.81 - 22.82 - private static synchronized void initialize(TypeDataBase db) { 22.83 - if (VM.getVM().isCore()) { 22.84 - INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; 22.85 - } else { 22.86 - INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; 22.87 - INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1; 22.88 - } 22.89 - INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1; 22.90 - INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1; 22.91 - INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1; 22.92 - INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; 22.93 - INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; 22.94 - } 22.95 - 22.96 - // an additional field beyond sp and pc: 22.97 - Address raw_fp; // frame pointer 22.98 - private Address raw_unextendedSP; 22.99 - 22.100 - private AMD64Frame() { 22.101 - } 22.102 - 22.103 - private void adjustForDeopt() { 22.104 - if ( pc != null) { 22.105 - // Look for a deopt pc and if it is deopted convert to original pc 22.106 - CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); 22.107 - if (cb != null && cb.isJavaMethod()) { 22.108 - NMethod nm = (NMethod) cb; 22.109 - if (pc.equals(nm.deoptBegin())) { 22.110 - // adjust pc if frame is deoptimized. 22.111 - if (Assert.ASSERTS_ENABLED) { 22.112 - Assert.that(this.getUnextendedSP() != null, "null SP in Java frame"); 22.113 - } 22.114 - pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); 22.115 - deoptimized = true; 22.116 - } 22.117 - } 22.118 - } 22.119 - } 22.120 - 22.121 - public AMD64Frame(Address raw_sp, Address raw_fp, Address pc) { 22.122 - this.raw_sp = raw_sp; 22.123 - this.raw_unextendedSP = raw_sp; 22.124 - this.raw_fp = raw_fp; 22.125 - this.pc = pc; 22.126 - 22.127 - // Frame must be fully constructed before this call 22.128 - adjustForDeopt(); 22.129 - 22.130 - if (DEBUG) { 22.131 - System.out.println("AMD64Frame(sp, fp, pc): " + this); 22.132 - dumpStack(); 22.133 - } 22.134 - } 22.135 - 22.136 - public AMD64Frame(Address raw_sp, Address raw_fp) { 22.137 - this.raw_sp = raw_sp; 22.138 - this.raw_unextendedSP = raw_sp; 22.139 - this.raw_fp = raw_fp; 22.140 - this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); 22.141 - 22.142 - // Frame must be fully constructed before this call 22.143 - adjustForDeopt(); 22.144 - 22.145 - if (DEBUG) { 22.146 - System.out.println("AMD64Frame(sp, fp): " + this); 22.147 - dumpStack(); 22.148 - } 22.149 - } 22.150 - 22.151 - // This constructor should really take the unextended SP as an arg 22.152 - // but then the constructor is ambiguous with constructor that takes 22.153 - // a PC so take an int and convert it. 22.154 - public AMD64Frame(Address raw_sp, Address raw_fp, long extension) { 22.155 - this.raw_sp = raw_sp; 22.156 - if ( raw_sp == null) { 22.157 - this.raw_unextendedSP = null; 22.158 - } else { 22.159 - this.raw_unextendedSP = raw_sp.addOffsetTo(extension); 22.160 - } 22.161 - this.raw_fp = raw_fp; 22.162 - this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); 22.163 - 22.164 - // Frame must be fully constructed before this call 22.165 - adjustForDeopt(); 22.166 - 22.167 - if (DEBUG) { 22.168 - System.out.println("AMD64Frame(sp, fp, extension): " + this); 22.169 - dumpStack(); 22.170 - } 22.171 - 22.172 - } 22.173 - 22.174 - public Object clone() { 22.175 - AMD64Frame frame = new AMD64Frame(); 22.176 - frame.raw_sp = raw_sp; 22.177 - frame.raw_unextendedSP = raw_unextendedSP; 22.178 - frame.raw_fp = raw_fp; 22.179 - frame.pc = pc; 22.180 - frame.deoptimized = deoptimized; 22.181 - return frame; 22.182 - } 22.183 - 22.184 - public boolean equals(Object arg) { 22.185 - if (arg == null) { 22.186 - return false; 22.187 - } 22.188 - 22.189 - if (!(arg instanceof AMD64Frame)) { 22.190 - return false; 22.191 - } 22.192 - 22.193 - AMD64Frame other = (AMD64Frame) arg; 22.194 - 22.195 - return (AddressOps.equal(getSP(), other.getSP()) && 22.196 - AddressOps.equal(getFP(), other.getFP()) && 22.197 - AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) && 22.198 - AddressOps.equal(getPC(), other.getPC())); 22.199 - } 22.200 - 22.201 - public int hashCode() { 22.202 - if (raw_sp == null) { 22.203 - return 0; 22.204 - } 22.205 - 22.206 - return raw_sp.hashCode(); 22.207 - } 22.208 - 22.209 - public String toString() { 22.210 - return "sp: " + (getSP() == null? "null" : getSP().toString()) + 22.211 - ", unextendedSP: " + (getUnextendedSP() == null? "null" : getUnextendedSP().toString()) + 22.212 - ", fp: " + (getFP() == null? "null" : getFP().toString()) + 22.213 - ", pc: " + (pc == null? "null" : pc.toString()); 22.214 - } 22.215 - 22.216 - // accessors for the instance variables 22.217 - public Address getFP() { return raw_fp; } 22.218 - public Address getSP() { return raw_sp; } 22.219 - public Address getID() { return raw_sp; } 22.220 - 22.221 - // FIXME: not implemented yet (should be done for Solaris/AMD64) 22.222 - public boolean isSignalHandlerFrameDbg() { return false; } 22.223 - public int getSignalNumberDbg() { return 0; } 22.224 - public String getSignalNameDbg() { return null; } 22.225 - 22.226 - public boolean isInterpretedFrameValid() { 22.227 - if (Assert.ASSERTS_ENABLED) { 22.228 - Assert.that(isInterpretedFrame(), "Not an interpreted frame"); 22.229 - } 22.230 - 22.231 - // These are reasonable sanity checks 22.232 - if (getFP() == null || getFP().andWithMask(0x3) != null) { 22.233 - return false; 22.234 - } 22.235 - 22.236 - if (getSP() == null || getSP().andWithMask(0x3) != null) { 22.237 - return false; 22.238 - } 22.239 - 22.240 - if (getFP().addOffsetTo(INTERPRETER_FRAME_INITIAL_SP_OFFSET * VM.getVM().getAddressSize()).lessThan(getSP())) { 22.241 - return false; 22.242 - } 22.243 - 22.244 - // These are hacks to keep us out of trouble. 22.245 - // The problem with these is that they mask other problems 22.246 - if (getFP().lessThanOrEqual(getSP())) { 22.247 - // this attempts to deal with unsigned comparison above 22.248 - return false; 22.249 - } 22.250 - 22.251 - if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) { 22.252 - // stack frames shouldn't be large. 22.253 - return false; 22.254 - } 22.255 - 22.256 - return true; 22.257 - } 22.258 - 22.259 - // FIXME: not applicable in current system 22.260 - // void patch_pc(Thread* thread, address pc); 22.261 - 22.262 - public Frame sender(RegisterMap regMap, CodeBlob cb) { 22.263 - AMD64RegisterMap map = (AMD64RegisterMap) regMap; 22.264 - 22.265 - if (Assert.ASSERTS_ENABLED) { 22.266 - Assert.that(map != null, "map must be set"); 22.267 - } 22.268 - 22.269 - // Default is we done have to follow them. The sender_for_xxx will 22.270 - // update it accordingly 22.271 - map.setIncludeArgumentOops(false); 22.272 - 22.273 - if (isEntryFrame()) return senderForEntryFrame(map); 22.274 - if (isInterpretedFrame()) return senderForInterpreterFrame(map); 22.275 - 22.276 - 22.277 - if (!VM.getVM().isCore()) { 22.278 - if(cb == null) { 22.279 - cb = VM.getVM().getCodeCache().findBlob(getPC()); 22.280 - } else { 22.281 - if (Assert.ASSERTS_ENABLED) { 22.282 - Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same"); 22.283 - } 22.284 - } 22.285 - 22.286 - if (cb != null) { 22.287 - return senderForCompiledFrame(map, cb); 22.288 - } 22.289 - } 22.290 - 22.291 - // Must be native-compiled frame, i.e. the marshaling code for native 22.292 - // methods that exists in the core system. 22.293 - return new AMD64Frame(getSenderSP(), getLink(), getSenderPC()); 22.294 - } 22.295 - 22.296 - private Frame senderForEntryFrame(AMD64RegisterMap map) { 22.297 - if (Assert.ASSERTS_ENABLED) { 22.298 - Assert.that(map != null, "map must be set"); 22.299 - } 22.300 - // Java frame called from C; skip all C frames and return top C 22.301 - // frame of that chunk as the sender 22.302 - AMD64JavaCallWrapper jcw = (AMD64JavaCallWrapper) getEntryFrameCallWrapper(); 22.303 - if (Assert.ASSERTS_ENABLED) { 22.304 - Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero"); 22.305 - Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack"); 22.306 - } 22.307 - AMD64Frame fr; 22.308 - if (jcw.getLastJavaPC() != null) { 22.309 - fr = new AMD64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC()); 22.310 - } else { 22.311 - fr = new AMD64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP()); 22.312 - } 22.313 - map.clear(); 22.314 - if (Assert.ASSERTS_ENABLED) { 22.315 - Assert.that(map.getIncludeArgumentOops(), "should be set by clear"); 22.316 - } 22.317 - return fr; 22.318 - } 22.319 - 22.320 - private Frame senderForInterpreterFrame(AMD64RegisterMap map) { 22.321 - Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); 22.322 - Address sp = addressOfStackSlot(SENDER_SP_OFFSET); 22.323 - // We do not need to update the callee-save register mapping because above 22.324 - // us is either another interpreter frame or a converter-frame, but never 22.325 - // directly a compiled frame. 22.326 - // 11/24/04 SFG. This is no longer true after adapter were removed. However at the moment 22.327 - // C2 no longer uses callee save register for java calls so there are no callee register 22.328 - // to find. 22.329 - return new AMD64Frame(sp, getLink(), unextendedSP.minus(sp)); 22.330 - } 22.331 - 22.332 - private Frame senderForCompiledFrame(AMD64RegisterMap map, CodeBlob cb) { 22.333 - // 22.334 - // NOTE: some of this code is (unfortunately) duplicated in AMD64CurrentFrameGuess 22.335 - // 22.336 - 22.337 - if (Assert.ASSERTS_ENABLED) { 22.338 - Assert.that(map != null, "map must be set"); 22.339 - } 22.340 - 22.341 - // frame owned by optimizing compiler 22.342 - Address sender_sp = null; 22.343 - 22.344 - 22.345 - if (VM.getVM().isClientCompiler()) { 22.346 - sender_sp = addressOfStackSlot(SENDER_SP_OFFSET); 22.347 - } else { 22.348 - if (Assert.ASSERTS_ENABLED) { 22.349 - Assert.that(cb.getFrameSize() >= 0, "Compiled by Compiler1: do not use"); 22.350 - } 22.351 - sender_sp = getUnextendedSP().addOffsetTo(cb.getFrameSize()); 22.352 - } 22.353 - 22.354 - // On Intel the return_address is always the word on the stack 22.355 - Address sender_pc = sender_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); 22.356 - 22.357 - if (map.getUpdateMap() && cb.getOopMaps() != null) { 22.358 - OopMapSet.updateRegisterMap(this, cb, map, true); 22.359 - } 22.360 - 22.361 - if (VM.getVM().isClientCompiler()) { 22.362 - // Move this here for C1 and collecting oops in arguments (According to Rene) 22.363 - map.setIncludeArgumentOops(cb.callerMustGCArguments(map.getThread())); 22.364 - } 22.365 - 22.366 - Address saved_fp = null; 22.367 - if (VM.getVM().isClientCompiler()) { 22.368 - saved_fp = getFP().getAddressAt(0); 22.369 - } else if (VM.getVM().isServerCompiler() && 22.370 - (VM.getVM().getInterpreter().contains(sender_pc) || 22.371 - VM.getVM().getStubRoutines().returnsToCallStub(sender_pc))) { 22.372 - // C2 prologue saves EBP in the usual place. 22.373 - // however only use it if the sender had link infomration in it. 22.374 - saved_fp = sender_sp.getAddressAt(-2 * VM.getVM().getAddressSize()); 22.375 - } 22.376 - 22.377 - return new AMD64Frame(sender_sp, saved_fp, sender_pc); 22.378 - } 22.379 - 22.380 - protected boolean hasSenderPD() { 22.381 - // FIXME 22.382 - // Check for null ebp? Need to do some tests. 22.383 - return true; 22.384 - } 22.385 - 22.386 - public long frameSize() { 22.387 - return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize()); 22.388 - } 22.389 - 22.390 - public Address getLink() { 22.391 - return addressOfStackSlot(LINK_OFFSET).getAddressAt(0); 22.392 - } 22.393 - 22.394 - // FIXME: not implementable yet 22.395 - //inline void frame::set_link(intptr_t* addr) { *(intptr_t **)addr_at(link_offset) = addr; } 22.396 - 22.397 - public Address getUnextendedSP() { return raw_unextendedSP; } 22.398 - 22.399 - // Return address: 22.400 - public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); } 22.401 - public Address getSenderPC() { return getSenderPCAddr().getAddressAt(0); } 22.402 - 22.403 - // return address of param, zero origin index. 22.404 - public Address getNativeParamAddr(int idx) { 22.405 - return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx); 22.406 - } 22.407 - 22.408 - public Address getSenderSP() { return addressOfStackSlot(SENDER_SP_OFFSET); } 22.409 - 22.410 - public Address compiledArgumentToLocationPD(VMReg reg, RegisterMap regMap, int argSize) { 22.411 - if (VM.getVM().isCore() || VM.getVM().isClientCompiler()) { 22.412 - throw new RuntimeException("Should not reach here"); 22.413 - } 22.414 - 22.415 - return oopMapRegToLocation(reg, regMap); 22.416 - } 22.417 - 22.418 - public Address addressOfInterpreterFrameLocals() { 22.419 - return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET); 22.420 - } 22.421 - 22.422 - private Address addressOfInterpreterFrameBCX() { 22.423 - return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET); 22.424 - } 22.425 - 22.426 - public int getInterpreterFrameBCI() { 22.427 - // FIXME: this is not atomic with respect to GC and is unsuitable 22.428 - // for use in a non-debugging, or reflective, system. Need to 22.429 - // figure out how to express this. 22.430 - Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0); 22.431 - OopHandle methodHandle = addressOfInterpreterFrameMethod().getOopHandleAt(0); 22.432 - Method method = (Method) VM.getVM().getObjectHeap().newOop(methodHandle); 22.433 - return (int) bcpToBci(bcp, method); 22.434 - } 22.435 - 22.436 - public Address addressOfInterpreterFrameMDX() { 22.437 - return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET); 22.438 - } 22.439 - 22.440 - // FIXME 22.441 - //inline int frame::interpreter_frame_monitor_size() { 22.442 - // return BasicObjectLock::size(); 22.443 - //} 22.444 - 22.445 - // expression stack 22.446 - // (the max_stack arguments are used by the GC; see class FrameClosure) 22.447 - 22.448 - public Address addressOfInterpreterFrameExpressionStack() { 22.449 - Address monitorEnd = interpreterFrameMonitorEnd().address(); 22.450 - return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize()); 22.451 - } 22.452 - 22.453 - public int getInterpreterFrameExpressionStackDirection() { return -1; } 22.454 - 22.455 - // top of expression stack 22.456 - public Address addressOfInterpreterFrameTOS() { 22.457 - return getSP(); 22.458 - } 22.459 - 22.460 - /** Expression stack from top down */ 22.461 - public Address addressOfInterpreterFrameTOSAt(int slot) { 22.462 - return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize()); 22.463 - } 22.464 - 22.465 - public Address getInterpreterFrameSenderSP() { 22.466 - if (Assert.ASSERTS_ENABLED) { 22.467 - Assert.that(isInterpretedFrame(), "interpreted frame expected"); 22.468 - } 22.469 - return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); 22.470 - } 22.471 - 22.472 - // Monitors 22.473 - public BasicObjectLock interpreterFrameMonitorBegin() { 22.474 - return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET)); 22.475 - } 22.476 - 22.477 - public BasicObjectLock interpreterFrameMonitorEnd() { 22.478 - Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0); 22.479 - if (Assert.ASSERTS_ENABLED) { 22.480 - // make sure the pointer points inside the frame 22.481 - Assert.that(AddressOps.gt(getFP(), result), "result must < than frame pointer"); 22.482 - Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer"); 22.483 - } 22.484 - return new BasicObjectLock(result); 22.485 - } 22.486 - 22.487 - public int interpreterFrameMonitorSize() { 22.488 - return BasicObjectLock.size(); 22.489 - } 22.490 - 22.491 - // Method 22.492 - public Address addressOfInterpreterFrameMethod() { 22.493 - return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET); 22.494 - } 22.495 - 22.496 - // Constant pool cache 22.497 - public Address addressOfInterpreterFrameCPCache() { 22.498 - return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET); 22.499 - } 22.500 - 22.501 - // Entry frames 22.502 - public JavaCallWrapper getEntryFrameCallWrapper() { 22.503 - return new AMD64JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0)); 22.504 - } 22.505 - 22.506 - protected Address addressOfSavedOopResult() { 22.507 - // offset is 2 for compiler2 and 3 for compiler1 22.508 - return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) * 22.509 - VM.getVM().getAddressSize()); 22.510 - } 22.511 - 22.512 - protected Address addressOfSavedReceiver() { 22.513 - return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize()); 22.514 - } 22.515 - 22.516 - private void dumpStack() { 22.517 - if (getFP() != null) { 22.518 - for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize()); 22.519 - AddressOps.lte(addr, getFP().addOffsetTo(5 * VM.getVM().getAddressSize())); 22.520 - addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { 22.521 - System.out.println(addr + ": " + addr.getAddressAt(0)); 22.522 - } 22.523 - } else { 22.524 - for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize()); 22.525 - AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize())); 22.526 - addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { 22.527 - System.out.println(addr + ": " + addr.getAddressAt(0)); 22.528 - } 22.529 - } 22.530 - } 22.531 -}
23.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64RegisterMap.java Thu Sep 08 16:59:27 2011 -0700 23.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 23.3 @@ -1,52 +0,0 @@ 23.4 -/* 23.5 - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. 23.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 23.7 - * 23.8 - * This code is free software; you can redistribute it and/or modify it 23.9 - * under the terms of the GNU General Public License version 2 only, as 23.10 - * published by the Free Software Foundation. 23.11 - * 23.12 - * This code is distributed in the hope that it will be useful, but WITHOUT 23.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 23.15 - * version 2 for more details (a copy is included in the LICENSE file that 23.16 - * accompanied this code). 23.17 - * 23.18 - * You should have received a copy of the GNU General Public License version 23.19 - * 2 along with this work; if not, write to the Free Software Foundation, 23.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 23.21 - * 23.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23.23 - * or visit www.oracle.com if you need additional information or have any 23.24 - * questions. 23.25 - * 23.26 - */ 23.27 - 23.28 -package sun.jvm.hotspot.runtime.amd64; 23.29 - 23.30 -import sun.jvm.hotspot.asm.amd64.*; 23.31 -import sun.jvm.hotspot.debugger.*; 23.32 -import sun.jvm.hotspot.runtime.*; 23.33 - 23.34 -public class AMD64RegisterMap extends RegisterMap { 23.35 - 23.36 - /** This is the only public constructor */ 23.37 - public AMD64RegisterMap(JavaThread thread, boolean updateMap) { 23.38 - super(thread, updateMap); 23.39 - } 23.40 - 23.41 - protected AMD64RegisterMap(RegisterMap map) { 23.42 - super(map); 23.43 - } 23.44 - 23.45 - public Object clone() { 23.46 - AMD64RegisterMap retval = new AMD64RegisterMap(this); 23.47 - return retval; 23.48 - } 23.49 - 23.50 - // no PD state to clear or copy: 23.51 - protected void clearPD() {} 23.52 - protected void initializePD() {} 23.53 - protected void initializeFromPD(RegisterMap map) {} 23.54 - protected Address getLocationPD(VMReg reg) { return null; } 23.55 -}
24.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java Thu Sep 08 16:59:27 2011 -0700 24.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/linux_amd64/LinuxAMD64JavaThreadPDAccess.java Fri Sep 09 16:17:16 2011 -0700 24.3 @@ -30,6 +30,7 @@ 24.4 import sun.jvm.hotspot.debugger.amd64.*; 24.5 import sun.jvm.hotspot.runtime.*; 24.6 import sun.jvm.hotspot.runtime.amd64.*; 24.7 +import sun.jvm.hotspot.runtime.x86.*; 24.8 import sun.jvm.hotspot.types.*; 24.9 import sun.jvm.hotspot.utilities.*; 24.10 24.11 @@ -80,11 +81,11 @@ 24.12 if (fp == null) { 24.13 return null; // no information 24.14 } 24.15 - return new AMD64Frame(thread.getLastJavaSP(), fp); 24.16 + return new X86Frame(thread.getLastJavaSP(), fp); 24.17 } 24.18 24.19 public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) { 24.20 - return new AMD64RegisterMap(thread, updateMap); 24.21 + return new X86RegisterMap(thread, updateMap); 24.22 } 24.23 24.24 public Frame getCurrentFrameGuess(JavaThread thread, Address addr) { 24.25 @@ -95,9 +96,9 @@ 24.26 return null; 24.27 } 24.28 if (guesser.getPC() == null) { 24.29 - return new AMD64Frame(guesser.getSP(), guesser.getFP()); 24.30 + return new X86Frame(guesser.getSP(), guesser.getFP()); 24.31 } else { 24.32 - return new AMD64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); 24.33 + return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); 24.34 } 24.35 } 24.36
25.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java Thu Sep 08 16:59:27 2011 -0700 25.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/solaris_amd64/SolarisAMD64JavaThreadPDAccess.java Fri Sep 09 16:17:16 2011 -0700 25.3 @@ -30,6 +30,7 @@ 25.4 import sun.jvm.hotspot.debugger.amd64.*; 25.5 import sun.jvm.hotspot.runtime.*; 25.6 import sun.jvm.hotspot.runtime.amd64.*; 25.7 +import sun.jvm.hotspot.runtime.x86.*; 25.8 import sun.jvm.hotspot.types.*; 25.9 import sun.jvm.hotspot.utilities.*; 25.10 25.11 @@ -84,14 +85,14 @@ 25.12 } 25.13 Address pc = thread.getLastJavaPC(); 25.14 if ( pc != null ) { 25.15 - return new AMD64Frame(thread.getLastJavaSP(), fp, pc); 25.16 + return new X86Frame(thread.getLastJavaSP(), fp, pc); 25.17 } else { 25.18 - return new AMD64Frame(thread.getLastJavaSP(), fp); 25.19 + return new X86Frame(thread.getLastJavaSP(), fp); 25.20 } 25.21 } 25.22 25.23 public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) { 25.24 - return new AMD64RegisterMap(thread, updateMap); 25.25 + return new X86RegisterMap(thread, updateMap); 25.26 } 25.27 25.28 public Frame getCurrentFrameGuess(JavaThread thread, Address addr) { 25.29 @@ -102,9 +103,9 @@ 25.30 return null; 25.31 } 25.32 if (guesser.getPC() == null) { 25.33 - return new AMD64Frame(guesser.getSP(), guesser.getFP()); 25.34 + return new X86Frame(guesser.getSP(), guesser.getFP()); 25.35 } else { 25.36 - return new AMD64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); 25.37 + return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); 25.38 } 25.39 } 25.40
26.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java Thu Sep 08 16:59:27 2011 -0700 26.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java Fri Sep 09 16:17:16 2011 -0700 26.3 @@ -236,7 +236,7 @@ 26.4 CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); 26.5 if (cb != null && cb.isJavaMethod()) { 26.6 NMethod nm = (NMethod) cb; 26.7 - if (pc.equals(nm.deoptBegin())) { 26.8 + if (pc.equals(nm.deoptHandlerBegin())) { 26.9 // adjust pc if frame is deoptimized. 26.10 pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); 26.11 deoptimized = true; 26.12 @@ -559,49 +559,46 @@ 26.13 } 26.14 } 26.15 26.16 - if (!VM.getVM().isCore()) { 26.17 - // Note: The version of this operation on any platform with callee-save 26.18 - // registers must update the register map (if not null). 26.19 - // In order to do this correctly, the various subtypes of 26.20 - // of frame (interpreted, compiled, glue, native), 26.21 - // must be distinguished. There is no need on SPARC for 26.22 - // such distinctions, because all callee-save registers are 26.23 - // preserved for all frames via SPARC-specific mechanisms. 26.24 - // 26.25 - // *** HOWEVER, *** if and when we make any floating-point 26.26 - // registers callee-saved, then we will have to copy over 26.27 - // the RegisterMap update logic from the Intel code. 26.28 + // Note: The version of this operation on any platform with callee-save 26.29 + // registers must update the register map (if not null). 26.30 + // In order to do this correctly, the various subtypes of 26.31 + // of frame (interpreted, compiled, glue, native), 26.32 + // must be distinguished. There is no need on SPARC for 26.33 + // such distinctions, because all callee-save registers are 26.34 + // preserved for all frames via SPARC-specific mechanisms. 26.35 + // 26.36 + // *** HOWEVER, *** if and when we make any floating-point 26.37 + // registers callee-saved, then we will have to copy over 26.38 + // the RegisterMap update logic from the Intel code. 26.39 26.40 + if (isRicochetFrame()) return senderForRicochetFrame(map); 26.41 26.42 - // The constructor of the sender must know whether this frame is interpreted so it can set the 26.43 - // sender's _interpreter_sp_adjustment field. 26.44 - if (VM.getVM().getInterpreter().contains(pc)) { 26.45 - isInterpreted = true; 26.46 - map.makeIntegerRegsUnsaved(); 26.47 + // The constructor of the sender must know whether this frame is interpreted so it can set the 26.48 + // sender's _interpreter_sp_adjustment field. 26.49 + if (VM.getVM().getInterpreter().contains(pc)) { 26.50 + isInterpreted = true; 26.51 + map.makeIntegerRegsUnsaved(); 26.52 + map.shiftWindow(sp, youngerSP); 26.53 + } else { 26.54 + // Find a CodeBlob containing this frame's pc or elide the lookup and use the 26.55 + // supplied blob which is already known to be associated with this frame. 26.56 + cb = VM.getVM().getCodeCache().findBlob(pc); 26.57 + if (cb != null) { 26.58 + // Update the location of all implicitly saved registers 26.59 + // as the address of these registers in the register save 26.60 + // area (for %o registers we use the address of the %i 26.61 + // register in the next younger frame) 26.62 map.shiftWindow(sp, youngerSP); 26.63 - } else { 26.64 - // Find a CodeBlob containing this frame's pc or elide the lookup and use the 26.65 - // supplied blob which is already known to be associated with this frame. 26.66 - cb = VM.getVM().getCodeCache().findBlob(pc); 26.67 - if (cb != null) { 26.68 - 26.69 - if (cb.callerMustGCArguments(map.getThread())) { 26.70 + if (map.getUpdateMap()) { 26.71 + if (cb.callerMustGCArguments()) { 26.72 map.setIncludeArgumentOops(true); 26.73 } 26.74 - 26.75 - // Update the location of all implicitly saved registers 26.76 - // as the address of these registers in the register save 26.77 - // area (for %o registers we use the address of the %i 26.78 - // register in the next younger frame) 26.79 - map.shiftWindow(sp, youngerSP); 26.80 - if (map.getUpdateMap()) { 26.81 - if (cb.getOopMaps() != null) { 26.82 - OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging()); 26.83 - } 26.84 + if (cb.getOopMaps() != null) { 26.85 + OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging()); 26.86 } 26.87 } 26.88 } 26.89 - } // #ifndef CORE 26.90 + } 26.91 26.92 return new SPARCFrame(biasSP(sp), biasSP(youngerSP), isInterpreted); 26.93 } 26.94 @@ -948,6 +945,20 @@ 26.95 } 26.96 26.97 26.98 + private Frame senderForRicochetFrame(SPARCRegisterMap map) { 26.99 + if (DEBUG) { 26.100 + System.out.println("senderForRicochetFrame"); 26.101 + } 26.102 + //RicochetFrame* f = RicochetFrame::from_frame(fr); 26.103 + // Cf. is_interpreted_frame path of frame::sender 26.104 + Address youngerSP = getSP(); 26.105 + Address sp = getSenderSP(); 26.106 + map.makeIntegerRegsUnsaved(); 26.107 + map.shiftWindow(sp, youngerSP); 26.108 + boolean thisFrameAdjustedStack = true; // I5_savedSP is live in this RF 26.109 + return new SPARCFrame(sp, youngerSP, thisFrameAdjustedStack); 26.110 + } 26.111 + 26.112 private Frame senderForEntryFrame(RegisterMap regMap) { 26.113 SPARCRegisterMap map = (SPARCRegisterMap) regMap; 26.114 26.115 @@ -965,10 +976,8 @@ 26.116 Address lastJavaPC = jcw.getLastJavaPC(); 26.117 map.clear(); 26.118 26.119 - if (!VM.getVM().isCore()) { 26.120 - map.makeIntegerRegsUnsaved(); 26.121 - map.shiftWindow(lastJavaSP, null); 26.122 - } 26.123 + map.makeIntegerRegsUnsaved(); 26.124 + map.shiftWindow(lastJavaSP, null); 26.125 26.126 if (Assert.ASSERTS_ENABLED) { 26.127 Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCRicochetFrame.java Fri Sep 09 16:17:16 2011 -0700 27.3 @@ -0,0 +1,77 @@ 27.4 +/* 27.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 27.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 27.7 + * 27.8 + * This code is free software; you can redistribute it and/or modify it 27.9 + * under the terms of the GNU General Public License version 2 only, as 27.10 + * published by the Free Software Foundation. 27.11 + * 27.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 27.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 27.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 27.15 + * version 2 for more details (a copy is included in the LICENSE file that 27.16 + * accompanied this code). 27.17 + * 27.18 + * You should have received a copy of the GNU General Public License version 27.19 + * 2 along with this work; if not, write to the Free Software Foundation, 27.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 27.21 + * 27.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 27.23 + * or visit www.oracle.com if you need additional information or have any 27.24 + * questions. 27.25 + * 27.26 + */ 27.27 + 27.28 +package sun.jvm.hotspot.runtime.sparc; 27.29 + 27.30 +import java.util.*; 27.31 +import sun.jvm.hotspot.asm.sparc.SPARCRegister; 27.32 +import sun.jvm.hotspot.asm.sparc.SPARCRegisters; 27.33 +import sun.jvm.hotspot.debugger.*; 27.34 +import sun.jvm.hotspot.runtime.*; 27.35 +import sun.jvm.hotspot.types.*; 27.36 + 27.37 +public class SPARCRicochetFrame { 27.38 + static { 27.39 + VM.registerVMInitializedObserver(new Observer() { 27.40 + public void update(Observable o, Object data) { 27.41 + initialize(VM.getVM().getTypeDataBase()); 27.42 + } 27.43 + }); 27.44 + } 27.45 + 27.46 + private SPARCFrame frame; 27.47 + 27.48 + private static void initialize(TypeDataBase db) { 27.49 + // Type type = db.lookupType("MethodHandles::RicochetFrame"); 27.50 + 27.51 + } 27.52 + 27.53 + static SPARCRicochetFrame fromFrame(SPARCFrame f) { 27.54 + return new SPARCRicochetFrame(f); 27.55 + } 27.56 + 27.57 + private SPARCRicochetFrame(SPARCFrame f) { 27.58 + frame = f; 27.59 + } 27.60 + 27.61 + private Address registerValue(SPARCRegister reg) { 27.62 + return frame.getSP().addOffsetTo(reg.spOffsetInSavedWindow()).getAddressAt(0); 27.63 + } 27.64 + 27.65 + public Address savedArgsBase() { 27.66 + return registerValue(SPARCRegisters.L4); 27.67 + } 27.68 + public Address exactSenderSP() { 27.69 + return registerValue(SPARCRegisters.I5); 27.70 + } 27.71 + public Address senderLink() { 27.72 + return frame.getSenderSP(); 27.73 + } 27.74 + public Address senderPC() { 27.75 + return frame.getSenderPC(); 27.76 + } 27.77 + public Address extendedSenderSP() { 27.78 + return savedArgsBase(); 27.79 + } 27.80 +}
28.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java Thu Sep 08 16:59:27 2011 -0700 28.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java Fri Sep 09 16:17:16 2011 -0700 28.3 @@ -31,6 +31,7 @@ 28.4 import sun.jvm.hotspot.debugger.amd64.*; 28.5 import sun.jvm.hotspot.runtime.*; 28.6 import sun.jvm.hotspot.runtime.amd64.*; 28.7 +import sun.jvm.hotspot.runtime.x86.*; 28.8 import sun.jvm.hotspot.types.*; 28.9 import sun.jvm.hotspot.utilities.*; 28.10 28.11 @@ -86,14 +87,14 @@ 28.12 } 28.13 Address pc = thread.getLastJavaPC(); 28.14 if ( pc != null ) { 28.15 - return new AMD64Frame(thread.getLastJavaSP(), fp, pc); 28.16 + return new X86Frame(thread.getLastJavaSP(), fp, pc); 28.17 } else { 28.18 - return new AMD64Frame(thread.getLastJavaSP(), fp); 28.19 + return new X86Frame(thread.getLastJavaSP(), fp); 28.20 } 28.21 } 28.22 28.23 public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) { 28.24 - return new AMD64RegisterMap(thread, updateMap); 28.25 + return new X86RegisterMap(thread, updateMap); 28.26 } 28.27 28.28 public Frame getCurrentFrameGuess(JavaThread thread, Address addr) { 28.29 @@ -104,9 +105,9 @@ 28.30 return null; 28.31 } 28.32 if (guesser.getPC() == null) { 28.33 - return new AMD64Frame(guesser.getSP(), guesser.getFP()); 28.34 + return new X86Frame(guesser.getSP(), guesser.getFP()); 28.35 } else { 28.36 - return new AMD64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); 28.37 + return new X86Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); 28.38 } 28.39 } 28.40
29.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java Thu Sep 08 16:59:27 2011 -0700 29.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java Fri Sep 09 16:17:16 2011 -0700 29.3 @@ -25,7 +25,6 @@ 29.4 package sun.jvm.hotspot.runtime.x86; 29.5 29.6 import java.util.*; 29.7 -import sun.jvm.hotspot.asm.x86.*; 29.8 import sun.jvm.hotspot.code.*; 29.9 import sun.jvm.hotspot.compiler.*; 29.10 import sun.jvm.hotspot.debugger.*; 29.11 @@ -62,11 +61,13 @@ 29.12 private static int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET; 29.13 29.14 // Entry frames 29.15 - private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET = 2; 29.16 + private static int ENTRY_FRAME_CALL_WRAPPER_OFFSET; 29.17 29.18 // Native frames 29.19 private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET = 2; 29.20 29.21 + private static VMReg rbp; 29.22 + 29.23 static { 29.24 VM.registerVMInitializedObserver(new Observer() { 29.25 public void update(Observable o, Object data) { 29.26 @@ -76,19 +77,23 @@ 29.27 } 29.28 29.29 private static synchronized void initialize(TypeDataBase db) { 29.30 - if (VM.getVM().isCore()) { 29.31 - INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; 29.32 - } else { 29.33 - INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; 29.34 - INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1; 29.35 - } 29.36 + INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; 29.37 + INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1; 29.38 INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1; 29.39 INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1; 29.40 INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1; 29.41 INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; 29.42 INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; 29.43 + 29.44 + ENTRY_FRAME_CALL_WRAPPER_OFFSET = db.lookupIntConstant("frame::entry_frame_call_wrapper_offset"); 29.45 + if (VM.getVM().getAddressSize() == 4) { 29.46 + rbp = new VMReg(5); 29.47 + } else { 29.48 + rbp = new VMReg(5 << 1); 29.49 + } 29.50 } 29.51 29.52 + 29.53 // an additional field beyond sp and pc: 29.54 Address raw_fp; // frame pointer 29.55 private Address raw_unextendedSP; 29.56 @@ -102,7 +107,7 @@ 29.57 CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); 29.58 if (cb != null && cb.isJavaMethod()) { 29.59 NMethod nm = (NMethod) cb; 29.60 - if (pc.equals(nm.deoptBegin())) { 29.61 + if (pc.equals(nm.deoptHandlerBegin())) { 29.62 if (Assert.ASSERTS_ENABLED) { 29.63 Assert.that(this.getUnextendedSP() != null, "null SP in Java frame"); 29.64 } 29.65 @@ -119,6 +124,7 @@ 29.66 this.raw_unextendedSP = raw_sp; 29.67 this.raw_fp = raw_fp; 29.68 this.pc = pc; 29.69 + adjustUnextendedSP(); 29.70 29.71 // Frame must be fully constructed before this call 29.72 adjustForDeopt(); 29.73 @@ -134,6 +140,7 @@ 29.74 this.raw_unextendedSP = raw_sp; 29.75 this.raw_fp = raw_fp; 29.76 this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); 29.77 + adjustUnextendedSP(); 29.78 29.79 // Frame must be fully constructed before this call 29.80 adjustForDeopt(); 29.81 @@ -144,24 +151,18 @@ 29.82 } 29.83 } 29.84 29.85 - // This constructor should really take the unextended SP as an arg 29.86 - // but then the constructor is ambiguous with constructor that takes 29.87 - // a PC so take an int and convert it. 29.88 - public X86Frame(Address raw_sp, Address raw_fp, long extension) { 29.89 + public X86Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) { 29.90 this.raw_sp = raw_sp; 29.91 - if (raw_sp == null) { 29.92 - this.raw_unextendedSP = null; 29.93 - } else { 29.94 - this.raw_unextendedSP = raw_sp.addOffsetTo(extension); 29.95 - } 29.96 + this.raw_unextendedSP = raw_unextendedSp; 29.97 this.raw_fp = raw_fp; 29.98 - this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); 29.99 + this.pc = pc; 29.100 + adjustUnextendedSP(); 29.101 29.102 // Frame must be fully constructed before this call 29.103 adjustForDeopt(); 29.104 29.105 if (DEBUG) { 29.106 - System.out.println("X86Frame(sp, fp): " + this); 29.107 + System.out.println("X86Frame(sp, unextendedSP, fp, pc): " + this); 29.108 dumpStack(); 29.109 } 29.110 29.111 @@ -172,7 +173,6 @@ 29.112 frame.raw_sp = raw_sp; 29.113 frame.raw_unextendedSP = raw_unextendedSP; 29.114 frame.raw_fp = raw_fp; 29.115 - frame.raw_fp = raw_fp; 29.116 frame.pc = pc; 29.117 frame.deoptimized = deoptimized; 29.118 return frame; 29.119 @@ -269,19 +269,18 @@ 29.120 29.121 if (isEntryFrame()) return senderForEntryFrame(map); 29.122 if (isInterpretedFrame()) return senderForInterpreterFrame(map); 29.123 + if (isRicochetFrame()) return senderForRicochetFrame(map); 29.124 29.125 - if (!VM.getVM().isCore()) { 29.126 - if(cb == null) { 29.127 - cb = VM.getVM().getCodeCache().findBlob(getPC()); 29.128 - } else { 29.129 - if (Assert.ASSERTS_ENABLED) { 29.130 - Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same"); 29.131 - } 29.132 + if(cb == null) { 29.133 + cb = VM.getVM().getCodeCache().findBlob(getPC()); 29.134 + } else { 29.135 + if (Assert.ASSERTS_ENABLED) { 29.136 + Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same"); 29.137 } 29.138 + } 29.139 29.140 - if (cb != null) { 29.141 - return senderForCompiledFrame(map, cb); 29.142 - } 29.143 + if (cb != null) { 29.144 + return senderForCompiledFrame(map, cb); 29.145 } 29.146 29.147 // Must be native-compiled frame, i.e. the marshaling code for native 29.148 @@ -289,7 +288,20 @@ 29.149 return new X86Frame(getSenderSP(), getLink(), getSenderPC()); 29.150 } 29.151 29.152 + private Frame senderForRicochetFrame(X86RegisterMap map) { 29.153 + if (DEBUG) { 29.154 + System.out.println("senderForRicochetFrame"); 29.155 + } 29.156 + X86RicochetFrame f = X86RicochetFrame.fromFrame(this); 29.157 + if (map.getUpdateMap()) 29.158 + updateMapWithSavedLink(map, f.senderLinkAddress()); 29.159 + return new X86Frame(f.extendedSenderSP(), f.exactSenderSP(), f.senderLink(), f.senderPC()); 29.160 + } 29.161 + 29.162 private Frame senderForEntryFrame(X86RegisterMap map) { 29.163 + if (DEBUG) { 29.164 + System.out.println("senderForEntryFrame"); 29.165 + } 29.166 if (Assert.ASSERTS_ENABLED) { 29.167 Assert.that(map != null, "map must be set"); 29.168 } 29.169 @@ -313,7 +325,37 @@ 29.170 return fr; 29.171 } 29.172 29.173 + //------------------------------------------------------------------------------ 29.174 + // frame::adjust_unextended_sp 29.175 + private void adjustUnextendedSP() { 29.176 + // If we are returning to a compiled MethodHandle call site, the 29.177 + // saved_fp will in fact be a saved value of the unextended SP. The 29.178 + // simplest way to tell whether we are returning to such a call site 29.179 + // is as follows: 29.180 + 29.181 + CodeBlob cb = cb(); 29.182 + NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull(); 29.183 + if (senderNm != null) { 29.184 + // If the sender PC is a deoptimization point, get the original 29.185 + // PC. For MethodHandle call site the unextended_sp is stored in 29.186 + // saved_fp. 29.187 + if (senderNm.isDeoptMhEntry(getPC())) { 29.188 + // DEBUG_ONLY(verifyDeoptMhOriginalPc(senderNm, getFP())); 29.189 + raw_unextendedSP = getFP(); 29.190 + } 29.191 + else if (senderNm.isDeoptEntry(getPC())) { 29.192 + // DEBUG_ONLY(verifyDeoptOriginalPc(senderNm, raw_unextendedSp)); 29.193 + } 29.194 + else if (senderNm.isMethodHandleReturn(getPC())) { 29.195 + raw_unextendedSP = getFP(); 29.196 + } 29.197 + } 29.198 + } 29.199 + 29.200 private Frame senderForInterpreterFrame(X86RegisterMap map) { 29.201 + if (DEBUG) { 29.202 + System.out.println("senderForInterpreterFrame"); 29.203 + } 29.204 Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); 29.205 Address sp = addressOfStackSlot(SENDER_SP_OFFSET); 29.206 // We do not need to update the callee-save register mapping because above 29.207 @@ -323,10 +365,21 @@ 29.208 // However c2 no longer uses callee save register for java calls so there 29.209 // are no callee register to find. 29.210 29.211 - return new X86Frame(sp, getLink(), unextendedSP.minus(sp)); 29.212 + if (map.getUpdateMap()) 29.213 + updateMapWithSavedLink(map, addressOfStackSlot(LINK_OFFSET)); 29.214 + 29.215 + return new X86Frame(sp, unextendedSP, getLink(), getSenderPC()); 29.216 + } 29.217 + 29.218 + private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) { 29.219 + map.setLocation(rbp, savedFPAddr); 29.220 } 29.221 29.222 private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) { 29.223 + if (DEBUG) { 29.224 + System.out.println("senderForCompiledFrame"); 29.225 + } 29.226 + 29.227 // 29.228 // NOTE: some of this code is (unfortunately) duplicated in X86CurrentFrameGuess 29.229 // 29.230 @@ -336,41 +389,35 @@ 29.231 } 29.232 29.233 // frame owned by optimizing compiler 29.234 - Address sender_sp = null; 29.235 + if (Assert.ASSERTS_ENABLED) { 29.236 + Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size"); 29.237 + } 29.238 + Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize()); 29.239 29.240 - if (VM.getVM().isClientCompiler()) { 29.241 - sender_sp = addressOfStackSlot(SENDER_SP_OFFSET); 29.242 - } else { 29.243 - if (Assert.ASSERTS_ENABLED) { 29.244 - Assert.that(cb.getFrameSize() >= 0, "Compiled by Compiler1: do not use"); 29.245 + // On Intel the return_address is always the word on the stack 29.246 + Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize()); 29.247 + 29.248 + // This is the saved value of EBP which may or may not really be an FP. 29.249 + // It is only an FP if the sender is an interpreter frame (or C1?). 29.250 + Address savedFPAddr = senderSP.addOffsetTo(- SENDER_SP_OFFSET * VM.getVM().getAddressSize()); 29.251 + 29.252 + if (map.getUpdateMap()) { 29.253 + // Tell GC to use argument oopmaps for some runtime stubs that need it. 29.254 + // For C1, the runtime stub might not have oop maps, so set this flag 29.255 + // outside of update_register_map. 29.256 + map.setIncludeArgumentOops(cb.callerMustGCArguments()); 29.257 + 29.258 + if (cb.getOopMaps() != null) { 29.259 + OopMapSet.updateRegisterMap(this, cb, map, true); 29.260 } 29.261 - sender_sp = getUnextendedSP().addOffsetTo(cb.getFrameSize()); 29.262 + 29.263 + // Since the prolog does the save and restore of EBP there is no oopmap 29.264 + // for it so we must fill in its location as if there was an oopmap entry 29.265 + // since if our caller was compiled code there could be live jvm state in it. 29.266 + updateMapWithSavedLink(map, savedFPAddr); 29.267 } 29.268 29.269 - // On Intel the return_address is always the word on the stack 29.270 - Address sender_pc = sender_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); 29.271 - 29.272 - if (map.getUpdateMap() && cb.getOopMaps() != null) { 29.273 - OopMapSet.updateRegisterMap(this, cb, map, true); 29.274 - } 29.275 - 29.276 - if (VM.getVM().isClientCompiler()) { 29.277 - // Move this here for C1 and collecting oops in arguments (According to Rene) 29.278 - map.setIncludeArgumentOops(cb.callerMustGCArguments(map.getThread())); 29.279 - } 29.280 - 29.281 - Address saved_fp = null; 29.282 - if (VM.getVM().isClientCompiler()) { 29.283 - saved_fp = getFP().getAddressAt(0); 29.284 - } else if (VM.getVM().isServerCompiler() && 29.285 - (VM.getVM().getInterpreter().contains(sender_pc) || 29.286 - VM.getVM().getStubRoutines().returnsToCallStub(sender_pc))) { 29.287 - // C2 prologue saves EBP in the usual place. 29.288 - // however only use it if the sender had link infomration in it. 29.289 - saved_fp = sender_sp.getAddressAt(-2 * VM.getVM().getAddressSize()); 29.290 - } 29.291 - 29.292 - return new X86Frame(sender_sp, saved_fp, sender_pc); 29.293 + return new X86Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC); 29.294 } 29.295 29.296 protected boolean hasSenderPD() { 29.297 @@ -403,14 +450,6 @@ 29.298 29.299 public Address getSenderSP() { return addressOfStackSlot(SENDER_SP_OFFSET); } 29.300 29.301 - public Address compiledArgumentToLocationPD(VMReg reg, RegisterMap regMap, int argSize) { 29.302 - if (VM.getVM().isCore() || VM.getVM().isClientCompiler()) { 29.303 - throw new RuntimeException("Should not reach here"); 29.304 - } 29.305 - 29.306 - return oopMapRegToLocation(reg, regMap); 29.307 - } 29.308 - 29.309 public Address addressOfInterpreterFrameLocals() { 29.310 return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET); 29.311 }
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/x86/X86RicochetFrame.java Fri Sep 09 16:17:16 2011 -0700 30.3 @@ -0,0 +1,81 @@ 30.4 +/* 30.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 30.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 30.7 + * 30.8 + * This code is free software; you can redistribute it and/or modify it 30.9 + * under the terms of the GNU General Public License version 2 only, as 30.10 + * published by the Free Software Foundation. 30.11 + * 30.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 30.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 30.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 30.15 + * version 2 for more details (a copy is included in the LICENSE file that 30.16 + * accompanied this code). 30.17 + * 30.18 + * You should have received a copy of the GNU General Public License version 30.19 + * 2 along with this work; if not, write to the Free Software Foundation, 30.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 30.21 + * 30.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 30.23 + * or visit www.oracle.com if you need additional information or have any 30.24 + * questions. 30.25 + * 30.26 + */ 30.27 + 30.28 +package sun.jvm.hotspot.runtime.x86; 30.29 + 30.30 +import java.util.*; 30.31 +import sun.jvm.hotspot.debugger.*; 30.32 +import sun.jvm.hotspot.runtime.*; 30.33 +import sun.jvm.hotspot.types.*; 30.34 + 30.35 +public class X86RicochetFrame extends VMObject { 30.36 + static { 30.37 + VM.registerVMInitializedObserver(new Observer() { 30.38 + public void update(Observable o, Object data) { 30.39 + initialize(VM.getVM().getTypeDataBase()); 30.40 + } 30.41 + }); 30.42 + } 30.43 + 30.44 + private static void initialize(TypeDataBase db) { 30.45 + Type type = db.lookupType("MethodHandles::RicochetFrame"); 30.46 + 30.47 + senderLinkField = type.getAddressField("_sender_link"); 30.48 + savedArgsBaseField = type.getAddressField("_saved_args_base"); 30.49 + exactSenderSPField = type.getAddressField("_exact_sender_sp"); 30.50 + senderPCField = type.getAddressField("_sender_pc"); 30.51 + } 30.52 + 30.53 + private static AddressField senderLinkField; 30.54 + private static AddressField savedArgsBaseField; 30.55 + private static AddressField exactSenderSPField; 30.56 + private static AddressField senderPCField; 30.57 + 30.58 + static X86RicochetFrame fromFrame(X86Frame f) { 30.59 + return new X86RicochetFrame(f.getFP().addOffsetTo(- senderLinkField.getOffset())); 30.60 + } 30.61 + 30.62 + private X86RicochetFrame(Address addr) { 30.63 + super(addr); 30.64 + } 30.65 + 30.66 + public Address senderLink() { 30.67 + return senderLinkField.getValue(addr); 30.68 + } 30.69 + public Address senderLinkAddress() { 30.70 + return addr.addOffsetTo(senderLinkField.getOffset()); 30.71 + } 30.72 + public Address savedArgsBase() { 30.73 + return savedArgsBaseField.getValue(addr); 30.74 + } 30.75 + public Address extendedSenderSP() { 30.76 + return savedArgsBase(); 30.77 + } 30.78 + public Address exactSenderSP() { 30.79 + return exactSenderSPField.getValue(addr); 30.80 + } 30.81 + public Address senderPC() { 30.82 + return senderPCField.getValue(addr); 30.83 + } 30.84 +}
31.1 --- a/make/hotspot_version Thu Sep 08 16:59:27 2011 -0700 31.2 +++ b/make/hotspot_version Fri Sep 09 16:17:16 2011 -0700 31.3 @@ -35,7 +35,7 @@ 31.4 31.5 HS_MAJOR_VER=22 31.6 HS_MINOR_VER=0 31.7 -HS_BUILD_NUMBER=03 31.8 +HS_BUILD_NUMBER=04 31.9 31.10 JDK_MAJOR_VER=1 31.11 JDK_MINOR_VER=8
32.1 --- a/make/linux/makefiles/mapfile-vers-debug Thu Sep 08 16:59:27 2011 -0700 32.2 +++ b/make/linux/makefiles/mapfile-vers-debug Fri Sep 09 16:17:16 2011 -0700 32.3 @@ -244,24 +244,6 @@ 32.4 JVM_Yield; 32.5 JVM_handle_linux_signal; 32.6 32.7 - # Old reflection routines 32.8 - # These do not need to be present in the product build in JDK 1.4 32.9 - # but their code has not been removed yet because there will not 32.10 - # be a substantial code savings until JVM_InvokeMethod and 32.11 - # JVM_NewInstanceFromConstructor can also be removed; see 32.12 - # reflectionCompat.hpp. 32.13 - JVM_GetClassConstructor; 32.14 - JVM_GetClassConstructors; 32.15 - JVM_GetClassField; 32.16 - JVM_GetClassFields; 32.17 - JVM_GetClassMethod; 32.18 - JVM_GetClassMethods; 32.19 - JVM_GetField; 32.20 - JVM_GetPrimitiveField; 32.21 - JVM_NewInstance; 32.22 - JVM_SetField; 32.23 - JVM_SetPrimitiveField; 32.24 - 32.25 # debug JVM 32.26 JVM_AccessVMBooleanFlag; 32.27 JVM_AccessVMIntFlag;
33.1 --- a/make/linux/makefiles/mapfile-vers-product Thu Sep 08 16:59:27 2011 -0700 33.2 +++ b/make/linux/makefiles/mapfile-vers-product Fri Sep 09 16:17:16 2011 -0700 33.3 @@ -244,24 +244,6 @@ 33.4 JVM_Yield; 33.5 JVM_handle_linux_signal; 33.6 33.7 - # Old reflection routines 33.8 - # These do not need to be present in the product build in JDK 1.4 33.9 - # but their code has not been removed yet because there will not 33.10 - # be a substantial code savings until JVM_InvokeMethod and 33.11 - # JVM_NewInstanceFromConstructor can also be removed; see 33.12 - # reflectionCompat.hpp. 33.13 - JVM_GetClassConstructor; 33.14 - JVM_GetClassConstructors; 33.15 - JVM_GetClassField; 33.16 - JVM_GetClassFields; 33.17 - JVM_GetClassMethod; 33.18 - JVM_GetClassMethods; 33.19 - JVM_GetField; 33.20 - JVM_GetPrimitiveField; 33.21 - JVM_NewInstance; 33.22 - JVM_SetField; 33.23 - JVM_SetPrimitiveField; 33.24 - 33.25 # miscellaneous functions 33.26 jio_fprintf; 33.27 jio_printf;
34.1 --- a/make/solaris/makefiles/debug.make Thu Sep 08 16:59:27 2011 -0700 34.2 +++ b/make/solaris/makefiles/debug.make Fri Sep 09 16:17:16 2011 -0700 34.3 @@ -41,8 +41,7 @@ 34.4 34.5 # Linker mapfiles 34.6 MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ 34.7 - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug \ 34.8 - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct 34.9 + $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug 34.10 34.11 # This mapfile is only needed when compiling with dtrace support, 34.12 # and mustn't be otherwise.
35.1 --- a/make/solaris/makefiles/fastdebug.make Thu Sep 08 16:59:27 2011 -0700 35.2 +++ b/make/solaris/makefiles/fastdebug.make Fri Sep 09 16:17:16 2011 -0700 35.3 @@ -107,8 +107,7 @@ 35.4 35.5 # Linker mapfiles 35.6 MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ 35.7 - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug \ 35.8 - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct 35.9 + $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug 35.10 35.11 # This mapfile is only needed when compiling with dtrace support, 35.12 # and mustn't be otherwise.
36.1 --- a/make/solaris/makefiles/jvmg.make Thu Sep 08 16:59:27 2011 -0700 36.2 +++ b/make/solaris/makefiles/jvmg.make Fri Sep 09 16:17:16 2011 -0700 36.3 @@ -44,8 +44,7 @@ 36.4 36.5 # Linker mapfiles 36.6 MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ 36.7 - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug \ 36.8 - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct 36.9 + $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug 36.10 36.11 # This mapfile is only needed when compiling with dtrace support, 36.12 # and mustn't be otherwise.
37.1 --- a/make/solaris/makefiles/mapfile-vers-nonproduct Thu Sep 08 16:59:27 2011 -0700 37.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 37.3 @@ -1,48 +0,0 @@ 37.4 -# 37.5 - 37.6 -# 37.7 -# Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. 37.8 -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 37.9 -# 37.10 -# This code is free software; you can redistribute it and/or modify it 37.11 -# under the terms of the GNU General Public License version 2 only, as 37.12 -# published by the Free Software Foundation. 37.13 -# 37.14 -# This code is distributed in the hope that it will be useful, but WITHOUT 37.15 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 37.16 -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 37.17 -# version 2 for more details (a copy is included in the LICENSE file that 37.18 -# accompanied this code). 37.19 -# 37.20 -# You should have received a copy of the GNU General Public License version 37.21 -# 2 along with this work; if not, write to the Free Software Foundation, 37.22 -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 37.23 -# 37.24 -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 37.25 -# or visit www.oracle.com if you need additional information or have any 37.26 -# questions. 37.27 -# 37.28 -# 37.29 - 37.30 -# Define public interface. 37.31 - 37.32 -SUNWprivate_1.1 { 37.33 - global: 37.34 - # Old reflection routines 37.35 - # These do not need to be present in the product build in JDK 1.4 37.36 - # but their code has not been removed yet because there will not 37.37 - # be a substantial code savings until JVM_InvokeMethod and 37.38 - # JVM_NewInstanceFromConstructor can also be removed; see 37.39 - # reflectionCompat.hpp. 37.40 - JVM_GetClassConstructor; 37.41 - JVM_GetClassConstructors; 37.42 - JVM_GetClassField; 37.43 - JVM_GetClassFields; 37.44 - JVM_GetClassMethod; 37.45 - JVM_GetClassMethods; 37.46 - JVM_GetField; 37.47 - JVM_GetPrimitiveField; 37.48 - JVM_NewInstance; 37.49 - JVM_SetField; 37.50 - JVM_SetPrimitiveField; 37.51 -};
38.1 --- a/make/solaris/makefiles/optimized.make Thu Sep 08 16:59:27 2011 -0700 38.2 +++ b/make/solaris/makefiles/optimized.make Fri Sep 09 16:17:16 2011 -0700 38.3 @@ -48,9 +48,7 @@ 38.4 CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE) 38.5 38.6 # Linker mapfiles 38.7 -# NOTE: inclusion of nonproduct mapfile not necessary; read it for details 38.8 -MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ 38.9 - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct 38.10 +MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers 38.11 38.12 # This mapfile is only needed when compiling with dtrace support, 38.13 # and mustn't be otherwise.
39.1 --- a/make/solaris/makefiles/product.make Thu Sep 08 16:59:27 2011 -0700 39.2 +++ b/make/solaris/makefiles/product.make Fri Sep 09 16:17:16 2011 -0700 39.3 @@ -58,13 +58,9 @@ 39.4 # to inhibit the effect of the previous line on CFLAGS. 39.5 39.6 # Linker mapfiles 39.7 -# NOTE: inclusion of nonproduct mapfile not necessary; read it for details 39.8 -ifdef USE_GCC 39.9 MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers 39.10 -else 39.11 -MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ 39.12 - $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct 39.13 39.14 +ifndef USE_GCC 39.15 # This mapfile is only needed when compiling with dtrace support, 39.16 # and mustn't be otherwise. 39.17 MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE)
40.1 --- a/src/cpu/sparc/vm/assembler_sparc.cpp Thu Sep 08 16:59:27 2011 -0700 40.2 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp Fri Sep 09 16:17:16 2011 -0700 40.3 @@ -1794,7 +1794,8 @@ 40.4 mov(reg,O0); // Move arg into O0; arg might be in O7 which is about to be crushed 40.5 stx(O7,SP,frame::register_save_words*wordSize+STACK_BIAS+7*8); 40.6 40.7 - set((intptr_t)real_msg, O1); 40.8 + // Size of set() should stay the same 40.9 + patchable_set((intptr_t)real_msg, O1); 40.10 // Load address to call to into O7 40.11 load_ptr_contents(a, O7); 40.12 // Register call to verify_oop_subroutine 40.13 @@ -1831,7 +1832,8 @@ 40.14 ld_ptr(addr.base(), addr.disp() + 8*8, O0); // Load arg into O0; arg might be in O7 which is about to be crushed 40.15 stx(O7,SP,frame::register_save_words*wordSize+STACK_BIAS+7*8); 40.16 40.17 - set((intptr_t)real_msg, O1); 40.18 + // Size of set() should stay the same 40.19 + patchable_set((intptr_t)real_msg, O1); 40.20 // Load address to call to into O7 40.21 load_ptr_contents(a, O7); 40.22 // Register call to verify_oop_subroutine 40.23 @@ -1976,7 +1978,8 @@ 40.24 save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); 40.25 40.26 // stop_subroutine expects message pointer in I1. 40.27 - set((intptr_t)msg, O1); 40.28 + // Size of set() should stay the same 40.29 + patchable_set((intptr_t)msg, O1); 40.30 40.31 // factor long stop-sequence into subroutine to save space 40.32 assert(StubRoutines::Sparc::stop_subroutine_entry_address(), "hasn't been generated yet"); 40.33 @@ -1998,7 +2001,8 @@ 40.34 save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); 40.35 RegistersForDebugging::save_registers(this); 40.36 mov(O0, L0); 40.37 - set((intptr_t)msg, O0); 40.38 + // Size of set() should stay the same 40.39 + patchable_set((intptr_t)msg, O0); 40.40 call( CAST_FROM_FN_PTR(address, warning) ); 40.41 delayed()->nop(); 40.42 // ret(); 40.43 @@ -2161,29 +2165,6 @@ 40.44 #endif 40.45 } 40.46 40.47 -void MacroAssembler::br_on_reg_cond( RCondition rc, bool a, Predict p, 40.48 - Register s1, address d, 40.49 - relocInfo::relocType rt ) { 40.50 - assert_not_delayed(); 40.51 - if (VM_Version::v9_instructions_work()) { 40.52 - bpr(rc, a, p, s1, d, rt); 40.53 - } else { 40.54 - tst(s1); 40.55 - br(reg_cond_to_cc_cond(rc), a, p, d, rt); 40.56 - } 40.57 -} 40.58 - 40.59 -void MacroAssembler::br_on_reg_cond( RCondition rc, bool a, Predict p, 40.60 - Register s1, Label& L ) { 40.61 - assert_not_delayed(); 40.62 - if (VM_Version::v9_instructions_work()) { 40.63 - bpr(rc, a, p, s1, L); 40.64 - } else { 40.65 - tst(s1); 40.66 - br(reg_cond_to_cc_cond(rc), a, p, L); 40.67 - } 40.68 -} 40.69 - 40.70 // Compare registers and branch with nop in delay slot or cbcond without delay slot. 40.71 40.72 // Compare integer (32 bit) values (icc only). 40.73 @@ -4340,22 +4321,29 @@ 40.74 } else { 40.75 pre_val = O0; 40.76 } 40.77 + 40.78 int satb_q_index_byte_offset = 40.79 in_bytes(JavaThread::satb_mark_queue_offset() + 40.80 PtrQueue::byte_offset_of_index()); 40.81 + 40.82 int satb_q_buf_byte_offset = 40.83 in_bytes(JavaThread::satb_mark_queue_offset() + 40.84 PtrQueue::byte_offset_of_buf()); 40.85 + 40.86 assert(in_bytes(PtrQueue::byte_width_of_index()) == sizeof(intptr_t) && 40.87 in_bytes(PtrQueue::byte_width_of_buf()) == sizeof(intptr_t), 40.88 "check sizes in assembly below"); 40.89 40.90 __ bind(restart); 40.91 + 40.92 + // Load the index into the SATB buffer. PtrQueue::_index is a size_t 40.93 + // so ld_ptr is appropriate. 40.94 __ ld_ptr(G2_thread, satb_q_index_byte_offset, L0); 40.95 40.96 - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pn, L0, refill); 40.97 - // If the branch is taken, no harm in executing this in the delay slot. 40.98 - __ delayed()->ld_ptr(G2_thread, satb_q_buf_byte_offset, L1); 40.99 + // index == 0? 40.100 + __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); 40.101 + 40.102 + __ ld_ptr(G2_thread, satb_q_buf_byte_offset, L1); 40.103 __ sub(L0, oopSize, L0); 40.104 40.105 __ st_ptr(pre_val, L1, L0); // [_buf + index] := I0 40.106 @@ -4466,9 +4454,8 @@ 40.107 tmp); 40.108 } 40.109 40.110 - // Check on whether to annul. 40.111 - br_on_reg_cond(rc_z, /*annul*/false, Assembler::pt, tmp, filtered); 40.112 - delayed()->nop(); 40.113 + // Is marking active? 40.114 + cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); 40.115 40.116 // Do we need to load the previous value? 40.117 if (obj != noreg) { 40.118 @@ -4490,9 +4477,7 @@ 40.119 assert(pre_val != noreg, "must have a real register"); 40.120 40.121 // Is the previous value null? 40.122 - // Check on whether to annul. 40.123 - br_on_reg_cond(rc_z, /*annul*/false, Assembler::pt, pre_val, filtered); 40.124 - delayed()->nop(); 40.125 + cmp_and_brx_short(pre_val, G0, Assembler::equal, Assembler::pt, filtered); 40.126 40.127 // OK, it's not filtered, so we'll need to call enqueue. In the normal 40.128 // case, pre_val will be a scratch G-reg, but there are some cases in 40.129 @@ -4519,39 +4504,6 @@ 40.130 bind(filtered); 40.131 } 40.132 40.133 -static jint num_ct_writes = 0; 40.134 -static jint num_ct_writes_filtered_in_hr = 0; 40.135 -static jint num_ct_writes_filtered_null = 0; 40.136 -static G1CollectedHeap* g1 = NULL; 40.137 - 40.138 -static Thread* count_ct_writes(void* filter_val, void* new_val) { 40.139 - Atomic::inc(&num_ct_writes); 40.140 - if (filter_val == NULL) { 40.141 - Atomic::inc(&num_ct_writes_filtered_in_hr); 40.142 - } else if (new_val == NULL) { 40.143 - Atomic::inc(&num_ct_writes_filtered_null); 40.144 - } else { 40.145 - if (g1 == NULL) { 40.146 - g1 = G1CollectedHeap::heap(); 40.147 - } 40.148 - } 40.149 - if ((num_ct_writes % 1000000) == 0) { 40.150 - jint num_ct_writes_filtered = 40.151 - num_ct_writes_filtered_in_hr + 40.152 - num_ct_writes_filtered_null; 40.153 - 40.154 - tty->print_cr("%d potential CT writes: %5.2f%% filtered\n" 40.155 - " (%5.2f%% intra-HR, %5.2f%% null).", 40.156 - num_ct_writes, 40.157 - 100.0*(float)num_ct_writes_filtered/(float)num_ct_writes, 40.158 - 100.0*(float)num_ct_writes_filtered_in_hr/ 40.159 - (float)num_ct_writes, 40.160 - 100.0*(float)num_ct_writes_filtered_null/ 40.161 - (float)num_ct_writes); 40.162 - } 40.163 - return Thread::current(); 40.164 -} 40.165 - 40.166 static address dirty_card_log_enqueue = 0; 40.167 static u_char* dirty_card_log_enqueue_end = 0; 40.168 40.169 @@ -4574,11 +4526,8 @@ 40.170 __ set(addrlit, O1); // O1 := <card table base> 40.171 __ ldub(O0, O1, O2); // O2 := [O0 + O1] 40.172 40.173 - __ br_on_reg_cond(Assembler::rc_nz, /*annul*/false, Assembler::pt, 40.174 - O2, not_already_dirty); 40.175 - // Get O1 + O2 into a reg by itself -- useful in the take-the-branch 40.176 - // case, harmless if not. 40.177 - __ delayed()->add(O0, O1, O3); 40.178 + assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code"); 40.179 + __ cmp_and_br_short(O2, G0, Assembler::notEqual, Assembler::pt, not_already_dirty); 40.180 40.181 // We didn't take the branch, so we're already dirty: return. 40.182 // Use return-from-leaf 40.183 @@ -4587,8 +4536,13 @@ 40.184 40.185 // Not dirty. 40.186 __ bind(not_already_dirty); 40.187 + 40.188 + // Get O0 + O1 into a reg by itself 40.189 + __ add(O0, O1, O3); 40.190 + 40.191 // First, dirty it. 40.192 __ stb(G0, O3, G0); // [cardPtr] := 0 (i.e., dirty). 40.193 + 40.194 int dirty_card_q_index_byte_offset = 40.195 in_bytes(JavaThread::dirty_card_queue_offset() + 40.196 PtrQueue::byte_offset_of_index()); 40.197 @@ -4596,12 +4550,15 @@ 40.198 in_bytes(JavaThread::dirty_card_queue_offset() + 40.199 PtrQueue::byte_offset_of_buf()); 40.200 __ bind(restart); 40.201 + 40.202 + // Load the index into the update buffer. PtrQueue::_index is 40.203 + // a size_t so ld_ptr is appropriate here. 40.204 __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, L0); 40.205 40.206 - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pn, 40.207 - L0, refill); 40.208 - // If the branch is taken, no harm in executing this in the delay slot. 40.209 - __ delayed()->ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1); 40.210 + // index == 0? 40.211 + __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); 40.212 + 40.213 + __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1); 40.214 __ sub(L0, oopSize, L0); 40.215 40.216 __ st_ptr(O3, L1, L0); // [_buf + index] := I0 40.217 @@ -4664,6 +4621,7 @@ 40.218 G1SATBCardTableModRefBS* bs = (G1SATBCardTableModRefBS*) Universe::heap()->barrier_set(); 40.219 assert(bs->kind() == BarrierSet::G1SATBCT || 40.220 bs->kind() == BarrierSet::G1SATBCTLogging, "wrong barrier"); 40.221 + 40.222 if (G1RSBarrierRegionFilter) { 40.223 xor3(store_addr, new_val, tmp); 40.224 #ifdef _LP64 40.225 @@ -4672,33 +4630,8 @@ 40.226 srl(tmp, HeapRegion::LogOfHRGrainBytes, tmp); 40.227 #endif 40.228 40.229 - if (G1PrintCTFilterStats) { 40.230 - guarantee(tmp->is_global(), "Or stats won't work..."); 40.231 - // This is a sleazy hack: I'm temporarily hijacking G2, which I 40.232 - // promise to restore. 40.233 - mov(new_val, G2); 40.234 - save_frame(0); 40.235 - mov(tmp, O0); 40.236 - mov(G2, O1); 40.237 - // Save G-regs that target may use. 40.238 - mov(G1, L1); 40.239 - mov(G2, L2); 40.240 - mov(G3, L3); 40.241 - mov(G4, L4); 40.242 - mov(G5, L5); 40.243 - call(CAST_FROM_FN_PTR(address, &count_ct_writes)); 40.244 - delayed()->nop(); 40.245 - mov(O0, G2); 40.246 - // Restore G-regs that target may have used. 40.247 - mov(L1, G1); 40.248 - mov(L3, G3); 40.249 - mov(L4, G4); 40.250 - mov(L5, G5); 40.251 - restore(G0, G0, G0); 40.252 - } 40.253 - // XXX Should I predict this taken or not? Does it mattern? 40.254 - br_on_reg_cond(rc_z, /*annul*/false, Assembler::pt, tmp, filtered); 40.255 - delayed()->nop(); 40.256 + // XXX Should I predict this taken or not? Does it matter? 40.257 + cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); 40.258 } 40.259 40.260 // If the "store_addr" register is an "in" or "local" register, move it to 40.261 @@ -4723,7 +4656,6 @@ 40.262 restore(); 40.263 40.264 bind(filtered); 40.265 - 40.266 } 40.267 40.268 #endif // SERIALGC 40.269 @@ -4973,3 +4905,65 @@ 40.270 // Caller should set it: 40.271 // add(G0, 1, result); // equals 40.272 } 40.273 + 40.274 +// Use BIS for zeroing (count is in bytes). 40.275 +void MacroAssembler::bis_zeroing(Register to, Register count, Register temp, Label& Ldone) { 40.276 + assert(UseBlockZeroing && VM_Version::has_block_zeroing(), "only works with BIS zeroing"); 40.277 + Register end = count; 40.278 + int cache_line_size = VM_Version::prefetch_data_size(); 40.279 + // Minimum count when BIS zeroing can be used since 40.280 + // it needs membar which is expensive. 40.281 + int block_zero_size = MAX2(cache_line_size*3, (int)BlockZeroingLowLimit); 40.282 + 40.283 + Label small_loop; 40.284 + // Check if count is negative (dead code) or zero. 40.285 + // Note, count uses 64bit in 64 bit VM. 40.286 + cmp_and_brx_short(count, 0, Assembler::lessEqual, Assembler::pn, Ldone); 40.287 + 40.288 + // Use BIS zeroing only for big arrays since it requires membar. 40.289 + if (Assembler::is_simm13(block_zero_size)) { // < 4096 40.290 + cmp(count, block_zero_size); 40.291 + } else { 40.292 + set(block_zero_size, temp); 40.293 + cmp(count, temp); 40.294 + } 40.295 + br(Assembler::lessUnsigned, false, Assembler::pt, small_loop); 40.296 + delayed()->add(to, count, end); 40.297 + 40.298 + // Note: size is >= three (32 bytes) cache lines. 40.299 + 40.300 + // Clean the beginning of space up to next cache line. 40.301 + for (int offs = 0; offs < cache_line_size; offs += 8) { 40.302 + stx(G0, to, offs); 40.303 + } 40.304 + 40.305 + // align to next cache line 40.306 + add(to, cache_line_size, to); 40.307 + and3(to, -cache_line_size, to); 40.308 + 40.309 + // Note: size left >= two (32 bytes) cache lines. 40.310 + 40.311 + // BIS should not be used to zero tail (64 bytes) 40.312 + // to avoid zeroing a header of the following object. 40.313 + sub(end, (cache_line_size*2)-8, end); 40.314 + 40.315 + Label bis_loop; 40.316 + bind(bis_loop); 40.317 + stxa(G0, to, G0, Assembler::ASI_ST_BLKINIT_PRIMARY); 40.318 + add(to, cache_line_size, to); 40.319 + cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, bis_loop); 40.320 + 40.321 + // BIS needs membar. 40.322 + membar(Assembler::StoreLoad); 40.323 + 40.324 + add(end, (cache_line_size*2)-8, end); // restore end 40.325 + cmp_and_brx_short(to, end, Assembler::greaterEqualUnsigned, Assembler::pn, Ldone); 40.326 + 40.327 + // Clean the tail. 40.328 + bind(small_loop); 40.329 + stx(G0, to, 0); 40.330 + add(to, 8, to); 40.331 + cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, small_loop); 40.332 + nop(); // Separate short branches 40.333 +} 40.334 +
41.1 --- a/src/cpu/sparc/vm/assembler_sparc.hpp Thu Sep 08 16:59:27 2011 -0700 41.2 +++ b/src/cpu/sparc/vm/assembler_sparc.hpp Fri Sep 09 16:17:16 2011 -0700 41.3 @@ -885,8 +885,9 @@ 41.4 } 41.5 41.6 enum ASIs { // page 72, v9 41.7 - ASI_PRIMARY = 0x80, 41.8 - ASI_PRIMARY_LITTLE = 0x88, 41.9 + ASI_PRIMARY = 0x80, 41.10 + ASI_PRIMARY_NOFAULT = 0x82, 41.11 + ASI_PRIMARY_LITTLE = 0x88, 41.12 // Block initializing store 41.13 ASI_ST_BLKINIT_PRIMARY = 0xE2, 41.14 // Most-Recently-Used (MRU) BIS variant 41.15 @@ -1786,9 +1787,12 @@ 41.16 rs1(s) | 41.17 op3(wrreg_op3) | 41.18 u_field(2, 29, 25) | 41.19 - u_field(1, 13, 13) | 41.20 + immed(true) | 41.21 simm(simm13a, 13)); } 41.22 - inline void wrasi( Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(3, 29, 25)); } 41.23 + inline void wrasi(Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(3, 29, 25)); } 41.24 + // wrasi(d, imm) stores (d xor imm) to asi 41.25 + inline void wrasi(Register d, int simm13a) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | 41.26 + u_field(3, 29, 25) | immed(true) | simm(simm13a, 13)); } 41.27 inline void wrfprs( Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(6, 29, 25)); } 41.28 41.29 41.30 @@ -1940,12 +1944,6 @@ 41.31 void br_null ( Register s1, bool a, Predict p, Label& L ); 41.32 void br_notnull( Register s1, bool a, Predict p, Label& L ); 41.33 41.34 - // These versions will do the most efficient thing on v8 and v9. Perhaps 41.35 - // this is what the routine above was meant to do, but it didn't (and 41.36 - // didn't cover both target address kinds.) 41.37 - void br_on_reg_cond( RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt = relocInfo::none ); 41.38 - void br_on_reg_cond( RCondition c, bool a, Predict p, Register s1, Label& L); 41.39 - 41.40 // 41.41 // Compare registers and branch with nop in delay slot or cbcond without delay slot. 41.42 // 41.43 @@ -2631,6 +2629,8 @@ 41.44 void char_arrays_equals(Register ary1, Register ary2, 41.45 Register limit, Register result, 41.46 Register chr1, Register chr2, Label& Ldone); 41.47 + // Use BIS for zeroing 41.48 + void bis_zeroing(Register to, Register count, Register temp, Label& Ldone); 41.49 41.50 #undef VIRTUAL 41.51
42.1 --- a/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Thu Sep 08 16:59:27 2011 -0700 42.2 +++ b/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Fri Sep 09 16:17:16 2011 -0700 42.3 @@ -421,8 +421,7 @@ 42.4 } 42.5 42.6 if (__ is_in_wdisp16_range(_continuation)) { 42.7 - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, 42.8 - pre_val_reg, _continuation); 42.9 + __ br_null(pre_val_reg, /*annul*/false, Assembler::pt, _continuation); 42.10 } else { 42.11 __ cmp(pre_val_reg, G0); 42.12 __ brx(Assembler::equal, false, Assembler::pn, _continuation); 42.13 @@ -458,8 +457,7 @@ 42.14 // The original src operand was not a constant. 42.15 // Generate src == null? 42.16 if (__ is_in_wdisp16_range(_continuation)) { 42.17 - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, 42.18 - src_reg, _continuation); 42.19 + __ br_null(src_reg, /*annul*/false, Assembler::pt, _continuation); 42.20 } else { 42.21 __ cmp(src_reg, G0); 42.22 __ brx(Assembler::equal, false, Assembler::pt, _continuation); 42.23 @@ -476,13 +474,9 @@ 42.24 Address ref_type_adr(tmp_reg, instanceKlass::reference_type_offset_in_bytes() + sizeof(oopDesc)); 42.25 __ ld(ref_type_adr, tmp_reg); 42.26 42.27 - if (__ is_in_wdisp16_range(_continuation)) { 42.28 - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, 42.29 - tmp_reg, _continuation); 42.30 - } else { 42.31 - __ cmp(tmp_reg, G0); 42.32 - __ brx(Assembler::equal, false, Assembler::pt, _continuation); 42.33 - } 42.34 + // _reference_type field is of type ReferenceType (enum) 42.35 + assert(REF_NONE == 0, "check this code"); 42.36 + __ cmp_zero_and_br(Assembler::equal, tmp_reg, _continuation, /*annul*/false, Assembler::pt); 42.37 __ delayed()->nop(); 42.38 42.39 // Is marking active? 42.40 @@ -498,13 +492,8 @@ 42.41 assert(in_bytes(PtrQueue::byte_width_of_active()) == 1, "Assumption"); 42.42 __ ldsb(in_progress, tmp_reg); 42.43 } 42.44 - if (__ is_in_wdisp16_range(_continuation)) { 42.45 - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, 42.46 - tmp_reg, _continuation); 42.47 - } else { 42.48 - __ cmp(tmp_reg, G0); 42.49 - __ brx(Assembler::equal, false, Assembler::pt, _continuation); 42.50 - } 42.51 + 42.52 + __ cmp_zero_and_br(Assembler::equal, tmp_reg, _continuation, /*annul*/false, Assembler::pt); 42.53 __ delayed()->nop(); 42.54 42.55 // val == null? 42.56 @@ -512,8 +501,7 @@ 42.57 Register val_reg = val()->as_register(); 42.58 42.59 if (__ is_in_wdisp16_range(_continuation)) { 42.60 - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, 42.61 - val_reg, _continuation); 42.62 + __ br_null(val_reg, /*annul*/false, Assembler::pt, _continuation); 42.63 } else { 42.64 __ cmp(val_reg, G0); 42.65 __ brx(Assembler::equal, false, Assembler::pt, _continuation); 42.66 @@ -542,9 +530,9 @@ 42.67 assert(new_val()->is_register(), "Precondition."); 42.68 Register addr_reg = addr()->as_pointer_register(); 42.69 Register new_val_reg = new_val()->as_register(); 42.70 + 42.71 if (__ is_in_wdisp16_range(_continuation)) { 42.72 - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt, 42.73 - new_val_reg, _continuation); 42.74 + __ br_null(new_val_reg, /*annul*/false, Assembler::pt, _continuation); 42.75 } else { 42.76 __ cmp(new_val_reg, G0); 42.77 __ brx(Assembler::equal, false, Assembler::pn, _continuation);
43.1 --- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Sep 08 16:59:27 2011 -0700 43.2 +++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Fri Sep 09 16:17:16 2011 -0700 43.3 @@ -142,11 +142,6 @@ 43.4 } 43.5 43.6 43.7 -LIR_Opr LIR_Assembler::incomingReceiverOpr() { 43.8 - return FrameMap::I0_oop_opr; 43.9 -} 43.10 - 43.11 - 43.12 LIR_Opr LIR_Assembler::osrBufferPointer() { 43.13 return FrameMap::I0_opr; 43.14 }
44.1 --- a/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Thu Sep 08 16:59:27 2011 -0700 44.2 +++ b/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Fri Sep 09 16:17:16 2011 -0700 44.3 @@ -782,13 +782,6 @@ 44.4 } 44.5 break; 44.6 44.7 - case jvmti_exception_throw_id: 44.8 - { // Oexception : exception 44.9 - __ set_info("jvmti_exception_throw", dont_gc_arguments); 44.10 - oop_maps = generate_stub_call(sasm, noreg, CAST_FROM_FN_PTR(address, Runtime1::post_jvmti_exception_throw), I0); 44.11 - } 44.12 - break; 44.13 - 44.14 case dtrace_object_alloc_id: 44.15 { // O0: object 44.16 __ set_info("dtrace_object_alloc", dont_gc_arguments); 44.17 @@ -834,14 +827,16 @@ 44.18 int satb_q_buf_byte_offset = 44.19 in_bytes(JavaThread::satb_mark_queue_offset() + 44.20 PtrQueue::byte_offset_of_buf()); 44.21 + 44.22 __ bind(restart); 44.23 + // Load the index into the SATB buffer. PtrQueue::_index is a 44.24 + // size_t so ld_ptr is appropriate 44.25 __ ld_ptr(G2_thread, satb_q_index_byte_offset, tmp); 44.26 44.27 - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, 44.28 - Assembler::pn, tmp, refill); 44.29 + // index == 0? 44.30 + __ cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pn, refill); 44.31 44.32 - // If the branch is taken, no harm in executing this in the delay slot. 44.33 - __ delayed()->ld_ptr(G2_thread, satb_q_buf_byte_offset, tmp2); 44.34 + __ ld_ptr(G2_thread, satb_q_buf_byte_offset, tmp2); 44.35 __ sub(tmp, oopSize, tmp); 44.36 44.37 __ st_ptr(pre_val, tmp2, tmp); // [_buf + index] := <address_of_card> 44.38 @@ -901,11 +896,8 @@ 44.39 __ set(rs, cardtable); // cardtable := <card table base> 44.40 __ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable] 44.41 44.42 - __ br_on_reg_cond(Assembler::rc_nz, /*annul*/false, Assembler::pt, 44.43 - tmp, not_already_dirty); 44.44 - // Get cardtable + tmp into a reg by itself -- useful in the take-the-branch 44.45 - // case, harmless if not. 44.46 - __ delayed()->add(addr, cardtable, tmp2); 44.47 + assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code"); 44.48 + __ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, not_already_dirty); 44.49 44.50 // We didn't take the branch, so we're already dirty: return. 44.51 // Use return-from-leaf 44.52 @@ -914,6 +906,10 @@ 44.53 44.54 // Not dirty. 44.55 __ bind(not_already_dirty); 44.56 + 44.57 + // Get cardtable + tmp into a reg by itself 44.58 + __ add(addr, cardtable, tmp2); 44.59 + 44.60 // First, dirty it. 44.61 __ stb(G0, tmp2, 0); // [cardPtr] := 0 (i.e., dirty). 44.62 44.63 @@ -929,13 +925,17 @@ 44.64 int dirty_card_q_buf_byte_offset = 44.65 in_bytes(JavaThread::dirty_card_queue_offset() + 44.66 PtrQueue::byte_offset_of_buf()); 44.67 + 44.68 __ bind(restart); 44.69 + 44.70 + // Get the index into the update buffer. PtrQueue::_index is 44.71 + // a size_t so ld_ptr is appropriate here. 44.72 __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, tmp3); 44.73 44.74 - __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pn, 44.75 - tmp3, refill); 44.76 - // If the branch is taken, no harm in executing this in the delay slot. 44.77 - __ delayed()->ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, tmp4); 44.78 + // index == 0? 44.79 + __ cmp_and_brx_short(tmp3, G0, Assembler::equal, Assembler::pn, refill); 44.80 + 44.81 + __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, tmp4); 44.82 __ sub(tmp3, oopSize, tmp3); 44.83 44.84 __ st_ptr(tmp2, tmp4, tmp3); // [_buf + index] := <address_of_card>
45.1 --- a/src/cpu/sparc/vm/copy_sparc.hpp Thu Sep 08 16:59:27 2011 -0700 45.2 +++ b/src/cpu/sparc/vm/copy_sparc.hpp Fri Sep 09 16:17:16 2011 -0700 45.3 @@ -156,9 +156,16 @@ 45.4 #endif // _LP64 45.5 } 45.6 45.7 +typedef void (*_zero_Fn)(HeapWord* to, size_t count); 45.8 + 45.9 static void pd_fill_to_aligned_words(HeapWord* tohw, size_t count, juint value) { 45.10 assert(MinObjAlignmentInBytes >= BytesPerLong, "need alternate implementation"); 45.11 45.12 + if (value == 0 && UseBlockZeroing && 45.13 + (count > (BlockZeroingLowLimit >> LogHeapWordSize))) { 45.14 + // Call it only when block zeroing is used 45.15 + ((_zero_Fn)StubRoutines::zero_aligned_words())(tohw, count); 45.16 + } else { 45.17 julong* to = (julong*)tohw; 45.18 julong v = ((julong)value << 32) | value; 45.19 // If count is odd, odd will be equal to 1 on 32-bit platform 45.20 @@ -176,6 +183,7 @@ 45.21 *((juint*)to) = value; 45.22 45.23 } 45.24 + } 45.25 } 45.26 45.27 static void pd_fill_to_bytes(void* to, size_t count, jubyte value) {
46.1 --- a/src/cpu/sparc/vm/frame_sparc.hpp Thu Sep 08 16:59:27 2011 -0700 46.2 +++ b/src/cpu/sparc/vm/frame_sparc.hpp Fri Sep 09 16:17:16 2011 -0700 46.3 @@ -259,13 +259,8 @@ 46.4 }; 46.5 #endif /* CC_INTERP */ 46.6 46.7 - // the compiler frame has many of the same fields as the interpreter frame 46.8 - // %%%%% factor out declarations of the shared fields 46.9 enum compiler_frame_fixed_locals { 46.10 - compiler_frame_d_scratch_fp_offset = -2, 46.11 - compiler_frame_vm_locals_fp_offset = -2, // should be same as above 46.12 - 46.13 - compiler_frame_vm_local_words = -compiler_frame_vm_locals_fp_offset 46.14 + compiler_frame_vm_locals_fp_offset = -2 46.15 }; 46.16 46.17 private: 46.18 @@ -283,9 +278,6 @@ 46.19 46.20 inline void interpreter_frame_set_tos_address(intptr_t* x); 46.21 46.22 - 46.23 - // %%%%% Another idea: instead of defining 3 fns per item, just define one returning a ref 46.24 - 46.25 // monitors: 46.26 46.27 // next two fns read and write Lmonitors value, 46.28 @@ -298,22 +290,8 @@ 46.29 return ((interpreterState)sp_at(interpreter_state_ptr_offset)); 46.30 } 46.31 46.32 - 46.33 #endif /* CC_INTERP */ 46.34 46.35 - 46.36 - 46.37 - // Compiled frames 46.38 - 46.39 public: 46.40 - // Tells if this register can hold 64 bits on V9 (really, V8+). 46.41 - static bool holds_a_doubleword(Register reg) { 46.42 -#ifdef _LP64 46.43 - // return true; 46.44 - return reg->is_out() || reg->is_global(); 46.45 -#else 46.46 - return reg->is_out() || reg->is_global(); 46.47 -#endif 46.48 - } 46.49 46.50 #endif // CPU_SPARC_VM_FRAME_SPARC_HPP
47.1 --- a/src/cpu/sparc/vm/methodHandles_sparc.cpp Thu Sep 08 16:59:27 2011 -0700 47.2 +++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp Fri Sep 09 16:17:16 2011 -0700 47.3 @@ -1262,6 +1262,15 @@ 47.4 } 47.5 break; 47.6 47.7 + case _adapter_opt_profiling: 47.8 + if (java_lang_invoke_CountingMethodHandle::vmcount_offset_in_bytes() != 0) { 47.9 + Address G3_mh_vmcount(G3_method_handle, java_lang_invoke_CountingMethodHandle::vmcount_offset_in_bytes()); 47.10 + __ ld(G3_mh_vmcount, O1_scratch); 47.11 + __ add(O1_scratch, 1, O1_scratch); 47.12 + __ st(O1_scratch, G3_mh_vmcount); 47.13 + } 47.14 + // fall through 47.15 + 47.16 case _adapter_retype_only: 47.17 case _adapter_retype_raw: 47.18 // Immediately jump to the next MH layer:
48.1 --- a/src/cpu/sparc/vm/sparc.ad Thu Sep 08 16:59:27 2011 -0700 48.2 +++ b/src/cpu/sparc/vm/sparc.ad Fri Sep 09 16:17:16 2011 -0700 48.3 @@ -460,6 +460,8 @@ 48.4 // Must be visible to the DFA in dfa_sparc.cpp 48.5 extern bool can_branch_register( Node *bol, Node *cmp ); 48.6 48.7 +extern bool use_block_zeroing(Node* count); 48.8 + 48.9 // Macros to extract hi & lo halves from a long pair. 48.10 // G0 is not part of any long pair, so assert on that. 48.11 // Prevents accidentally using G1 instead of G0. 48.12 @@ -521,6 +523,12 @@ 48.13 return false; 48.14 } 48.15 48.16 +bool use_block_zeroing(Node* count) { 48.17 + // Use BIS for zeroing if count is not constant 48.18 + // or it is >= BlockZeroingLowLimit. 48.19 + return UseBlockZeroing && (count->find_intptr_t_con(BlockZeroingLowLimit) >= BlockZeroingLowLimit); 48.20 +} 48.21 + 48.22 // **************************************************************************** 48.23 48.24 // REQUIRED FUNCTIONALITY 48.25 @@ -832,6 +840,7 @@ 48.26 !(n->ideal_Opcode()==Op_ConvI2D && ld_op==Op_LoadF) && 48.27 !(n->ideal_Opcode()==Op_PrefetchRead && ld_op==Op_LoadI) && 48.28 !(n->ideal_Opcode()==Op_PrefetchWrite && ld_op==Op_LoadI) && 48.29 + !(n->ideal_Opcode()==Op_PrefetchAllocation && ld_op==Op_LoadI) && 48.30 !(n->ideal_Opcode()==Op_Load2I && ld_op==Op_LoadD) && 48.31 !(n->ideal_Opcode()==Op_Load4C && ld_op==Op_LoadD) && 48.32 !(n->ideal_Opcode()==Op_Load4S && ld_op==Op_LoadD) && 48.33 @@ -2810,25 +2819,6 @@ 48.34 __ float_cmp( $primary, -1, Fsrc1, Fsrc2, Rdst); 48.35 %} 48.36 48.37 - // Compiler ensures base is doubleword aligned and cnt is count of doublewords 48.38 - enc_class enc_Clear_Array(iRegX cnt, iRegP base, iRegX temp) %{ 48.39 - MacroAssembler _masm(&cbuf); 48.40 - Register nof_bytes_arg = reg_to_register_object($cnt$$reg); 48.41 - Register nof_bytes_tmp = reg_to_register_object($temp$$reg); 48.42 - Register base_pointer_arg = reg_to_register_object($base$$reg); 48.43 - 48.44 - Label loop; 48.45 - __ mov(nof_bytes_arg, nof_bytes_tmp); 48.46 - 48.47 - // Loop and clear, walking backwards through the array. 48.48 - // nof_bytes_tmp (if >0) is always the number of bytes to zero 48.49 - __ bind(loop); 48.50 - __ deccc(nof_bytes_tmp, 8); 48.51 - __ br(Assembler::greaterEqual, true, Assembler::pt, loop); 48.52 - __ delayed()-> stx(G0, base_pointer_arg, nof_bytes_tmp); 48.53 - // %%%% this mini-loop must not cross a cache boundary! 48.54 - %} 48.55 - 48.56 48.57 enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result) %{ 48.58 Label Ldone, Lloop; 48.59 @@ -10257,9 +10247,9 @@ 48.60 ins_pipe(long_memory_op); 48.61 %} 48.62 48.63 -// Count and Base registers are fixed because the allocator cannot 48.64 -// kill unknown registers. The encodings are generic. 48.65 +// The encodings are generic. 48.66 instruct clear_array(iRegX cnt, iRegP base, iRegX temp, Universe dummy, flagsReg ccr) %{ 48.67 + predicate(!use_block_zeroing(n->in(2)) ); 48.68 match(Set dummy (ClearArray cnt base)); 48.69 effect(TEMP temp, KILL ccr); 48.70 ins_cost(300); 48.71 @@ -10267,7 +10257,71 @@ 48.72 "loop: SUBcc $temp,8,$temp\t! Count down a dword of bytes\n" 48.73 " BRge loop\t\t! Clearing loop\n" 48.74 " STX G0,[$base+$temp]\t! delay slot" %} 48.75 - ins_encode( enc_Clear_Array(cnt, base, temp) ); 48.76 + 48.77 + ins_encode %{ 48.78 + // Compiler ensures base is doubleword aligned and cnt is count of doublewords 48.79 + Register nof_bytes_arg = $cnt$$Register; 48.80 + Register nof_bytes_tmp = $temp$$Register; 48.81 + Register base_pointer_arg = $base$$Register; 48.82 + 48.83 + Label loop; 48.84 + __ mov(nof_bytes_arg, nof_bytes_tmp); 48.85 + 48.86 + // Loop and clear, walking backwards through the array. 48.87 + // nof_bytes_tmp (if >0) is always the number of bytes to zero 48.88 + __ bind(loop); 48.89 + __ deccc(nof_bytes_tmp, 8); 48.90 + __ br(Assembler::greaterEqual, true, Assembler::pt, loop); 48.91 + __ delayed()-> stx(G0, base_pointer_arg, nof_bytes_tmp); 48.92 + // %%%% this mini-loop must not cross a cache boundary! 48.93 + %} 48.94 + ins_pipe(long_memory_op); 48.95 +%} 48.96 + 48.97 +instruct clear_array_bis(g1RegX cnt, o0RegP base, Universe dummy, flagsReg ccr) %{ 48.98 + predicate(use_block_zeroing(n->in(2))); 48.99 + match(Set dummy (ClearArray cnt base)); 48.100 + effect(USE_KILL cnt, USE_KILL base, KILL ccr); 48.101 + ins_cost(300); 48.102 + format %{ "CLEAR [$base, $cnt]\t! ClearArray" %} 48.103 + 48.104 + ins_encode %{ 48.105 + 48.106 + assert(MinObjAlignmentInBytes >= BytesPerLong, "need alternate implementation"); 48.107 + Register to = $base$$Register; 48.108 + Register count = $cnt$$Register; 48.109 + 48.110 + Label Ldone; 48.111 + __ nop(); // Separate short branches 48.112 + // Use BIS for zeroing (temp is not used). 48.113 + __ bis_zeroing(to, count, G0, Ldone); 48.114 + __ bind(Ldone); 48.115 + 48.116 + %} 48.117 + ins_pipe(long_memory_op); 48.118 +%} 48.119 + 48.120 +instruct clear_array_bis_2(g1RegX cnt, o0RegP base, iRegX tmp, Universe dummy, flagsReg ccr) %{ 48.121 + predicate(use_block_zeroing(n->in(2)) && !Assembler::is_simm13((int)BlockZeroingLowLimit)); 48.122 + match(Set dummy (ClearArray cnt base)); 48.123 + effect(TEMP tmp, USE_KILL cnt, USE_KILL base, KILL ccr); 48.124 + ins_cost(300); 48.125 + format %{ "CLEAR [$base, $cnt]\t! ClearArray" %} 48.126 + 48.127 + ins_encode %{ 48.128 + 48.129 + assert(MinObjAlignmentInBytes >= BytesPerLong, "need alternate implementation"); 48.130 + Register to = $base$$Register; 48.131 + Register count = $cnt$$Register; 48.132 + Register temp = $tmp$$Register; 48.133 + 48.134 + Label Ldone; 48.135 + __ nop(); // Separate short branches 48.136 + // Use BIS for zeroing 48.137 + __ bis_zeroing(to, count, temp, Ldone); 48.138 + __ bind(Ldone); 48.139 + 48.140 + %} 48.141 ins_pipe(long_memory_op); 48.142 %} 48.143
49.1 --- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp Thu Sep 08 16:59:27 2011 -0700 49.2 +++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp Fri Sep 09 16:17:16 2011 -0700 49.3 @@ -1124,6 +1124,126 @@ 49.4 } 49.5 } 49.6 49.7 + // 49.8 + // Generate main code for disjoint arraycopy 49.9 + // 49.10 + typedef void (StubGenerator::*CopyLoopFunc)(Register from, Register to, Register count, int count_dec, 49.11 + Label& L_loop, bool use_prefetch, bool use_bis); 49.12 + 49.13 + void disjoint_copy_core(Register from, Register to, Register count, int log2_elem_size, 49.14 + int iter_size, CopyLoopFunc copy_loop_func) { 49.15 + Label L_copy; 49.16 + 49.17 + assert(log2_elem_size <= 3, "the following code should be changed"); 49.18 + int count_dec = 16>>log2_elem_size; 49.19 + 49.20 + int prefetch_dist = MAX2(ArraycopySrcPrefetchDistance, ArraycopyDstPrefetchDistance); 49.21 + assert(prefetch_dist < 4096, "invalid value"); 49.22 + prefetch_dist = (prefetch_dist + (iter_size-1)) & (-iter_size); // round up to one iteration copy size 49.23 + int prefetch_count = (prefetch_dist >> log2_elem_size); // elements count 49.24 + 49.25 + if (UseBlockCopy) { 49.26 + Label L_block_copy, L_block_copy_prefetch, L_skip_block_copy; 49.27 + 49.28 + // 64 bytes tail + bytes copied in one loop iteration 49.29 + int tail_size = 64 + iter_size; 49.30 + int block_copy_count = (MAX2(tail_size, (int)BlockCopyLowLimit)) >> log2_elem_size; 49.31 + // Use BIS copy only for big arrays since it requires membar. 49.32 + __ set(block_copy_count, O4); 49.33 + __ cmp_and_br_short(count, O4, Assembler::lessUnsigned, Assembler::pt, L_skip_block_copy); 49.34 + // This code is for disjoint source and destination: 49.35 + // to <= from || to >= from+count 49.36 + // but BIS will stomp over 'from' if (to > from-tail_size && to <= from) 49.37 + __ sub(from, to, O4); 49.38 + __ srax(O4, 4, O4); // divide by 16 since following short branch have only 5 bits for imm. 49.39 + __ cmp_and_br_short(O4, (tail_size>>4), Assembler::lessEqualUnsigned, Assembler::pn, L_skip_block_copy); 49.40 + 49.41 + __ wrasi(G0, Assembler::ASI_ST_BLKINIT_PRIMARY); 49.42 + // BIS should not be used to copy tail (64 bytes+iter_size) 49.43 + // to avoid zeroing of following values. 49.44 + __ sub(count, (tail_size>>log2_elem_size), count); // count is still positive >= 0 49.45 + 49.46 + if (prefetch_count > 0) { // rounded up to one iteration count 49.47 + // Do prefetching only if copy size is bigger 49.48 + // than prefetch distance. 49.49 + __ set(prefetch_count, O4); 49.50 + __ cmp_and_brx_short(count, O4, Assembler::less, Assembler::pt, L_block_copy); 49.51 + __ sub(count, prefetch_count, count); 49.52 + 49.53 + (this->*copy_loop_func)(from, to, count, count_dec, L_block_copy_prefetch, true, true); 49.54 + __ add(count, prefetch_count, count); // restore count 49.55 + 49.56 + } // prefetch_count > 0 49.57 + 49.58 + (this->*copy_loop_func)(from, to, count, count_dec, L_block_copy, false, true); 49.59 + __ add(count, (tail_size>>log2_elem_size), count); // restore count 49.60 + 49.61 + __ wrasi(G0, Assembler::ASI_PRIMARY_NOFAULT); 49.62 + // BIS needs membar. 49.63 + __ membar(Assembler::StoreLoad); 49.64 + // Copy tail 49.65 + __ ba_short(L_copy); 49.66 + 49.67 + __ BIND(L_skip_block_copy); 49.68 + } // UseBlockCopy 49.69 + 49.70 + if (prefetch_count > 0) { // rounded up to one iteration count 49.71 + // Do prefetching only if copy size is bigger 49.72 + // than prefetch distance. 49.73 + __ set(prefetch_count, O4); 49.74 + __ cmp_and_brx_short(count, O4, Assembler::lessUnsigned, Assembler::pt, L_copy); 49.75 + __ sub(count, prefetch_count, count); 49.76 + 49.77 + Label L_copy_prefetch; 49.78 + (this->*copy_loop_func)(from, to, count, count_dec, L_copy_prefetch, true, false); 49.79 + __ add(count, prefetch_count, count); // restore count 49.80 + 49.81 + } // prefetch_count > 0 49.82 + 49.83 + (this->*copy_loop_func)(from, to, count, count_dec, L_copy, false, false); 49.84 + } 49.85 + 49.86 + 49.87 + 49.88 + // 49.89 + // Helper methods for copy_16_bytes_forward_with_shift() 49.90 + // 49.91 + void copy_16_bytes_shift_loop(Register from, Register to, Register count, int count_dec, 49.92 + Label& L_loop, bool use_prefetch, bool use_bis) { 49.93 + 49.94 + const Register left_shift = G1; // left shift bit counter 49.95 + const Register right_shift = G5; // right shift bit counter 49.96 + 49.97 + __ align(OptoLoopAlignment); 49.98 + __ BIND(L_loop); 49.99 + if (use_prefetch) { 49.100 + if (ArraycopySrcPrefetchDistance > 0) { 49.101 + __ prefetch(from, ArraycopySrcPrefetchDistance, Assembler::severalReads); 49.102 + } 49.103 + if (ArraycopyDstPrefetchDistance > 0) { 49.104 + __ prefetch(to, ArraycopyDstPrefetchDistance, Assembler::severalWritesAndPossiblyReads); 49.105 + } 49.106 + } 49.107 + __ ldx(from, 0, O4); 49.108 + __ ldx(from, 8, G4); 49.109 + __ inc(to, 16); 49.110 + __ inc(from, 16); 49.111 + __ deccc(count, count_dec); // Can we do next iteration after this one? 49.112 + __ srlx(O4, right_shift, G3); 49.113 + __ bset(G3, O3); 49.114 + __ sllx(O4, left_shift, O4); 49.115 + __ srlx(G4, right_shift, G3); 49.116 + __ bset(G3, O4); 49.117 + if (use_bis) { 49.118 + __ stxa(O3, to, -16); 49.119 + __ stxa(O4, to, -8); 49.120 + } else { 49.121 + __ stx(O3, to, -16); 49.122 + __ stx(O4, to, -8); 49.123 + } 49.124 + __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop); 49.125 + __ delayed()->sllx(G4, left_shift, O3); 49.126 + } 49.127 49.128 // Copy big chunks forward with shift 49.129 // 49.130 @@ -1135,64 +1255,51 @@ 49.131 // L_copy_bytes - copy exit label 49.132 // 49.133 void copy_16_bytes_forward_with_shift(Register from, Register to, 49.134 - Register count, int count_dec, Label& L_copy_bytes) { 49.135 - Label L_loop, L_aligned_copy, L_copy_last_bytes; 49.136 + Register count, int log2_elem_size, Label& L_copy_bytes) { 49.137 + Label L_aligned_copy, L_copy_last_bytes; 49.138 + assert(log2_elem_size <= 3, "the following code should be changed"); 49.139 + int count_dec = 16>>log2_elem_size; 49.140 49.141 // if both arrays have the same alignment mod 8, do 8 bytes aligned copy 49.142 - __ andcc(from, 7, G1); // misaligned bytes 49.143 - __ br(Assembler::zero, false, Assembler::pt, L_aligned_copy); 49.144 - __ delayed()->nop(); 49.145 + __ andcc(from, 7, G1); // misaligned bytes 49.146 + __ br(Assembler::zero, false, Assembler::pt, L_aligned_copy); 49.147 + __ delayed()->nop(); 49.148 49.149 const Register left_shift = G1; // left shift bit counter 49.150 const Register right_shift = G5; // right shift bit counter 49.151 49.152 - __ sll(G1, LogBitsPerByte, left_shift); 49.153 - __ mov(64, right_shift); 49.154 - __ sub(right_shift, left_shift, right_shift); 49.155 + __ sll(G1, LogBitsPerByte, left_shift); 49.156 + __ mov(64, right_shift); 49.157 + __ sub(right_shift, left_shift, right_shift); 49.158 49.159 // 49.160 // Load 2 aligned 8-bytes chunks and use one from previous iteration 49.161 // to form 2 aligned 8-bytes chunks to store. 49.162 // 49.163 - __ deccc(count, count_dec); // Pre-decrement 'count' 49.164 - __ andn(from, 7, from); // Align address 49.165 - __ ldx(from, 0, O3); 49.166 - __ inc(from, 8); 49.167 - __ align(OptoLoopAlignment); 49.168 - __ BIND(L_loop); 49.169 - __ ldx(from, 0, O4); 49.170 - __ deccc(count, count_dec); // Can we do next iteration after this one? 49.171 - __ ldx(from, 8, G4); 49.172 - __ inc(to, 16); 49.173 - __ inc(from, 16); 49.174 - __ sllx(O3, left_shift, O3); 49.175 - __ srlx(O4, right_shift, G3); 49.176 - __ bset(G3, O3); 49.177 - __ stx(O3, to, -16); 49.178 - __ sllx(O4, left_shift, O4); 49.179 - __ srlx(G4, right_shift, G3); 49.180 - __ bset(G3, O4); 49.181 - __ stx(O4, to, -8); 49.182 - __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop); 49.183 - __ delayed()->mov(G4, O3); 49.184 - 49.185 - __ inccc(count, count_dec>>1 ); // + 8 bytes 49.186 - __ brx(Assembler::negative, true, Assembler::pn, L_copy_last_bytes); 49.187 - __ delayed()->inc(count, count_dec>>1); // restore 'count' 49.188 - 49.189 - // copy 8 bytes, part of them already loaded in O3 49.190 - __ ldx(from, 0, O4); 49.191 - __ inc(to, 8); 49.192 - __ inc(from, 8); 49.193 - __ sllx(O3, left_shift, O3); 49.194 - __ srlx(O4, right_shift, G3); 49.195 - __ bset(O3, G3); 49.196 - __ stx(G3, to, -8); 49.197 + __ dec(count, count_dec); // Pre-decrement 'count' 49.198 + __ andn(from, 7, from); // Align address 49.199 + __ ldx(from, 0, O3); 49.200 + __ inc(from, 8); 49.201 + __ sllx(O3, left_shift, O3); 49.202 + 49.203 + disjoint_copy_core(from, to, count, log2_elem_size, 16, copy_16_bytes_shift_loop); 49.204 + 49.205 + __ inccc(count, count_dec>>1 ); // + 8 bytes 49.206 + __ brx(Assembler::negative, true, Assembler::pn, L_copy_last_bytes); 49.207 + __ delayed()->inc(count, count_dec>>1); // restore 'count' 49.208 + 49.209 + // copy 8 bytes, part of them already loaded in O3 49.210 + __ ldx(from, 0, O4); 49.211 + __ inc(to, 8); 49.212 + __ inc(from, 8); 49.213 + __ srlx(O4, right_shift, G3); 49.214 + __ bset(O3, G3); 49.215 + __ stx(G3, to, -8); 49.216 49.217 __ BIND(L_copy_last_bytes); 49.218 - __ srl(right_shift, LogBitsPerByte, right_shift); // misaligned bytes 49.219 - __ br(Assembler::always, false, Assembler::pt, L_copy_bytes); 49.220 - __ delayed()->sub(from, right_shift, from); // restore address 49.221 + __ srl(right_shift, LogBitsPerByte, right_shift); // misaligned bytes 49.222 + __ br(Assembler::always, false, Assembler::pt, L_copy_bytes); 49.223 + __ delayed()->sub(from, right_shift, from); // restore address 49.224 49.225 __ BIND(L_aligned_copy); 49.226 } 49.227 @@ -1348,7 +1455,7 @@ 49.228 // The compare above (count >= 23) guarantes 'count' >= 16 bytes. 49.229 // Also jump over aligned copy after the copy with shift completed. 49.230 49.231 - copy_16_bytes_forward_with_shift(from, to, count, 16, L_copy_byte); 49.232 + copy_16_bytes_forward_with_shift(from, to, count, 0, L_copy_byte); 49.233 } 49.234 49.235 // Both array are 8 bytes aligned, copy 16 bytes at a time 49.236 @@ -1576,7 +1683,7 @@ 49.237 // The compare above (count >= 11) guarantes 'count' >= 16 bytes. 49.238 // Also jump over aligned copy after the copy with shift completed. 49.239 49.240 - copy_16_bytes_forward_with_shift(from, to, count, 8, L_copy_2_bytes); 49.241 + copy_16_bytes_forward_with_shift(from, to, count, 1, L_copy_2_bytes); 49.242 } 49.243 49.244 // Both array are 8 bytes aligned, copy 16 bytes at a time 49.245 @@ -1950,6 +2057,45 @@ 49.246 } 49.247 49.248 // 49.249 + // Helper methods for generate_disjoint_int_copy_core() 49.250 + // 49.251 + void copy_16_bytes_loop(Register from, Register to, Register count, int count_dec, 49.252 + Label& L_loop, bool use_prefetch, bool use_bis) { 49.253 + 49.254 + __ align(OptoLoopAlignment); 49.255 + __ BIND(L_loop); 49.256 + if (use_prefetch) { 49.257 + if (ArraycopySrcPrefetchDistance > 0) { 49.258 + __ prefetch(from, ArraycopySrcPrefetchDistance, Assembler::severalReads); 49.259 + } 49.260 + if (ArraycopyDstPrefetchDistance > 0) { 49.261 + __ prefetch(to, ArraycopyDstPrefetchDistance, Assembler::severalWritesAndPossiblyReads); 49.262 + } 49.263 + } 49.264 + __ ldx(from, 4, O4); 49.265 + __ ldx(from, 12, G4); 49.266 + __ inc(to, 16); 49.267 + __ inc(from, 16); 49.268 + __ deccc(count, 4); // Can we do next iteration after this one? 49.269 + 49.270 + __ srlx(O4, 32, G3); 49.271 + __ bset(G3, O3); 49.272 + __ sllx(O4, 32, O4); 49.273 + __ srlx(G4, 32, G3); 49.274 + __ bset(G3, O4); 49.275 + if (use_bis) { 49.276 + __ stxa(O3, to, -16); 49.277 + __ stxa(O4, to, -8); 49.278 + } else { 49.279 + __ stx(O3, to, -16); 49.280 + __ stx(O4, to, -8); 49.281 + } 49.282 + __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop); 49.283 + __ delayed()->sllx(G4, 32, O3); 49.284 + 49.285 + } 49.286 + 49.287 + // 49.288 // Generate core code for disjoint int copy (and oop copy on 32-bit). 49.289 // If "aligned" is true, the "from" and "to" addresses are assumed 49.290 // to be heapword aligned. 49.291 @@ -1962,7 +2108,7 @@ 49.292 void generate_disjoint_int_copy_core(bool aligned) { 49.293 49.294 Label L_skip_alignment, L_aligned_copy; 49.295 - Label L_copy_16_bytes, L_copy_4_bytes, L_copy_4_bytes_loop, L_exit; 49.296 + Label L_copy_4_bytes, L_copy_4_bytes_loop, L_exit; 49.297 49.298 const Register from = O0; // source array address 49.299 const Register to = O1; // destination array address 49.300 @@ -2013,30 +2159,16 @@ 49.301 49.302 // copy with shift 4 elements (16 bytes) at a time 49.303 __ dec(count, 4); // The cmp at the beginning guaranty count >= 4 49.304 - 49.305 - __ align(OptoLoopAlignment); 49.306 - __ BIND(L_copy_16_bytes); 49.307 - __ ldx(from, 4, O4); 49.308 - __ deccc(count, 4); // Can we do next iteration after this one? 49.309 - __ ldx(from, 12, G4); 49.310 - __ inc(to, 16); 49.311 - __ inc(from, 16); 49.312 - __ sllx(O3, 32, O3); 49.313 - __ srlx(O4, 32, G3); 49.314 - __ bset(G3, O3); 49.315 - __ stx(O3, to, -16); 49.316 - __ sllx(O4, 32, O4); 49.317 - __ srlx(G4, 32, G3); 49.318 - __ bset(G3, O4); 49.319 - __ stx(O4, to, -8); 49.320 - __ brx(Assembler::greaterEqual, false, Assembler::pt, L_copy_16_bytes); 49.321 - __ delayed()->mov(G4, O3); 49.322 + __ sllx(O3, 32, O3); 49.323 + 49.324 + disjoint_copy_core(from, to, count, 2, 16, copy_16_bytes_loop); 49.325 49.326 __ br(Assembler::always, false, Assembler::pt, L_copy_4_bytes); 49.327 __ delayed()->inc(count, 4); // restore 'count' 49.328 49.329 __ BIND(L_aligned_copy); 49.330 - } 49.331 + } // !aligned 49.332 + 49.333 // copy 4 elements (16 bytes) at a time 49.334 __ and3(count, 1, G4); // Save 49.335 __ srl(count, 1, count); 49.336 @@ -2223,6 +2355,38 @@ 49.337 } 49.338 49.339 // 49.340 + // Helper methods for generate_disjoint_long_copy_core() 49.341 + // 49.342 + void copy_64_bytes_loop(Register from, Register to, Register count, int count_dec, 49.343 + Label& L_loop, bool use_prefetch, bool use_bis) { 49.344 + __ align(OptoLoopAlignment); 49.345 + __ BIND(L_loop); 49.346 + for (int off = 0; off < 64; off += 16) { 49.347 + if (use_prefetch && (off & 31) == 0) { 49.348 + if (ArraycopySrcPrefetchDistance > 0) { 49.349 + __ prefetch(from, ArraycopySrcPrefetchDistance, Assembler::severalReads); 49.350 + } 49.351 + if (ArraycopyDstPrefetchDistance > 0) { 49.352 + __ prefetch(to, ArraycopyDstPrefetchDistance, Assembler::severalWritesAndPossiblyReads); 49.353 + } 49.354 + } 49.355 + __ ldx(from, off+0, O4); 49.356 + __ ldx(from, off+8, O5); 49.357 + if (use_bis) { 49.358 + __ stxa(O4, to, off+0); 49.359 + __ stxa(O5, to, off+8); 49.360 + } else { 49.361 + __ stx(O4, to, off+0); 49.362 + __ stx(O5, to, off+8); 49.363 + } 49.364 + } 49.365 + __ deccc(count, 8); 49.366 + __ inc(from, 64); 49.367 + __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop); 49.368 + __ delayed()->inc(to, 64); 49.369 + } 49.370 + 49.371 + // 49.372 // Generate core code for disjoint long copy (and oop copy on 64-bit). 49.373 // "aligned" is ignored, because we must make the stronger 49.374 // assumption that both addresses are always 64-bit aligned. 49.375 @@ -2261,38 +2425,28 @@ 49.376 const Register offset0 = O4; // element offset 49.377 const Register offset8 = O5; // next element offset 49.378 49.379 - __ deccc(count, 2); 49.380 - __ mov(G0, offset0); // offset from start of arrays (0) 49.381 - __ brx(Assembler::negative, false, Assembler::pn, L_copy_8_bytes ); 49.382 - __ delayed()->add(offset0, 8, offset8); 49.383 + __ deccc(count, 2); 49.384 + __ mov(G0, offset0); // offset from start of arrays (0) 49.385 + __ brx(Assembler::negative, false, Assembler::pn, L_copy_8_bytes ); 49.386 + __ delayed()->add(offset0, 8, offset8); 49.387 49.388 // Copy by 64 bytes chunks 49.389 - Label L_copy_64_bytes; 49.390 + 49.391 const Register from64 = O3; // source address 49.392 const Register to64 = G3; // destination address 49.393 - __ subcc(count, 6, O3); 49.394 - __ brx(Assembler::negative, false, Assembler::pt, L_copy_16_bytes ); 49.395 - __ delayed()->mov(to, to64); 49.396 - // Now we can use O4(offset0), O5(offset8) as temps 49.397 - __ mov(O3, count); 49.398 - __ mov(from, from64); 49.399 - 49.400 - __ align(OptoLoopAlignment); 49.401 - __ BIND(L_copy_64_bytes); 49.402 - for( int off = 0; off < 64; off += 16 ) { 49.403 - __ ldx(from64, off+0, O4); 49.404 - __ ldx(from64, off+8, O5); 49.405 - __ stx(O4, to64, off+0); 49.406 - __ stx(O5, to64, off+8); 49.407 - } 49.408 - __ deccc(count, 8); 49.409 - __ inc(from64, 64); 49.410 - __ brx(Assembler::greaterEqual, false, Assembler::pt, L_copy_64_bytes); 49.411 - __ delayed()->inc(to64, 64); 49.412 + __ subcc(count, 6, O3); 49.413 + __ brx(Assembler::negative, false, Assembler::pt, L_copy_16_bytes ); 49.414 + __ delayed()->mov(to, to64); 49.415 + // Now we can use O4(offset0), O5(offset8) as temps 49.416 + __ mov(O3, count); 49.417 + // count >= 0 (original count - 8) 49.418 + __ mov(from, from64); 49.419 + 49.420 + disjoint_copy_core(from64, to64, count, 3, 64, copy_64_bytes_loop); 49.421 49.422 // Restore O4(offset0), O5(offset8) 49.423 __ sub(from64, from, offset0); 49.424 - __ inccc(count, 6); 49.425 + __ inccc(count, 6); // restore count 49.426 __ brx(Assembler::negative, false, Assembler::pn, L_copy_8_bytes ); 49.427 __ delayed()->add(offset0, 8, offset8); 49.428 49.429 @@ -3069,6 +3223,34 @@ 49.430 return start; 49.431 } 49.432 49.433 + // 49.434 + // Generate stub for heap zeroing. 49.435 + // "to" address is aligned to jlong (8 bytes). 49.436 + // 49.437 + // Arguments for generated stub: 49.438 + // to: O0 49.439 + // count: O1 treated as signed (count of HeapWord) 49.440 + // count could be 0 49.441 + // 49.442 + address generate_zero_aligned_words(const char* name) { 49.443 + __ align(CodeEntryAlignment); 49.444 + StubCodeMark mark(this, "StubRoutines", name); 49.445 + address start = __ pc(); 49.446 + 49.447 + const Register to = O0; // source array address 49.448 + const Register count = O1; // HeapWords count 49.449 + const Register temp = O2; // scratch 49.450 + 49.451 + Label Ldone; 49.452 + __ sllx(count, LogHeapWordSize, count); // to bytes count 49.453 + // Use BIS for zeroing 49.454 + __ bis_zeroing(to, count, temp, Ldone); 49.455 + __ bind(Ldone); 49.456 + __ retl(); 49.457 + __ delayed()->nop(); 49.458 + return start; 49.459 +} 49.460 + 49.461 void generate_arraycopy_stubs() { 49.462 address entry; 49.463 address entry_jbyte_arraycopy; 49.464 @@ -3195,6 +3377,10 @@ 49.465 StubRoutines::_arrayof_jbyte_fill = generate_fill(T_BYTE, true, "arrayof_jbyte_fill"); 49.466 StubRoutines::_arrayof_jshort_fill = generate_fill(T_SHORT, true, "arrayof_jshort_fill"); 49.467 StubRoutines::_arrayof_jint_fill = generate_fill(T_INT, true, "arrayof_jint_fill"); 49.468 + 49.469 + if (UseBlockZeroing) { 49.470 + StubRoutines::_zero_aligned_words = generate_zero_aligned_words("zero_aligned_words"); 49.471 + } 49.472 } 49.473 49.474 void generate_initial() {
50.1 --- a/src/cpu/sparc/vm/templateTable_sparc.cpp Thu Sep 08 16:59:27 2011 -0700 50.2 +++ b/src/cpu/sparc/vm/templateTable_sparc.cpp Fri Sep 09 16:17:16 2011 -0700 50.3 @@ -3374,7 +3374,7 @@ 50.4 50.5 if(UseTLAB) { 50.6 Register RoldTopValue = RallocatedObject; 50.7 - Register RtopAddr = G3_scratch, RtlabWasteLimitValue = G3_scratch; 50.8 + Register RtlabWasteLimitValue = G3_scratch; 50.9 Register RnewTopValue = G1_scratch; 50.10 Register RendValue = Rscratch; 50.11 Register RfreeValue = RnewTopValue; 50.12 @@ -3455,7 +3455,11 @@ 50.13 __ delayed()->add(RallocatedObject, sizeof(oopDesc), G3_scratch); 50.14 50.15 // initialize remaining object fields 50.16 - { Label loop; 50.17 + if (UseBlockZeroing) { 50.18 + // Use BIS for zeroing 50.19 + __ bis_zeroing(G3_scratch, Roffset, G1_scratch, initialize_header); 50.20 + } else { 50.21 + Label loop; 50.22 __ subcc(Roffset, wordSize, Roffset); 50.23 __ bind(loop); 50.24 //__ subcc(Roffset, wordSize, Roffset); // executed above loop or in delay slot
51.1 --- a/src/cpu/sparc/vm/vm_version_sparc.cpp Thu Sep 08 16:59:27 2011 -0700 51.2 +++ b/src/cpu/sparc/vm/vm_version_sparc.cpp Fri Sep 09 16:17:16 2011 -0700 51.3 @@ -75,6 +75,24 @@ 51.4 FLAG_SET_DEFAULT(AllocatePrefetchStyle, 1); 51.5 } 51.6 51.7 + if (has_v9()) { 51.8 + assert(ArraycopySrcPrefetchDistance < 4096, "invalid value"); 51.9 + if (ArraycopySrcPrefetchDistance >= 4096) 51.10 + ArraycopySrcPrefetchDistance = 4064; 51.11 + assert(ArraycopyDstPrefetchDistance < 4096, "invalid value"); 51.12 + if (ArraycopyDstPrefetchDistance >= 4096) 51.13 + ArraycopyDstPrefetchDistance = 4064; 51.14 + } else { 51.15 + if (ArraycopySrcPrefetchDistance > 0) { 51.16 + warning("prefetch instructions are not available on this CPU"); 51.17 + FLAG_SET_DEFAULT(ArraycopySrcPrefetchDistance, 0); 51.18 + } 51.19 + if (ArraycopyDstPrefetchDistance > 0) { 51.20 + warning("prefetch instructions are not available on this CPU"); 51.21 + FLAG_SET_DEFAULT(ArraycopyDstPrefetchDistance, 0); 51.22 + } 51.23 + } 51.24 + 51.25 UseSSE = 0; // Only on x86 and x64 51.26 51.27 _supports_cx8 = has_v9(); 51.28 @@ -170,6 +188,26 @@ 51.29 FLAG_SET_DEFAULT(UseCBCond, false); 51.30 } 51.31 51.32 + assert(BlockZeroingLowLimit > 0, "invalid value"); 51.33 + if (has_block_zeroing()) { 51.34 + if (FLAG_IS_DEFAULT(UseBlockZeroing)) { 51.35 + FLAG_SET_DEFAULT(UseBlockZeroing, true); 51.36 + } 51.37 + } else if (UseBlockZeroing) { 51.38 + warning("BIS zeroing instructions are not available on this CPU"); 51.39 + FLAG_SET_DEFAULT(UseBlockZeroing, false); 51.40 + } 51.41 + 51.42 + assert(BlockCopyLowLimit > 0, "invalid value"); 51.43 + if (has_block_zeroing()) { // has_blk_init() && is_T4(): core's local L2 cache 51.44 + if (FLAG_IS_DEFAULT(UseBlockCopy)) { 51.45 + FLAG_SET_DEFAULT(UseBlockCopy, true); 51.46 + } 51.47 + } else if (UseBlockCopy) { 51.48 + warning("BIS instructions are not available or expensive on this CPU"); 51.49 + FLAG_SET_DEFAULT(UseBlockCopy, false); 51.50 + } 51.51 + 51.52 #ifdef COMPILER2 51.53 // T4 and newer Sparc cpus have fast RDPC. 51.54 if (has_fast_rdpc() && FLAG_IS_DEFAULT(UseRDPCForConstantTableBase)) {
52.1 --- a/src/cpu/sparc/vm/vm_version_sparc.hpp Thu Sep 08 16:59:27 2011 -0700 52.2 +++ b/src/cpu/sparc/vm/vm_version_sparc.hpp Fri Sep 09 16:17:16 2011 -0700 52.3 @@ -135,8 +135,8 @@ 52.4 // T4 and newer Sparc have fast RDPC instruction. 52.5 static bool has_fast_rdpc() { return is_T4(); } 52.6 52.7 - // T4 and newer Sparc have Most-Recently-Used (MRU) BIS. 52.8 - static bool has_mru_blk_init() { return has_blk_init() && is_T4(); } 52.9 + // On T4 and newer Sparc BIS to the beginning of cache line always zeros it. 52.10 + static bool has_block_zeroing() { return has_blk_init() && is_T4(); } 52.11 52.12 static const char* cpu_features() { return _features_str; } 52.13
53.1 --- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Sep 08 16:59:27 2011 -0700 53.2 +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Sep 09 16:17:16 2011 -0700 53.3 @@ -129,10 +129,6 @@ 53.4 return FrameMap::receiver_opr; 53.5 } 53.6 53.7 -LIR_Opr LIR_Assembler::incomingReceiverOpr() { 53.8 - return receiverOpr(); 53.9 -} 53.10 - 53.11 LIR_Opr LIR_Assembler::osrBufferPointer() { 53.12 return FrameMap::as_pointer_opr(receiverOpr()->as_register()); 53.13 } 53.14 @@ -371,55 +367,6 @@ 53.15 } 53.16 53.17 53.18 -void LIR_Assembler::monitorexit(LIR_Opr obj_opr, LIR_Opr lock_opr, Register new_hdr, int monitor_no, Register exception) { 53.19 - if (exception->is_valid()) { 53.20 - // preserve exception 53.21 - // note: the monitor_exit runtime call is a leaf routine 53.22 - // and cannot block => no GC can happen 53.23 - // The slow case (MonitorAccessStub) uses the first two stack slots 53.24 - // ([esp+0] and [esp+4]), therefore we store the exception at [esp+8] 53.25 - __ movptr (Address(rsp, 2*wordSize), exception); 53.26 - } 53.27 - 53.28 - Register obj_reg = obj_opr->as_register(); 53.29 - Register lock_reg = lock_opr->as_register(); 53.30 - 53.31 - // setup registers (lock_reg must be rax, for lock_object) 53.32 - assert(obj_reg != SYNC_header && lock_reg != SYNC_header, "rax, must be available here"); 53.33 - Register hdr = lock_reg; 53.34 - assert(new_hdr == SYNC_header, "wrong register"); 53.35 - lock_reg = new_hdr; 53.36 - // compute pointer to BasicLock 53.37 - Address lock_addr = frame_map()->address_for_monitor_lock(monitor_no); 53.38 - __ lea(lock_reg, lock_addr); 53.39 - // unlock object 53.40 - MonitorAccessStub* slow_case = new MonitorExitStub(lock_opr, true, monitor_no); 53.41 - // _slow_case_stubs->append(slow_case); 53.42 - // temporary fix: must be created after exceptionhandler, therefore as call stub 53.43 - _slow_case_stubs->append(slow_case); 53.44 - if (UseFastLocking) { 53.45 - // try inlined fast unlocking first, revert to slow locking if it fails 53.46 - // note: lock_reg points to the displaced header since the displaced header offset is 0! 53.47 - assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); 53.48 - __ unlock_object(hdr, obj_reg, lock_reg, *slow_case->entry()); 53.49 - } else { 53.50 - // always do slow unlocking 53.51 - // note: the slow unlocking code could be inlined here, however if we use 53.52 - // slow unlocking, speed doesn't matter anyway and this solution is 53.53 - // simpler and requires less duplicated code - additionally, the 53.54 - // slow unlocking code is the same in either case which simplifies 53.55 - // debugging 53.56 - __ jmp(*slow_case->entry()); 53.57 - } 53.58 - // done 53.59 - __ bind(*slow_case->continuation()); 53.60 - 53.61 - if (exception->is_valid()) { 53.62 - // restore exception 53.63 - __ movptr (exception, Address(rsp, 2 * wordSize)); 53.64 - } 53.65 -} 53.66 - 53.67 // This specifies the rsp decrement needed to build the frame 53.68 int LIR_Assembler::initial_frame_size_in_bytes() { 53.69 // if rounding, must let FrameMap know!
54.1 --- a/src/cpu/x86/vm/c1_LIRAssembler_x86.hpp Thu Sep 08 16:59:27 2011 -0700 54.2 +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.hpp Fri Sep 09 16:17:16 2011 -0700 54.3 @@ -29,8 +29,6 @@ 54.4 54.5 Address::ScaleFactor array_element_size(BasicType type) const; 54.6 54.7 - void monitorexit(LIR_Opr obj_opr, LIR_Opr lock_opr, Register new_hdr, int monitor_no, Register exception); 54.8 - 54.9 void arith_fpu_implementation(LIR_Code code, int left_index, int right_index, int dest_index, bool pop_fpu_stack); 54.10 54.11 // helper functions which checks for overflow and sets bailout if it
55.1 --- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp Thu Sep 08 16:59:27 2011 -0700 55.2 +++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp Fri Sep 09 16:17:16 2011 -0700 55.3 @@ -1465,19 +1465,6 @@ 55.4 } 55.5 break; 55.6 55.7 - case jvmti_exception_throw_id: 55.8 - { // rax,: exception oop 55.9 - StubFrame f(sasm, "jvmti_exception_throw", dont_gc_arguments); 55.10 - // Preserve all registers across this potentially blocking call 55.11 - const int num_rt_args = 2; // thread, exception oop 55.12 - OopMap* map = save_live_registers(sasm, num_rt_args); 55.13 - int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, Runtime1::post_jvmti_exception_throw), rax); 55.14 - oop_maps = new OopMapSet(); 55.15 - oop_maps->add_gc_map(call_offset, map); 55.16 - restore_live_registers(sasm); 55.17 - } 55.18 - break; 55.19 - 55.20 case dtrace_object_alloc_id: 55.21 { // rax,: object 55.22 StubFrame f(sasm, "dtrace_object_alloc", dont_gc_arguments);
56.1 --- a/src/cpu/x86/vm/methodHandles_x86.cpp Thu Sep 08 16:59:27 2011 -0700 56.2 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Fri Sep 09 16:17:16 2011 -0700 56.3 @@ -1343,6 +1343,13 @@ 56.4 } 56.5 break; 56.6 56.7 + case _adapter_opt_profiling: 56.8 + if (java_lang_invoke_CountingMethodHandle::vmcount_offset_in_bytes() != 0) { 56.9 + Address rcx_mh_vmcount(rcx_recv, java_lang_invoke_CountingMethodHandle::vmcount_offset_in_bytes()); 56.10 + __ incrementl(rcx_mh_vmcount); 56.11 + } 56.12 + // fall through 56.13 + 56.14 case _adapter_retype_only: 56.15 case _adapter_retype_raw: 56.16 // immediately jump to the next MH layer:
57.1 --- a/src/cpu/x86/vm/methodHandles_x86.hpp Thu Sep 08 16:59:27 2011 -0700 57.2 +++ b/src/cpu/x86/vm/methodHandles_x86.hpp Fri Sep 09 16:17:16 2011 -0700 57.3 @@ -110,6 +110,7 @@ 57.4 57.5 class RicochetFrame { 57.6 friend class MethodHandles; 57.7 + friend class VMStructs; 57.8 57.9 private: 57.10 intptr_t* _continuation; // what to do when control gets back here
58.1 --- a/src/os/linux/vm/os_linux.cpp Thu Sep 08 16:59:27 2011 -0700 58.2 +++ b/src/os/linux/vm/os_linux.cpp Fri Sep 09 16:17:16 2011 -0700 58.3 @@ -125,10 +125,6 @@ 58.4 # include <inttypes.h> 58.5 # include <sys/ioctl.h> 58.6 58.7 -#ifdef AMD64 58.8 -#include <asm/vsyscall.h> 58.9 -#endif 58.10 - 58.11 #define MAX_PATH (2 * K) 58.12 58.13 // for timer info max values which include all bits 58.14 @@ -2502,7 +2498,13 @@ 58.15 int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; 58.16 uintptr_t res = (uintptr_t) ::mmap(addr, size, prot, 58.17 MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); 58.18 - return res != (uintptr_t) MAP_FAILED; 58.19 + if (res != (uintptr_t) MAP_FAILED) { 58.20 + if (UseNUMAInterleaving) { 58.21 + numa_make_global(addr, size); 58.22 + } 58.23 + return true; 58.24 + } 58.25 + return false; 58.26 } 58.27 58.28 // Define MAP_HUGETLB here so we can build HotSpot on old systems. 58.29 @@ -2523,10 +2525,20 @@ 58.30 (uintptr_t) ::mmap(addr, size, prot, 58.31 MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_HUGETLB, 58.32 -1, 0); 58.33 - return res != (uintptr_t) MAP_FAILED; 58.34 - } 58.35 - 58.36 - return commit_memory(addr, size, exec); 58.37 + if (res != (uintptr_t) MAP_FAILED) { 58.38 + if (UseNUMAInterleaving) { 58.39 + numa_make_global(addr, size); 58.40 + } 58.41 + return true; 58.42 + } 58.43 + // Fall through and try to use small pages 58.44 + } 58.45 + 58.46 + if (commit_memory(addr, size, exec)) { 58.47 + realign_memory(addr, size, alignment_hint); 58.48 + return true; 58.49 + } 58.50 + return false; 58.51 } 58.52 58.53 void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { 58.54 @@ -2588,8 +2600,17 @@ 58.55 int retval = -1; 58.56 58.57 #if defined(IA32) 58.58 +# ifndef SYS_getcpu 58.59 +# define SYS_getcpu 318 58.60 +# endif 58.61 retval = syscall(SYS_getcpu, &cpu, NULL, NULL); 58.62 #elif defined(AMD64) 58.63 +// Unfortunately we have to bring all these macros here from vsyscall.h 58.64 +// to be able to compile on old linuxes. 58.65 +# define __NR_vgetcpu 2 58.66 +# define VSYSCALL_START (-10UL << 20) 58.67 +# define VSYSCALL_SIZE 1024 58.68 +# define VSYSCALL_ADDR(vsyscall_nr) (VSYSCALL_START+VSYSCALL_SIZE*(vsyscall_nr)) 58.69 typedef long (*vgetcpu_t)(unsigned int *cpu, unsigned int *node, unsigned long *tcache); 58.70 vgetcpu_t vgetcpu = (vgetcpu_t)VSYSCALL_ADDR(__NR_vgetcpu); 58.71 retval = vgetcpu(&cpu, NULL, NULL); 58.72 @@ -3115,6 +3136,10 @@ 58.73 return NULL; 58.74 } 58.75 58.76 + if ((addr != NULL) && UseNUMAInterleaving) { 58.77 + numa_make_global(addr, bytes); 58.78 + } 58.79 + 58.80 return addr; 58.81 } 58.82
59.1 --- a/src/os/solaris/vm/os_solaris.cpp Thu Sep 08 16:59:27 2011 -0700 59.2 +++ b/src/os/solaris/vm/os_solaris.cpp Fri Sep 09 16:17:16 2011 -0700 59.3 @@ -2777,8 +2777,14 @@ 59.4 bool os::commit_memory(char* addr, size_t bytes, bool exec) { 59.5 int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE; 59.6 size_t size = bytes; 59.7 - return 59.8 - NULL != Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, prot); 59.9 + char *res = Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, prot); 59.10 + if (res != NULL) { 59.11 + if (UseNUMAInterleaving) { 59.12 + numa_make_global(addr, bytes); 59.13 + } 59.14 + return true; 59.15 + } 59.16 + return false; 59.17 } 59.18 59.19 bool os::commit_memory(char* addr, size_t bytes, size_t alignment_hint, 59.20 @@ -3389,12 +3395,11 @@ 59.21 return true; 59.22 } 59.23 59.24 -char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) { 59.25 +char* os::reserve_memory_special(size_t size, char* addr, bool exec) { 59.26 // "exec" is passed in but not used. Creating the shared image for 59.27 // the code cache doesn't have an SHM_X executable permission to check. 59.28 assert(UseLargePages && UseISM, "only for ISM large pages"); 59.29 59.30 - size_t size = bytes; 59.31 char* retAddr = NULL; 59.32 int shmid; 59.33 key_t ismKey; 59.34 @@ -3436,7 +3441,9 @@ 59.35 } 59.36 return NULL; 59.37 } 59.38 - 59.39 + if ((retAddr != NULL) && UseNUMAInterleaving) { 59.40 + numa_make_global(retAddr, size); 59.41 + } 59.42 return retAddr; 59.43 } 59.44
60.1 --- a/src/os/windows/vm/os_windows.cpp Thu Sep 08 16:59:27 2011 -0700 60.2 +++ b/src/os/windows/vm/os_windows.cpp Fri Sep 09 16:17:16 2011 -0700 60.3 @@ -2614,6 +2614,57 @@ 60.4 static HANDLE _hProcess; 60.5 static HANDLE _hToken; 60.6 60.7 +// Container for NUMA node list info 60.8 +class NUMANodeListHolder { 60.9 +private: 60.10 + int *_numa_used_node_list; // allocated below 60.11 + int _numa_used_node_count; 60.12 + 60.13 + void free_node_list() { 60.14 + if (_numa_used_node_list != NULL) { 60.15 + FREE_C_HEAP_ARRAY(int, _numa_used_node_list); 60.16 + } 60.17 + } 60.18 + 60.19 +public: 60.20 + NUMANodeListHolder() { 60.21 + _numa_used_node_count = 0; 60.22 + _numa_used_node_list = NULL; 60.23 + // do rest of initialization in build routine (after function pointers are set up) 60.24 + } 60.25 + 60.26 + ~NUMANodeListHolder() { 60.27 + free_node_list(); 60.28 + } 60.29 + 60.30 + bool build() { 60.31 + DWORD_PTR proc_aff_mask; 60.32 + DWORD_PTR sys_aff_mask; 60.33 + if (!GetProcessAffinityMask(GetCurrentProcess(), &proc_aff_mask, &sys_aff_mask)) return false; 60.34 + ULONG highest_node_number; 60.35 + if (!os::Kernel32Dll::GetNumaHighestNodeNumber(&highest_node_number)) return false; 60.36 + free_node_list(); 60.37 + _numa_used_node_list = NEW_C_HEAP_ARRAY(int, highest_node_number); 60.38 + for (unsigned int i = 0; i <= highest_node_number; i++) { 60.39 + ULONGLONG proc_mask_numa_node; 60.40 + if (!os::Kernel32Dll::GetNumaNodeProcessorMask(i, &proc_mask_numa_node)) return false; 60.41 + if ((proc_aff_mask & proc_mask_numa_node)!=0) { 60.42 + _numa_used_node_list[_numa_used_node_count++] = i; 60.43 + } 60.44 + } 60.45 + return (_numa_used_node_count > 1); 60.46 + } 60.47 + 60.48 + int get_count() {return _numa_used_node_count;} 60.49 + int get_node_list_entry(int n) { 60.50 + // for indexes out of range, returns -1 60.51 + return (n < _numa_used_node_count ? _numa_used_node_list[n] : -1); 60.52 + } 60.53 + 60.54 +} numa_node_list_holder; 60.55 + 60.56 + 60.57 + 60.58 static size_t _large_page_size = 0; 60.59 60.60 static bool resolve_functions_for_large_page_init() { 60.61 @@ -2653,6 +2704,153 @@ 60.62 _hToken = NULL; 60.63 } 60.64 60.65 +static bool numa_interleaving_init() { 60.66 + bool success = false; 60.67 + bool use_numa_interleaving_specified = !FLAG_IS_DEFAULT(UseNUMAInterleaving); 60.68 + 60.69 + // print a warning if UseNUMAInterleaving flag is specified on command line 60.70 + bool warn_on_failure = use_numa_interleaving_specified; 60.71 +# define WARN(msg) if (warn_on_failure) { warning(msg); } 60.72 + 60.73 + // NUMAInterleaveGranularity cannot be less than vm_allocation_granularity (or _large_page_size if using large pages) 60.74 + size_t min_interleave_granularity = UseLargePages ? _large_page_size : os::vm_allocation_granularity(); 60.75 + NUMAInterleaveGranularity = align_size_up(NUMAInterleaveGranularity, min_interleave_granularity); 60.76 + 60.77 + if (os::Kernel32Dll::NumaCallsAvailable()) { 60.78 + if (numa_node_list_holder.build()) { 60.79 + if (PrintMiscellaneous && Verbose) { 60.80 + tty->print("NUMA UsedNodeCount=%d, namely ", numa_node_list_holder.get_count()); 60.81 + for (int i = 0; i < numa_node_list_holder.get_count(); i++) { 60.82 + tty->print("%d ", numa_node_list_holder.get_node_list_entry(i)); 60.83 + } 60.84 + tty->print("\n"); 60.85 + } 60.86 + success = true; 60.87 + } else { 60.88 + WARN("Process does not cover multiple NUMA nodes."); 60.89 + } 60.90 + } else { 60.91 + WARN("NUMA Interleaving is not supported by the operating system."); 60.92 + } 60.93 + if (!success) { 60.94 + if (use_numa_interleaving_specified) WARN("...Ignoring UseNUMAInterleaving flag."); 60.95 + } 60.96 + return success; 60.97 +#undef WARN 60.98 +} 60.99 + 60.100 +// this routine is used whenever we need to reserve a contiguous VA range 60.101 +// but we need to make separate VirtualAlloc calls for each piece of the range 60.102 +// Reasons for doing this: 60.103 +// * UseLargePagesIndividualAllocation was set (normally only needed on WS2003 but possible to be set otherwise) 60.104 +// * UseNUMAInterleaving requires a separate node for each piece 60.105 +static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags, DWORD prot, 60.106 + bool should_inject_error=false) { 60.107 + char * p_buf; 60.108 + // note: at setup time we guaranteed that NUMAInterleaveGranularity was aligned up to a page size 60.109 + size_t page_size = UseLargePages ? _large_page_size : os::vm_allocation_granularity(); 60.110 + size_t chunk_size = UseNUMAInterleaving ? NUMAInterleaveGranularity : page_size; 60.111 + 60.112 + // first reserve enough address space in advance since we want to be 60.113 + // able to break a single contiguous virtual address range into multiple 60.114 + // large page commits but WS2003 does not allow reserving large page space 60.115 + // so we just use 4K pages for reserve, this gives us a legal contiguous 60.116 + // address space. then we will deallocate that reservation, and re alloc 60.117 + // using large pages 60.118 + const size_t size_of_reserve = bytes + chunk_size; 60.119 + if (bytes > size_of_reserve) { 60.120 + // Overflowed. 60.121 + return NULL; 60.122 + } 60.123 + p_buf = (char *) VirtualAlloc(addr, 60.124 + size_of_reserve, // size of Reserve 60.125 + MEM_RESERVE, 60.126 + PAGE_READWRITE); 60.127 + // If reservation failed, return NULL 60.128 + if (p_buf == NULL) return NULL; 60.129 + 60.130 + os::release_memory(p_buf, bytes + chunk_size); 60.131 + 60.132 + // we still need to round up to a page boundary (in case we are using large pages) 60.133 + // but not to a chunk boundary (in case InterleavingGranularity doesn't align with page size) 60.134 + // instead we handle this in the bytes_to_rq computation below 60.135 + p_buf = (char *) align_size_up((size_t)p_buf, page_size); 60.136 + 60.137 + // now go through and allocate one chunk at a time until all bytes are 60.138 + // allocated 60.139 + size_t bytes_remaining = bytes; 60.140 + // An overflow of align_size_up() would have been caught above 60.141 + // in the calculation of size_of_reserve. 60.142 + char * next_alloc_addr = p_buf; 60.143 + HANDLE hProc = GetCurrentProcess(); 60.144 + 60.145 +#ifdef ASSERT 60.146 + // Variable for the failure injection 60.147 + long ran_num = os::random(); 60.148 + size_t fail_after = ran_num % bytes; 60.149 +#endif 60.150 + 60.151 + int count=0; 60.152 + while (bytes_remaining) { 60.153 + // select bytes_to_rq to get to the next chunk_size boundary 60.154 + 60.155 + size_t bytes_to_rq = MIN2(bytes_remaining, chunk_size - ((size_t)next_alloc_addr % chunk_size)); 60.156 + // Note allocate and commit 60.157 + char * p_new; 60.158 + 60.159 +#ifdef ASSERT 60.160 + bool inject_error_now = should_inject_error && (bytes_remaining <= fail_after); 60.161 +#else 60.162 + const bool inject_error_now = false; 60.163 +#endif 60.164 + 60.165 + if (inject_error_now) { 60.166 + p_new = NULL; 60.167 + } else { 60.168 + if (!UseNUMAInterleaving) { 60.169 + p_new = (char *) VirtualAlloc(next_alloc_addr, 60.170 + bytes_to_rq, 60.171 + flags, 60.172 + prot); 60.173 + } else { 60.174 + // get the next node to use from the used_node_list 60.175 + assert(numa_node_list_holder.get_count() > 0, "Multiple NUMA nodes expected"); 60.176 + DWORD node = numa_node_list_holder.get_node_list_entry(count % numa_node_list_holder.get_count()); 60.177 + p_new = (char *)os::Kernel32Dll::VirtualAllocExNuma(hProc, 60.178 + next_alloc_addr, 60.179 + bytes_to_rq, 60.180 + flags, 60.181 + prot, 60.182 + node); 60.183 + } 60.184 + } 60.185 + 60.186 + if (p_new == NULL) { 60.187 + // Free any allocated pages 60.188 + if (next_alloc_addr > p_buf) { 60.189 + // Some memory was committed so release it. 60.190 + size_t bytes_to_release = bytes - bytes_remaining; 60.191 + os::release_memory(p_buf, bytes_to_release); 60.192 + } 60.193 +#ifdef ASSERT 60.194 + if (should_inject_error) { 60.195 + if (TracePageSizes && Verbose) { 60.196 + tty->print_cr("Reserving pages individually failed."); 60.197 + } 60.198 + } 60.199 +#endif 60.200 + return NULL; 60.201 + } 60.202 + bytes_remaining -= bytes_to_rq; 60.203 + next_alloc_addr += bytes_to_rq; 60.204 + count++; 60.205 + } 60.206 + // made it this far, success 60.207 + return p_buf; 60.208 +} 60.209 + 60.210 + 60.211 + 60.212 void os::large_page_init() { 60.213 if (!UseLargePages) return; 60.214 60.215 @@ -2722,9 +2920,30 @@ 60.216 assert((size_t)addr % os::vm_allocation_granularity() == 0, 60.217 "reserve alignment"); 60.218 assert(bytes % os::vm_allocation_granularity() == 0, "reserve block size"); 60.219 - char* res = (char*)VirtualAlloc(addr, bytes, MEM_RESERVE, PAGE_READWRITE); 60.220 + char* res; 60.221 + // note that if UseLargePages is on, all the areas that require interleaving 60.222 + // will go thru reserve_memory_special rather than thru here. 60.223 + bool use_individual = (UseNUMAInterleaving && !UseLargePages); 60.224 + if (!use_individual) { 60.225 + res = (char*)VirtualAlloc(addr, bytes, MEM_RESERVE, PAGE_READWRITE); 60.226 + } else { 60.227 + elapsedTimer reserveTimer; 60.228 + if( Verbose && PrintMiscellaneous ) reserveTimer.start(); 60.229 + // in numa interleaving, we have to allocate pages individually 60.230 + // (well really chunks of NUMAInterleaveGranularity size) 60.231 + res = allocate_pages_individually(bytes, addr, MEM_RESERVE, PAGE_READWRITE); 60.232 + if (res == NULL) { 60.233 + warning("NUMA page allocation failed"); 60.234 + } 60.235 + if( Verbose && PrintMiscellaneous ) { 60.236 + reserveTimer.stop(); 60.237 + tty->print_cr("reserve_memory of %Ix bytes took %ld ms (%ld ticks)", bytes, 60.238 + reserveTimer.milliseconds(), reserveTimer.ticks()); 60.239 + } 60.240 + } 60.241 assert(res == NULL || addr == NULL || addr == res, 60.242 "Unexpected address from reserve."); 60.243 + 60.244 return res; 60.245 } 60.246 60.247 @@ -2754,92 +2973,27 @@ 60.248 char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) { 60.249 60.250 const DWORD prot = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 60.251 - 60.252 - if (UseLargePagesIndividualAllocation) { 60.253 + const DWORD flags = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; 60.254 + 60.255 + // with large pages, there are two cases where we need to use Individual Allocation 60.256 + // 1) the UseLargePagesIndividualAllocation flag is set (set by default on WS2003) 60.257 + // 2) NUMA Interleaving is enabled, in which case we use a different node for each page 60.258 + if (UseLargePagesIndividualAllocation || UseNUMAInterleaving) { 60.259 if (TracePageSizes && Verbose) { 60.260 tty->print_cr("Reserving large pages individually."); 60.261 } 60.262 - char * p_buf; 60.263 - // first reserve enough address space in advance since we want to be 60.264 - // able to break a single contiguous virtual address range into multiple 60.265 - // large page commits but WS2003 does not allow reserving large page space 60.266 - // so we just use 4K pages for reserve, this gives us a legal contiguous 60.267 - // address space. then we will deallocate that reservation, and re alloc 60.268 - // using large pages 60.269 - const size_t size_of_reserve = bytes + _large_page_size; 60.270 - if (bytes > size_of_reserve) { 60.271 - // Overflowed. 60.272 - warning("Individually allocated large pages failed, " 60.273 - "use -XX:-UseLargePagesIndividualAllocation to turn off"); 60.274 + char * p_buf = allocate_pages_individually(bytes, addr, flags, prot, LargePagesIndividualAllocationInjectError); 60.275 + if (p_buf == NULL) { 60.276 + // give an appropriate warning message 60.277 + if (UseNUMAInterleaving) { 60.278 + warning("NUMA large page allocation failed, UseLargePages flag ignored"); 60.279 + } 60.280 + if (UseLargePagesIndividualAllocation) { 60.281 + warning("Individually allocated large pages failed, " 60.282 + "use -XX:-UseLargePagesIndividualAllocation to turn off"); 60.283 + } 60.284 return NULL; 60.285 } 60.286 - p_buf = (char *) VirtualAlloc(addr, 60.287 - size_of_reserve, // size of Reserve 60.288 - MEM_RESERVE, 60.289 - PAGE_READWRITE); 60.290 - // If reservation failed, return NULL 60.291 - if (p_buf == NULL) return NULL; 60.292 - 60.293 - release_memory(p_buf, bytes + _large_page_size); 60.294 - // round up to page boundary. If the size_of_reserve did not 60.295 - // overflow and the reservation did not fail, this align up 60.296 - // should not overflow. 60.297 - p_buf = (char *) align_size_up((size_t)p_buf, _large_page_size); 60.298 - 60.299 - // now go through and allocate one page at a time until all bytes are 60.300 - // allocated 60.301 - size_t bytes_remaining = align_size_up(bytes, _large_page_size); 60.302 - // An overflow of align_size_up() would have been caught above 60.303 - // in the calculation of size_of_reserve. 60.304 - char * next_alloc_addr = p_buf; 60.305 - 60.306 -#ifdef ASSERT 60.307 - // Variable for the failure injection 60.308 - long ran_num = os::random(); 60.309 - size_t fail_after = ran_num % bytes; 60.310 -#endif 60.311 - 60.312 - while (bytes_remaining) { 60.313 - size_t bytes_to_rq = MIN2(bytes_remaining, _large_page_size); 60.314 - // Note allocate and commit 60.315 - char * p_new; 60.316 - 60.317 -#ifdef ASSERT 60.318 - bool inject_error = LargePagesIndividualAllocationInjectError && 60.319 - (bytes_remaining <= fail_after); 60.320 -#else 60.321 - const bool inject_error = false; 60.322 -#endif 60.323 - 60.324 - if (inject_error) { 60.325 - p_new = NULL; 60.326 - } else { 60.327 - p_new = (char *) VirtualAlloc(next_alloc_addr, 60.328 - bytes_to_rq, 60.329 - MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, 60.330 - prot); 60.331 - } 60.332 - 60.333 - if (p_new == NULL) { 60.334 - // Free any allocated pages 60.335 - if (next_alloc_addr > p_buf) { 60.336 - // Some memory was committed so release it. 60.337 - size_t bytes_to_release = bytes - bytes_remaining; 60.338 - release_memory(p_buf, bytes_to_release); 60.339 - } 60.340 -#ifdef ASSERT 60.341 - if (UseLargePagesIndividualAllocation && 60.342 - LargePagesIndividualAllocationInjectError) { 60.343 - if (TracePageSizes && Verbose) { 60.344 - tty->print_cr("Reserving large pages individually failed."); 60.345 - } 60.346 - } 60.347 -#endif 60.348 - return NULL; 60.349 - } 60.350 - bytes_remaining -= bytes_to_rq; 60.351 - next_alloc_addr += bytes_to_rq; 60.352 - } 60.353 60.354 return p_buf; 60.355 60.356 @@ -2867,14 +3021,43 @@ 60.357 assert(bytes % os::vm_page_size() == 0, "commit in page-sized chunks"); 60.358 // Don't attempt to print anything if the OS call fails. We're 60.359 // probably low on resources, so the print itself may cause crashes. 60.360 - bool result = VirtualAlloc(addr, bytes, MEM_COMMIT, PAGE_READWRITE) != 0; 60.361 - if (result != NULL && exec) { 60.362 - DWORD oldprot; 60.363 - // Windows doc says to use VirtualProtect to get execute permissions 60.364 - return VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE, &oldprot) != 0; 60.365 + 60.366 + // unless we have NUMAInterleaving enabled, the range of a commit 60.367 + // is always within a reserve covered by a single VirtualAlloc 60.368 + // in that case we can just do a single commit for the requested size 60.369 + if (!UseNUMAInterleaving) { 60.370 + if (VirtualAlloc(addr, bytes, MEM_COMMIT, PAGE_READWRITE) == NULL) return false; 60.371 + if (exec) { 60.372 + DWORD oldprot; 60.373 + // Windows doc says to use VirtualProtect to get execute permissions 60.374 + if (!VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE, &oldprot)) return false; 60.375 + } 60.376 + return true; 60.377 } else { 60.378 - return result; 60.379 - } 60.380 + 60.381 + // when NUMAInterleaving is enabled, the commit might cover a range that 60.382 + // came from multiple VirtualAlloc reserves (using allocate_pages_individually). 60.383 + // VirtualQuery can help us determine that. The RegionSize that VirtualQuery 60.384 + // returns represents the number of bytes that can be committed in one step. 60.385 + size_t bytes_remaining = bytes; 60.386 + char * next_alloc_addr = addr; 60.387 + while (bytes_remaining > 0) { 60.388 + MEMORY_BASIC_INFORMATION alloc_info; 60.389 + VirtualQuery(next_alloc_addr, &alloc_info, sizeof(alloc_info)); 60.390 + size_t bytes_to_rq = MIN2(bytes_remaining, (size_t)alloc_info.RegionSize); 60.391 + if (VirtualAlloc(next_alloc_addr, bytes_to_rq, MEM_COMMIT, PAGE_READWRITE) == NULL) 60.392 + return false; 60.393 + if (exec) { 60.394 + DWORD oldprot; 60.395 + if (!VirtualProtect(next_alloc_addr, bytes_to_rq, PAGE_EXECUTE_READWRITE, &oldprot)) 60.396 + return false; 60.397 + } 60.398 + bytes_remaining -= bytes_to_rq; 60.399 + next_alloc_addr += bytes_to_rq; 60.400 + } 60.401 + } 60.402 + // if we made it this far, return true 60.403 + return true; 60.404 } 60.405 60.406 bool os::commit_memory(char* addr, size_t size, size_t alignment_hint, 60.407 @@ -2948,14 +3131,21 @@ 60.408 void os::numa_make_global(char *addr, size_t bytes) { } 60.409 void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { } 60.410 bool os::numa_topology_changed() { return false; } 60.411 -size_t os::numa_get_groups_num() { return 1; } 60.412 +size_t os::numa_get_groups_num() { return MAX2(numa_node_list_holder.get_count(), 1); } 60.413 int os::numa_get_group_id() { return 0; } 60.414 size_t os::numa_get_leaf_groups(int *ids, size_t size) { 60.415 - if (size > 0) { 60.416 + if (numa_node_list_holder.get_count() == 0 && size > 0) { 60.417 + // Provide an answer for UMA systems 60.418 ids[0] = 0; 60.419 return 1; 60.420 - } 60.421 - return 0; 60.422 + } else { 60.423 + // check for size bigger than actual groups_num 60.424 + size = MIN2(size, numa_get_groups_num()); 60.425 + for (int i = 0; i < (int)size; i++) { 60.426 + ids[i] = numa_node_list_holder.get_node_list_entry(i); 60.427 + } 60.428 + return size; 60.429 + } 60.430 } 60.431 60.432 bool os::get_page_info(char *start, page_info* info) { 60.433 @@ -3480,7 +3670,7 @@ 60.434 if(Verbose && PrintMiscellaneous) 60.435 tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page); 60.436 #endif 60.437 -} 60.438 + } 60.439 60.440 os::large_page_init(); 60.441 60.442 @@ -3584,7 +3774,13 @@ 60.443 prio_init(); 60.444 60.445 if (UseNUMA && !ForceNUMA) { 60.446 - UseNUMA = false; // Currently unsupported. 60.447 + UseNUMA = false; // We don't fully support this yet 60.448 + } 60.449 + 60.450 + if (UseNUMAInterleaving) { 60.451 + // first check whether this Windows OS supports VirtualAllocExNuma, if not ignore this flag 60.452 + bool success = numa_interleaving_init(); 60.453 + if (!success) UseNUMAInterleaving = false; 60.454 } 60.455 60.456 return JNI_OK; 60.457 @@ -4758,7 +4954,14 @@ 60.458 60.459 // Kernel32 API 60.460 typedef SIZE_T (WINAPI* GetLargePageMinimum_Fn)(void); 60.461 +typedef LPVOID (WINAPI *VirtualAllocExNuma_Fn) (HANDLE, LPVOID, SIZE_T, DWORD, DWORD, DWORD); 60.462 +typedef BOOL (WINAPI *GetNumaHighestNodeNumber_Fn) (PULONG); 60.463 +typedef BOOL (WINAPI *GetNumaNodeProcessorMask_Fn) (UCHAR, PULONGLONG); 60.464 + 60.465 GetLargePageMinimum_Fn os::Kernel32Dll::_GetLargePageMinimum = NULL; 60.466 +VirtualAllocExNuma_Fn os::Kernel32Dll::_VirtualAllocExNuma = NULL; 60.467 +GetNumaHighestNodeNumber_Fn os::Kernel32Dll::_GetNumaHighestNodeNumber = NULL; 60.468 +GetNumaNodeProcessorMask_Fn os::Kernel32Dll::_GetNumaNodeProcessorMask = NULL; 60.469 BOOL os::Kernel32Dll::initialized = FALSE; 60.470 SIZE_T os::Kernel32Dll::GetLargePageMinimum() { 60.471 assert(initialized && _GetLargePageMinimum != NULL, 60.472 @@ -4773,19 +4976,56 @@ 60.473 return _GetLargePageMinimum != NULL; 60.474 } 60.475 60.476 - 60.477 -#ifndef JDK6_OR_EARLIER 60.478 - 60.479 -void os::Kernel32Dll::initialize() { 60.480 +BOOL os::Kernel32Dll::NumaCallsAvailable() { 60.481 + if (!initialized) { 60.482 + initialize(); 60.483 + } 60.484 + return _VirtualAllocExNuma != NULL; 60.485 +} 60.486 + 60.487 +LPVOID os::Kernel32Dll::VirtualAllocExNuma(HANDLE hProc, LPVOID addr, SIZE_T bytes, DWORD flags, DWORD prot, DWORD node) { 60.488 + assert(initialized && _VirtualAllocExNuma != NULL, 60.489 + "NUMACallsAvailable() not yet called"); 60.490 + 60.491 + return _VirtualAllocExNuma(hProc, addr, bytes, flags, prot, node); 60.492 +} 60.493 + 60.494 +BOOL os::Kernel32Dll::GetNumaHighestNodeNumber(PULONG ptr_highest_node_number) { 60.495 + assert(initialized && _GetNumaHighestNodeNumber != NULL, 60.496 + "NUMACallsAvailable() not yet called"); 60.497 + 60.498 + return _GetNumaHighestNodeNumber(ptr_highest_node_number); 60.499 +} 60.500 + 60.501 +BOOL os::Kernel32Dll::GetNumaNodeProcessorMask(UCHAR node, PULONGLONG proc_mask) { 60.502 + assert(initialized && _GetNumaNodeProcessorMask != NULL, 60.503 + "NUMACallsAvailable() not yet called"); 60.504 + 60.505 + return _GetNumaNodeProcessorMask(node, proc_mask); 60.506 +} 60.507 + 60.508 + 60.509 +void os::Kernel32Dll::initializeCommon() { 60.510 if (!initialized) { 60.511 HMODULE handle = ::GetModuleHandle("Kernel32.dll"); 60.512 assert(handle != NULL, "Just check"); 60.513 _GetLargePageMinimum = (GetLargePageMinimum_Fn)::GetProcAddress(handle, "GetLargePageMinimum"); 60.514 + _VirtualAllocExNuma = (VirtualAllocExNuma_Fn)::GetProcAddress(handle, "VirtualAllocExNuma"); 60.515 + _GetNumaHighestNodeNumber = (GetNumaHighestNodeNumber_Fn)::GetProcAddress(handle, "GetNumaHighestNodeNumber"); 60.516 + _GetNumaNodeProcessorMask = (GetNumaNodeProcessorMask_Fn)::GetProcAddress(handle, "GetNumaNodeProcessorMask"); 60.517 initialized = TRUE; 60.518 } 60.519 } 60.520 60.521 60.522 + 60.523 +#ifndef JDK6_OR_EARLIER 60.524 + 60.525 +void os::Kernel32Dll::initialize() { 60.526 + initializeCommon(); 60.527 +} 60.528 + 60.529 + 60.530 // Kernel32 API 60.531 inline BOOL os::Kernel32Dll::SwitchToThread() { 60.532 return ::SwitchToThread(); 60.533 @@ -4887,18 +5127,19 @@ 60.534 Module32Next_Fn os::Kernel32Dll::_Module32Next = NULL; 60.535 GetNativeSystemInfo_Fn os::Kernel32Dll::_GetNativeSystemInfo = NULL; 60.536 60.537 + 60.538 void os::Kernel32Dll::initialize() { 60.539 if (!initialized) { 60.540 HMODULE handle = ::GetModuleHandle("Kernel32.dll"); 60.541 assert(handle != NULL, "Just check"); 60.542 60.543 _SwitchToThread = (SwitchToThread_Fn)::GetProcAddress(handle, "SwitchToThread"); 60.544 - _GetLargePageMinimum = (GetLargePageMinimum_Fn)::GetProcAddress(handle, "GetLargePageMinimum"); 60.545 _CreateToolhelp32Snapshot = (CreateToolhelp32Snapshot_Fn) 60.546 ::GetProcAddress(handle, "CreateToolhelp32Snapshot"); 60.547 _Module32First = (Module32First_Fn)::GetProcAddress(handle, "Module32First"); 60.548 _Module32Next = (Module32Next_Fn)::GetProcAddress(handle, "Module32Next"); 60.549 _GetNativeSystemInfo = (GetNativeSystemInfo_Fn)::GetProcAddress(handle, "GetNativeSystemInfo"); 60.550 + initializeCommon(); // resolve the functions that always need resolving 60.551 60.552 initialized = TRUE; 60.553 } 60.554 @@ -4964,6 +5205,8 @@ 60.555 _GetNativeSystemInfo(lpSystemInfo); 60.556 } 60.557 60.558 + 60.559 + 60.560 // PSAPI API 60.561 60.562
61.1 --- a/src/os/windows/vm/os_windows.hpp Thu Sep 08 16:59:27 2011 -0700 61.2 +++ b/src/os/windows/vm/os_windows.hpp Fri Sep 09 16:17:16 2011 -0700 61.3 @@ -173,13 +173,25 @@ 61.4 static BOOL GetNativeSystemInfoAvailable(); 61.5 static void GetNativeSystemInfo(LPSYSTEM_INFO); 61.6 61.7 + // NUMA calls 61.8 + static BOOL NumaCallsAvailable(); 61.9 + static LPVOID VirtualAllocExNuma(HANDLE, LPVOID, SIZE_T, DWORD, DWORD, DWORD); 61.10 + static BOOL GetNumaHighestNodeNumber(PULONG); 61.11 + static BOOL GetNumaNodeProcessorMask(UCHAR, PULONGLONG); 61.12 + 61.13 private: 61.14 // GetLargePageMinimum available on Windows Vista/Windows Server 2003 61.15 // and later 61.16 + // NUMA calls available Windows Vista/WS2008 and later 61.17 + 61.18 static SIZE_T (WINAPI *_GetLargePageMinimum)(void); 61.19 + static LPVOID (WINAPI *_VirtualAllocExNuma) (HANDLE, LPVOID, SIZE_T, DWORD, DWORD, DWORD); 61.20 + static BOOL (WINAPI *_GetNumaHighestNodeNumber) (PULONG); 61.21 + static BOOL (WINAPI *_GetNumaNodeProcessorMask) (UCHAR, PULONGLONG); 61.22 static BOOL initialized; 61.23 61.24 static void initialize(); 61.25 + static void initializeCommon(); 61.26 61.27 #ifdef JDK6_OR_EARLIER 61.28 private:
62.1 --- a/src/share/vm/c1/c1_Compilation.cpp Thu Sep 08 16:59:27 2011 -0700 62.2 +++ b/src/share/vm/c1/c1_Compilation.cpp Fri Sep 09 16:17:16 2011 -0700 62.3 @@ -346,7 +346,6 @@ 62.4 implicit_exception_table(), 62.5 compiler(), 62.6 _env->comp_level(), 62.7 - true, 62.8 has_unsafe_access() 62.9 ); 62.10 }
63.1 --- a/src/share/vm/c1/c1_GraphBuilder.cpp Thu Sep 08 16:59:27 2011 -0700 63.2 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Fri Sep 09 16:17:16 2011 -0700 63.3 @@ -28,8 +28,10 @@ 63.4 #include "c1/c1_Compilation.hpp" 63.5 #include "c1/c1_GraphBuilder.hpp" 63.6 #include "c1/c1_InstructionPrinter.hpp" 63.7 +#include "ci/ciCallSite.hpp" 63.8 #include "ci/ciField.hpp" 63.9 #include "ci/ciKlass.hpp" 63.10 +#include "ci/ciMethodHandle.hpp" 63.11 #include "compiler/compileBroker.hpp" 63.12 #include "interpreter/bytecode.hpp" 63.13 #include "runtime/sharedRuntime.hpp" 63.14 @@ -1424,7 +1426,7 @@ 63.15 // See whether this is the first return; if so, store off some 63.16 // of the state for later examination 63.17 if (num_returns() == 0) { 63.18 - set_inline_cleanup_info(_block, _last, state()); 63.19 + set_inline_cleanup_info(); 63.20 } 63.21 63.22 // The current bci() is in the wrong scope, so use the bci() of 63.23 @@ -1582,6 +1584,8 @@ 63.24 code = Bytecodes::_invokespecial; 63.25 } 63.26 63.27 + bool is_invokedynamic = code == Bytecodes::_invokedynamic; 63.28 + 63.29 // NEEDS_CLEANUP 63.30 // I've added the target-is_loaded() test below but I don't really understand 63.31 // how klass->is_loaded() can be true and yet target->is_loaded() is false. 63.32 @@ -1693,26 +1697,31 @@ 63.33 && target->will_link(klass, callee_holder, code)) { 63.34 // callee is known => check if we have static binding 63.35 assert(target->is_loaded(), "callee must be known"); 63.36 - if (code == Bytecodes::_invokestatic 63.37 - || code == Bytecodes::_invokespecial 63.38 - || code == Bytecodes::_invokevirtual && target->is_final_method() 63.39 - ) { 63.40 - // static binding => check if callee is ok 63.41 - ciMethod* inline_target = (cha_monomorphic_target != NULL) 63.42 - ? cha_monomorphic_target 63.43 - : target; 63.44 - bool res = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL)); 63.45 + if (code == Bytecodes::_invokestatic || 63.46 + code == Bytecodes::_invokespecial || 63.47 + code == Bytecodes::_invokevirtual && target->is_final_method() || 63.48 + code == Bytecodes::_invokedynamic) { 63.49 + ciMethod* inline_target = (cha_monomorphic_target != NULL) ? cha_monomorphic_target : target; 63.50 + bool success = false; 63.51 + if (target->is_method_handle_invoke()) { 63.52 + // method handle invokes 63.53 + success = !is_invokedynamic ? for_method_handle_inline(target) : for_invokedynamic_inline(target); 63.54 + } 63.55 + if (!success) { 63.56 + // static binding => check if callee is ok 63.57 + success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL)); 63.58 + } 63.59 CHECK_BAILOUT(); 63.60 63.61 #ifndef PRODUCT 63.62 // printing 63.63 - if (PrintInlining && !res) { 63.64 + if (PrintInlining && !success) { 63.65 // if it was successfully inlined, then it was already printed. 63.66 - print_inline_result(inline_target, res); 63.67 + print_inline_result(inline_target, success); 63.68 } 63.69 #endif 63.70 clear_inline_bailout(); 63.71 - if (res) { 63.72 + if (success) { 63.73 // Register dependence if JVMTI has either breakpoint 63.74 // setting or hotswapping of methods capabilities since they may 63.75 // cause deoptimization. 63.76 @@ -1740,7 +1749,6 @@ 63.77 code == Bytecodes::_invokespecial || 63.78 code == Bytecodes::_invokevirtual || 63.79 code == Bytecodes::_invokeinterface; 63.80 - bool is_invokedynamic = code == Bytecodes::_invokedynamic; 63.81 ValueType* result_type = as_ValueType(target->return_type()); 63.82 63.83 // We require the debug info to be the "state before" because 63.84 @@ -3038,7 +3046,7 @@ 63.85 INLINE_BAILOUT("disallowed by CompilerOracle") 63.86 } else if (!callee->can_be_compiled()) { 63.87 // callee is not compilable (prob. has breakpoints) 63.88 - INLINE_BAILOUT("not compilable") 63.89 + INLINE_BAILOUT("not compilable (disabled)") 63.90 } else if (callee->intrinsic_id() != vmIntrinsics::_none && try_inline_intrinsics(callee)) { 63.91 // intrinsics can be native or not 63.92 return true; 63.93 @@ -3397,7 +3405,7 @@ 63.94 } 63.95 63.96 63.97 -bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) { 63.98 +bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, BlockBegin* cont_block) { 63.99 assert(!callee->is_native(), "callee must not be native"); 63.100 if (CompilationPolicy::policy()->should_not_inline(compilation()->env(), callee)) { 63.101 INLINE_BAILOUT("inlining prohibited by policy"); 63.102 @@ -3430,7 +3438,7 @@ 63.103 } else { 63.104 if (inline_level() > MaxInlineLevel ) INLINE_BAILOUT("too-deep inlining"); 63.105 if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("too-deep recursive inlining"); 63.106 - if (callee->code_size() > max_inline_size() ) INLINE_BAILOUT("callee is too large"); 63.107 + if (callee->code_size_for_inlining() > max_inline_size() ) INLINE_BAILOUT("callee is too large"); 63.108 63.109 // don't inline throwable methods unless the inlining tree is rooted in a throwable class 63.110 if (callee->name() == ciSymbol::object_initializer_name() && 63.111 @@ -3468,7 +3476,8 @@ 63.112 63.113 // Insert null check if necessary 63.114 Value recv = NULL; 63.115 - if (code() != Bytecodes::_invokestatic) { 63.116 + if (code() != Bytecodes::_invokestatic && 63.117 + code() != Bytecodes::_invokedynamic) { 63.118 // note: null check must happen even if first instruction of callee does 63.119 // an implicit null check since the callee is in a different scope 63.120 // and we must make sure exception handling does the right thing 63.121 @@ -3496,7 +3505,7 @@ 63.122 // fall-through of control flow, all return instructions of the 63.123 // callee will need to be replaced by Goto's pointing to this 63.124 // continuation point. 63.125 - BlockBegin* cont = block_at(next_bci()); 63.126 + BlockBegin* cont = cont_block != NULL ? cont_block : block_at(next_bci()); 63.127 bool continuation_existed = true; 63.128 if (cont == NULL) { 63.129 cont = new BlockBegin(next_bci()); 63.130 @@ -3608,27 +3617,29 @@ 63.131 // block merging. This allows load elimination and CSE to take place 63.132 // across multiple callee scopes if they are relatively simple, and 63.133 // is currently essential to making inlining profitable. 63.134 - if ( num_returns() == 1 63.135 - && block() == orig_block 63.136 - && block() == inline_cleanup_block()) { 63.137 - _last = inline_cleanup_return_prev(); 63.138 - _state = inline_cleanup_state(); 63.139 - } else if (continuation_preds == cont->number_of_preds()) { 63.140 - // Inlining caused that the instructions after the invoke in the 63.141 - // caller are not reachable any more. So skip filling this block 63.142 - // with instructions! 63.143 - assert (cont == continuation(), ""); 63.144 - assert(_last && _last->as_BlockEnd(), ""); 63.145 - _skip_block = true; 63.146 - } else { 63.147 - // Resume parsing in continuation block unless it was already parsed. 63.148 - // Note that if we don't change _last here, iteration in 63.149 - // iterate_bytecodes_for_block will stop when we return. 63.150 - if (!continuation()->is_set(BlockBegin::was_visited_flag)) { 63.151 - // add continuation to work list instead of parsing it immediately 63.152 + if (cont_block == NULL) { 63.153 + if (num_returns() == 1 63.154 + && block() == orig_block 63.155 + && block() == inline_cleanup_block()) { 63.156 + _last = inline_cleanup_return_prev(); 63.157 + _state = inline_cleanup_state(); 63.158 + } else if (continuation_preds == cont->number_of_preds()) { 63.159 + // Inlining caused that the instructions after the invoke in the 63.160 + // caller are not reachable any more. So skip filling this block 63.161 + // with instructions! 63.162 + assert(cont == continuation(), ""); 63.163 assert(_last && _last->as_BlockEnd(), ""); 63.164 - scope_data()->parent()->add_to_work_list(continuation()); 63.165 _skip_block = true; 63.166 + } else { 63.167 + // Resume parsing in continuation block unless it was already parsed. 63.168 + // Note that if we don't change _last here, iteration in 63.169 + // iterate_bytecodes_for_block will stop when we return. 63.170 + if (!continuation()->is_set(BlockBegin::was_visited_flag)) { 63.171 + // add continuation to work list instead of parsing it immediately 63.172 + assert(_last && _last->as_BlockEnd(), ""); 63.173 + scope_data()->parent()->add_to_work_list(continuation()); 63.174 + _skip_block = true; 63.175 + } 63.176 } 63.177 } 63.178 63.179 @@ -3645,6 +3656,114 @@ 63.180 } 63.181 63.182 63.183 +bool GraphBuilder::for_method_handle_inline(ciMethod* callee) { 63.184 + assert(!callee->is_static(), "change next line"); 63.185 + int index = state()->stack_size() - (callee->arg_size_no_receiver() + 1); 63.186 + Value receiver = state()->stack_at(index); 63.187 + 63.188 + if (receiver->type()->is_constant()) { 63.189 + ciMethodHandle* method_handle = receiver->type()->as_ObjectType()->constant_value()->as_method_handle(); 63.190 + 63.191 + // Set the callee to have access to the class and signature in 63.192 + // the MethodHandleCompiler. 63.193 + method_handle->set_callee(callee); 63.194 + method_handle->set_caller(method()); 63.195 + 63.196 + // Get an adapter for the MethodHandle. 63.197 + ciMethod* method_handle_adapter = method_handle->get_method_handle_adapter(); 63.198 + if (method_handle_adapter != NULL) { 63.199 + return try_inline(method_handle_adapter, /*holder_known=*/ true); 63.200 + } 63.201 + } else if (receiver->as_CheckCast()) { 63.202 + // Match MethodHandle.selectAlternative idiom 63.203 + Phi* phi = receiver->as_CheckCast()->obj()->as_Phi(); 63.204 + 63.205 + if (phi != NULL && phi->operand_count() == 2) { 63.206 + // Get the two MethodHandle inputs from the Phi. 63.207 + Value op1 = phi->operand_at(0); 63.208 + Value op2 = phi->operand_at(1); 63.209 + ciMethodHandle* mh1 = op1->type()->as_ObjectType()->constant_value()->as_method_handle(); 63.210 + ciMethodHandle* mh2 = op2->type()->as_ObjectType()->constant_value()->as_method_handle(); 63.211 + 63.212 + // Set the callee to have access to the class and signature in 63.213 + // the MethodHandleCompiler. 63.214 + mh1->set_callee(callee); 63.215 + mh1->set_caller(method()); 63.216 + mh2->set_callee(callee); 63.217 + mh2->set_caller(method()); 63.218 + 63.219 + // Get adapters for the MethodHandles. 63.220 + ciMethod* mh1_adapter = mh1->get_method_handle_adapter(); 63.221 + ciMethod* mh2_adapter = mh2->get_method_handle_adapter(); 63.222 + 63.223 + if (mh1_adapter != NULL && mh2_adapter != NULL) { 63.224 + set_inline_cleanup_info(); 63.225 + 63.226 + // Build the If guard 63.227 + BlockBegin* one = new BlockBegin(next_bci()); 63.228 + BlockBegin* two = new BlockBegin(next_bci()); 63.229 + BlockBegin* end = new BlockBegin(next_bci()); 63.230 + Instruction* iff = append(new If(phi, If::eql, false, op1, one, two, NULL, false)); 63.231 + block()->set_end(iff->as_BlockEnd()); 63.232 + 63.233 + // Connect up the states 63.234 + one->merge(block()->end()->state()); 63.235 + two->merge(block()->end()->state()); 63.236 + 63.237 + // Save the state for the second inlinee 63.238 + ValueStack* state_before = copy_state_before(); 63.239 + 63.240 + // Parse first adapter 63.241 + _last = _block = one; 63.242 + if (!try_inline_full(mh1_adapter, /*holder_known=*/ true, end)) { 63.243 + restore_inline_cleanup_info(); 63.244 + block()->clear_end(); // remove appended iff 63.245 + return false; 63.246 + } 63.247 + 63.248 + // Parse second adapter 63.249 + _last = _block = two; 63.250 + _state = state_before; 63.251 + if (!try_inline_full(mh2_adapter, /*holder_known=*/ true, end)) { 63.252 + restore_inline_cleanup_info(); 63.253 + block()->clear_end(); // remove appended iff 63.254 + return false; 63.255 + } 63.256 + 63.257 + connect_to_end(end); 63.258 + return true; 63.259 + } 63.260 + } 63.261 + } 63.262 + return false; 63.263 +} 63.264 + 63.265 + 63.266 +bool GraphBuilder::for_invokedynamic_inline(ciMethod* callee) { 63.267 + // Get the MethodHandle from the CallSite. 63.268 + ciCallSite* call_site = stream()->get_call_site(); 63.269 + ciMethodHandle* method_handle = call_site->get_target(); 63.270 + 63.271 + // Set the callee to have access to the class and signature in the 63.272 + // MethodHandleCompiler. 63.273 + method_handle->set_callee(callee); 63.274 + method_handle->set_caller(method()); 63.275 + 63.276 + // Get an adapter for the MethodHandle. 63.277 + ciMethod* method_handle_adapter = method_handle->get_invokedynamic_adapter(); 63.278 + if (method_handle_adapter != NULL) { 63.279 + if (try_inline(method_handle_adapter, /*holder_known=*/ true)) { 63.280 + // Add a dependence for invalidation of the optimization. 63.281 + if (!call_site->is_constant_call_site()) { 63.282 + dependency_recorder()->assert_call_site_target_value(call_site, method_handle); 63.283 + } 63.284 + return true; 63.285 + } 63.286 + } 63.287 + return false; 63.288 +} 63.289 + 63.290 + 63.291 void GraphBuilder::inline_bailout(const char* msg) { 63.292 assert(msg != NULL, "inline bailout msg must exist"); 63.293 _inline_bailout_msg = msg;
64.1 --- a/src/share/vm/c1/c1_GraphBuilder.hpp Thu Sep 08 16:59:27 2011 -0700 64.2 +++ b/src/share/vm/c1/c1_GraphBuilder.hpp Fri Sep 09 16:17:16 2011 -0700 64.3 @@ -1,5 +1,5 @@ 64.4 /* 64.5 - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 64.6 + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. 64.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 64.8 * 64.9 * This code is free software; you can redistribute it and/or modify it 64.10 @@ -315,9 +315,17 @@ 64.11 ValueStack* return_state) { scope_data()->set_inline_cleanup_info(block, 64.12 return_prev, 64.13 return_state); } 64.14 + void set_inline_cleanup_info() { 64.15 + set_inline_cleanup_info(_block, _last, _state); 64.16 + } 64.17 BlockBegin* inline_cleanup_block() const { return scope_data()->inline_cleanup_block(); } 64.18 Instruction* inline_cleanup_return_prev() const { return scope_data()->inline_cleanup_return_prev(); } 64.19 ValueStack* inline_cleanup_state() const { return scope_data()->inline_cleanup_state(); } 64.20 + void restore_inline_cleanup_info() { 64.21 + _block = inline_cleanup_block(); 64.22 + _last = inline_cleanup_return_prev(); 64.23 + _state = inline_cleanup_state(); 64.24 + } 64.25 void incr_num_returns() { scope_data()->incr_num_returns(); } 64.26 int num_returns() const { return scope_data()->num_returns(); } 64.27 intx max_inline_size() const { return scope_data()->max_inline_size(); } 64.28 @@ -329,11 +337,15 @@ 64.29 void fill_sync_handler(Value lock, BlockBegin* sync_handler, bool default_handler = false); 64.30 64.31 // inliners 64.32 - bool try_inline(ciMethod* callee, bool holder_known); 64.33 + bool try_inline( ciMethod* callee, bool holder_known); 64.34 bool try_inline_intrinsics(ciMethod* callee); 64.35 - bool try_inline_full (ciMethod* callee, bool holder_known); 64.36 + bool try_inline_full( ciMethod* callee, bool holder_known, BlockBegin* cont_block = NULL); 64.37 bool try_inline_jsr(int jsr_dest_bci); 64.38 64.39 + // JSR 292 support 64.40 + bool for_method_handle_inline(ciMethod* callee); 64.41 + bool for_invokedynamic_inline(ciMethod* callee); 64.42 + 64.43 // helpers 64.44 void inline_bailout(const char* msg); 64.45 BlockBegin* header_block(BlockBegin* entry, BlockBegin::Flag f, ValueStack* state);
65.1 --- a/src/share/vm/c1/c1_Instruction.cpp Thu Sep 08 16:59:27 2011 -0700 65.2 +++ b/src/share/vm/c1/c1_Instruction.cpp Fri Sep 09 16:17:16 2011 -0700 65.3 @@ -514,28 +514,17 @@ 65.4 65.5 void BlockBegin::set_end(BlockEnd* end) { 65.6 assert(end != NULL, "should not reset block end to NULL"); 65.7 - BlockEnd* old_end = _end; 65.8 - if (end == old_end) { 65.9 + if (end == _end) { 65.10 return; 65.11 } 65.12 - // Must make the predecessors/successors match up with the 65.13 - // BlockEnd's notion. 65.14 - int i, n; 65.15 - if (old_end != NULL) { 65.16 - // disconnect from the old end 65.17 - old_end->set_begin(NULL); 65.18 + clear_end(); 65.19 65.20 - // disconnect this block from it's current successors 65.21 - for (i = 0; i < _successors.length(); i++) { 65.22 - _successors.at(i)->remove_predecessor(this); 65.23 - } 65.24 - } 65.25 + // Set the new end 65.26 _end = end; 65.27 65.28 _successors.clear(); 65.29 // Now reset successors list based on BlockEnd 65.30 - n = end->number_of_sux(); 65.31 - for (i = 0; i < n; i++) { 65.32 + for (int i = 0; i < end->number_of_sux(); i++) { 65.33 BlockBegin* sux = end->sux_at(i); 65.34 _successors.append(sux); 65.35 sux->_predecessors.append(this); 65.36 @@ -544,6 +533,22 @@ 65.37 } 65.38 65.39 65.40 +void BlockBegin::clear_end() { 65.41 + // Must make the predecessors/successors match up with the 65.42 + // BlockEnd's notion. 65.43 + if (_end != NULL) { 65.44 + // disconnect from the old end 65.45 + _end->set_begin(NULL); 65.46 + 65.47 + // disconnect this block from it's current successors 65.48 + for (int i = 0; i < _successors.length(); i++) { 65.49 + _successors.at(i)->remove_predecessor(this); 65.50 + } 65.51 + _end = NULL; 65.52 + } 65.53 +} 65.54 + 65.55 + 65.56 void BlockBegin::disconnect_edge(BlockBegin* from, BlockBegin* to) { 65.57 // disconnect any edges between from and to 65.58 #ifndef PRODUCT
66.1 --- a/src/share/vm/c1/c1_Instruction.hpp Thu Sep 08 16:59:27 2011 -0700 66.2 +++ b/src/share/vm/c1/c1_Instruction.hpp Fri Sep 09 16:17:16 2011 -0700 66.3 @@ -1601,6 +1601,7 @@ 66.4 void set_depth_first_number(int dfn) { _depth_first_number = dfn; } 66.5 void set_linear_scan_number(int lsn) { _linear_scan_number = lsn; } 66.6 void set_end(BlockEnd* end); 66.7 + void clear_end(); 66.8 void disconnect_from_graph(); 66.9 static void disconnect_edge(BlockBegin* from, BlockBegin* to); 66.10 BlockBegin* insert_block_between(BlockBegin* sux);
67.1 --- a/src/share/vm/c1/c1_LIRAssembler.cpp Thu Sep 08 16:59:27 2011 -0700 67.2 +++ b/src/share/vm/c1/c1_LIRAssembler.cpp Fri Sep 09 16:17:16 2011 -0700 67.3 @@ -121,7 +121,7 @@ 67.4 67.5 void LIR_Assembler::check_codespace() { 67.6 CodeSection* cs = _masm->code_section(); 67.7 - if (cs->remaining() < (int)(1*K)) { 67.8 + if (cs->remaining() < (int)(NOT_LP64(1*K)LP64_ONLY(2*K))) { 67.9 BAILOUT("CodeBuffer overflow"); 67.10 } 67.11 }
68.1 --- a/src/share/vm/c1/c1_LIRAssembler.hpp Thu Sep 08 16:59:27 2011 -0700 68.2 +++ b/src/share/vm/c1/c1_LIRAssembler.hpp Fri Sep 09 16:17:16 2011 -0700 68.3 @@ -133,7 +133,6 @@ 68.4 static bool is_small_constant(LIR_Opr opr); 68.5 68.6 static LIR_Opr receiverOpr(); 68.7 - static LIR_Opr incomingReceiverOpr(); 68.8 static LIR_Opr osrBufferPointer(); 68.9 68.10 // stubs
69.1 --- a/src/share/vm/c1/c1_LinearScan.cpp Thu Sep 08 16:59:27 2011 -0700 69.2 +++ b/src/share/vm/c1/c1_LinearScan.cpp Fri Sep 09 16:17:16 2011 -0700 69.3 @@ -2404,7 +2404,7 @@ 69.4 assert(!is_call_site || assigned_reg >= nof_regs || !is_caller_save(assigned_reg), "interval is in a caller-save register at a call -> register will be overwritten"); 69.5 69.6 VMReg name = vm_reg_for_interval(interval); 69.7 - map->set_oop(name); 69.8 + set_oop(map, name); 69.9 69.10 // Spill optimization: when the stack value is guaranteed to be always correct, 69.11 // then it must be added to the oop map even if the interval is currently in a register 69.12 @@ -2415,7 +2415,7 @@ 69.13 assert(interval->canonical_spill_slot() >= LinearScan::nof_regs, "no spill slot assigned"); 69.14 assert(interval->assigned_reg() < LinearScan::nof_regs, "interval is on stack, so stack slot is registered twice"); 69.15 69.16 - map->set_oop(frame_map()->slot_regname(interval->canonical_spill_slot() - LinearScan::nof_regs)); 69.17 + set_oop(map, frame_map()->slot_regname(interval->canonical_spill_slot() - LinearScan::nof_regs)); 69.18 } 69.19 } 69.20 } 69.21 @@ -2424,7 +2424,7 @@ 69.22 assert(info->stack() != NULL, "CodeEmitInfo must always have a stack"); 69.23 int locks_count = info->stack()->total_locks_size(); 69.24 for (int i = 0; i < locks_count; i++) { 69.25 - map->set_oop(frame_map()->monitor_object_regname(i)); 69.26 + set_oop(map, frame_map()->monitor_object_regname(i)); 69.27 } 69.28 69.29 return map;
70.1 --- a/src/share/vm/c1/c1_LinearScan.hpp Thu Sep 08 16:59:27 2011 -0700 70.2 +++ b/src/share/vm/c1/c1_LinearScan.hpp Fri Sep 09 16:17:16 2011 -0700 70.3 @@ -352,6 +352,13 @@ 70.4 70.5 MonitorValue* location_for_monitor_index(int monitor_index); 70.6 LocationValue* location_for_name(int name, Location::Type loc_type); 70.7 + void set_oop(OopMap* map, VMReg name) { 70.8 + if (map->legal_vm_reg_name(name)) { 70.9 + map->set_oop(name); 70.10 + } else { 70.11 + bailout("illegal oopMap register name"); 70.12 + } 70.13 + } 70.14 70.15 int append_scope_value_for_constant(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values); 70.16 int append_scope_value_for_operand(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values);
71.1 --- a/src/share/vm/c1/c1_Runtime1.cpp Thu Sep 08 16:59:27 2011 -0700 71.2 +++ b/src/share/vm/c1/c1_Runtime1.cpp Fri Sep 09 16:17:16 2011 -0700 71.3 @@ -375,14 +375,6 @@ 71.4 JRT_END 71.5 71.6 71.7 -JRT_ENTRY(void, Runtime1::post_jvmti_exception_throw(JavaThread* thread)) 71.8 - if (JvmtiExport::can_post_on_exceptions()) { 71.9 - vframeStream vfst(thread, true); 71.10 - address bcp = vfst.method()->bcp_from(vfst.bci()); 71.11 - JvmtiExport::post_exception_throw(thread, vfst.method(), bcp, thread->exception_oop()); 71.12 - } 71.13 -JRT_END 71.14 - 71.15 // counter_overflow() is called from within C1-compiled methods. The enclosing method is the method 71.16 // associated with the top activation record. The inlinee (that is possibly included in the enclosing 71.17 // method) method oop is passed as an argument. In order to do that it is embedded in the code as
72.1 --- a/src/share/vm/c1/c1_Runtime1.hpp Thu Sep 08 16:59:27 2011 -0700 72.2 +++ b/src/share/vm/c1/c1_Runtime1.hpp Fri Sep 09 16:17:16 2011 -0700 72.3 @@ -65,7 +65,6 @@ 72.4 stub(monitorexit_nofpu) /* optimized version that does not preserve fpu registers */ \ 72.5 stub(access_field_patching) \ 72.6 stub(load_klass_patching) \ 72.7 - stub(jvmti_exception_throw) \ 72.8 stub(g1_pre_barrier_slow) \ 72.9 stub(g1_post_barrier_slow) \ 72.10 stub(fpu2long_stub) \ 72.11 @@ -141,7 +140,6 @@ 72.12 static void unimplemented_entry (JavaThread* thread, StubID id); 72.13 72.14 static address exception_handler_for_pc(JavaThread* thread); 72.15 - static void post_jvmti_exception_throw(JavaThread* thread); 72.16 72.17 static void throw_range_check_exception(JavaThread* thread, int index); 72.18 static void throw_index_exception(JavaThread* thread, int index);
73.1 --- a/src/share/vm/c1/c1_globals.hpp Thu Sep 08 16:59:27 2011 -0700 73.2 +++ b/src/share/vm/c1/c1_globals.hpp Fri Sep 09 16:17:16 2011 -0700 73.3 @@ -278,7 +278,7 @@ 73.4 product(intx, CompilationRepeat, 0, \ 73.5 "Number of times to recompile method before returning result") \ 73.6 \ 73.7 - develop(intx, NMethodSizeLimit, (32*K)*wordSize, \ 73.8 + develop(intx, NMethodSizeLimit, (64*K)*wordSize, \ 73.9 "Maximum size of a compiled method.") \ 73.10 \ 73.11 develop(bool, TraceFPUStack, false, \
74.1 --- a/src/share/vm/ci/ciCallProfile.hpp Thu Sep 08 16:59:27 2011 -0700 74.2 +++ b/src/share/vm/ci/ciCallProfile.hpp Fri Sep 09 16:17:16 2011 -0700 74.3 @@ -79,6 +79,17 @@ 74.4 assert(i < _limit, "out of Call Profile MorphismLimit"); 74.5 return _receiver[i]; 74.6 } 74.7 + 74.8 + // Rescale the current profile based on the incoming scale 74.9 + ciCallProfile rescale(double scale) { 74.10 + assert(scale >= 0 && scale <= 1.0, "out of range"); 74.11 + ciCallProfile call = *this; 74.12 + call._count = (int)(call._count * scale); 74.13 + for (int i = 0; i < _morphism; i++) { 74.14 + call._receiver_count[i] = (int)(call._receiver_count[i] * scale); 74.15 + } 74.16 + return call; 74.17 + } 74.18 }; 74.19 74.20 #endif // SHARE_VM_CI_CICALLPROFILE_HPP
75.1 --- a/src/share/vm/ci/ciConstant.hpp Thu Sep 08 16:59:27 2011 -0700 75.2 +++ b/src/share/vm/ci/ciConstant.hpp Fri Sep 09 16:17:16 2011 -0700 75.3 @@ -46,9 +46,6 @@ 75.4 ciObject* _object; 75.5 } _value; 75.6 75.7 - // Implementation of the print method. 75.8 - void print_impl(outputStream* st); 75.9 - 75.10 public: 75.11 75.12 ciConstant() {
76.1 --- a/src/share/vm/ci/ciEnv.cpp Thu Sep 08 16:59:27 2011 -0700 76.2 +++ b/src/share/vm/ci/ciEnv.cpp Fri Sep 09 16:17:16 2011 -0700 76.3 @@ -884,19 +884,31 @@ 76.4 } 76.5 76.6 // ------------------------------------------------------------------ 76.7 -// ciEnv::check_for_system_dictionary_modification 76.8 -// Check for changes to the system dictionary during compilation 76.9 -// class loads, evolution, breakpoints 76.10 -void ciEnv::check_for_system_dictionary_modification(ciMethod* target) { 76.11 +// ciEnv::validate_compile_task_dependencies 76.12 +// 76.13 +// Check for changes during compilation (e.g. class loads, evolution, 76.14 +// breakpoints, call site invalidation). 76.15 +void ciEnv::validate_compile_task_dependencies(ciMethod* target) { 76.16 if (failing()) return; // no need for further checks 76.17 76.18 - // Dependencies must be checked when the system dictionary changes. 76.19 - // If logging is enabled all violated dependences will be recorded in 76.20 - // the log. In debug mode check dependencies even if the system 76.21 - // dictionary hasn't changed to verify that no invalid dependencies 76.22 - // were inserted. Any violated dependences in this case are dumped to 76.23 - // the tty. 76.24 + // First, check non-klass dependencies as we might return early and 76.25 + // not check klass dependencies if the system dictionary 76.26 + // modification counter hasn't changed (see below). 76.27 + for (Dependencies::DepStream deps(dependencies()); deps.next(); ) { 76.28 + if (deps.is_klass_type()) continue; // skip klass dependencies 76.29 + klassOop witness = deps.check_dependency(); 76.30 + if (witness != NULL) { 76.31 + record_failure("invalid non-klass dependency"); 76.32 + return; 76.33 + } 76.34 + } 76.35 76.36 + // Klass dependencies must be checked when the system dictionary 76.37 + // changes. If logging is enabled all violated dependences will be 76.38 + // recorded in the log. In debug mode check dependencies even if 76.39 + // the system dictionary hasn't changed to verify that no invalid 76.40 + // dependencies were inserted. Any violated dependences in this 76.41 + // case are dumped to the tty. 76.42 bool counter_changed = system_dictionary_modification_counter_changed(); 76.43 bool test_deps = counter_changed; 76.44 DEBUG_ONLY(test_deps = true); 76.45 @@ -904,22 +916,21 @@ 76.46 76.47 bool print_failures = false; 76.48 DEBUG_ONLY(print_failures = !counter_changed); 76.49 - 76.50 bool keep_going = (print_failures || xtty != NULL); 76.51 - 76.52 - int violated = 0; 76.53 + int klass_violations = 0; 76.54 76.55 for (Dependencies::DepStream deps(dependencies()); deps.next(); ) { 76.56 + if (!deps.is_klass_type()) continue; // skip non-klass dependencies 76.57 klassOop witness = deps.check_dependency(); 76.58 if (witness != NULL) { 76.59 - ++violated; 76.60 + klass_violations++; 76.61 if (print_failures) deps.print_dependency(witness, /*verbose=*/ true); 76.62 - // If there's no log and we're not sanity-checking, we're done. 76.63 - if (!keep_going) break; 76.64 } 76.65 + // If there's no log and we're not sanity-checking, we're done. 76.66 + if (!keep_going) break; 76.67 } 76.68 76.69 - if (violated != 0) { 76.70 + if (klass_violations != 0) { 76.71 assert(counter_changed, "failed dependencies, but counter didn't change"); 76.72 record_failure("concurrent class loading"); 76.73 } 76.74 @@ -938,7 +949,6 @@ 76.75 ImplicitExceptionTable* inc_table, 76.76 AbstractCompiler* compiler, 76.77 int comp_level, 76.78 - bool has_debug_info, 76.79 bool has_unsafe_access) { 76.80 VM_ENTRY_MARK; 76.81 nmethod* nm = NULL; 76.82 @@ -978,8 +988,8 @@ 76.83 // Encode the dependencies now, so we can check them right away. 76.84 dependencies()->encode_content_bytes(); 76.85 76.86 - // Check for {class loads, evolution, breakpoints} during compilation 76.87 - check_for_system_dictionary_modification(target); 76.88 + // Check for {class loads, evolution, breakpoints, ...} during compilation 76.89 + validate_compile_task_dependencies(target); 76.90 } 76.91 76.92 methodHandle method(THREAD, target->get_methodOop()); 76.93 @@ -1033,7 +1043,6 @@ 76.94 CompileBroker::handle_full_code_cache(); 76.95 } 76.96 } else { 76.97 - NOT_PRODUCT(nm->set_has_debug_info(has_debug_info); ) 76.98 nm->set_has_unsafe_access(has_unsafe_access); 76.99 76.100 // Record successful registration.
77.1 --- a/src/share/vm/ci/ciEnv.hpp Thu Sep 08 16:59:27 2011 -0700 77.2 +++ b/src/share/vm/ci/ciEnv.hpp Fri Sep 09 16:17:16 2011 -0700 77.3 @@ -247,9 +247,9 @@ 77.4 // Is this thread currently in the VM state? 77.5 static bool is_in_vm(); 77.6 77.7 - // Helper routine for determining the validity of a compilation 77.8 - // with respect to concurrent class loading. 77.9 - void check_for_system_dictionary_modification(ciMethod* target); 77.10 + // Helper routine for determining the validity of a compilation with 77.11 + // respect to method dependencies (e.g. concurrent class loading). 77.12 + void validate_compile_task_dependencies(ciMethod* target); 77.13 77.14 public: 77.15 enum { 77.16 @@ -317,8 +317,7 @@ 77.17 ImplicitExceptionTable* inc_table, 77.18 AbstractCompiler* compiler, 77.19 int comp_level, 77.20 - bool has_debug_info = true, 77.21 - bool has_unsafe_access = false); 77.22 + bool has_unsafe_access); 77.23 77.24 77.25 // Access to certain well known ciObjects.
78.1 --- a/src/share/vm/ci/ciField.hpp Thu Sep 08 16:59:27 2011 -0700 78.2 +++ b/src/share/vm/ci/ciField.hpp Fri Sep 09 16:17:16 2011 -0700 78.3 @@ -64,9 +64,6 @@ 78.4 // shared constructor code 78.5 void initialize_from(fieldDescriptor* fd); 78.6 78.7 - // The implementation of the print method. 78.8 - void print_impl(outputStream* st); 78.9 - 78.10 public: 78.11 ciFlags flags() { return _flags; } 78.12 78.13 @@ -178,7 +175,12 @@ 78.14 bool is_volatile () { return flags().is_volatile(); } 78.15 bool is_transient () { return flags().is_transient(); } 78.16 78.17 - bool is_call_site_target() { return ((holder() == CURRENT_ENV->CallSite_klass()) && (name() == ciSymbol::target_name())); } 78.18 + bool is_call_site_target() { 78.19 + ciInstanceKlass* callsite_klass = CURRENT_ENV->CallSite_klass(); 78.20 + if (callsite_klass == NULL) 78.21 + return false; 78.22 + return (holder()->is_subclass_of(callsite_klass) && (name() == ciSymbol::target_name())); 78.23 + } 78.24 78.25 // Debugging output 78.26 void print();
79.1 --- a/src/share/vm/ci/ciMethod.cpp Thu Sep 08 16:59:27 2011 -0700 79.2 +++ b/src/share/vm/ci/ciMethod.cpp Fri Sep 09 16:17:16 2011 -0700 79.3 @@ -1017,6 +1017,34 @@ 79.4 } 79.5 79.6 // ------------------------------------------------------------------ 79.7 +// ciMethod::code_size_for_inlining 79.8 +// 79.9 +// Code size for inlining decisions. 79.10 +// 79.11 +// Don't fully count method handle adapters against inlining budgets: 79.12 +// the metric we use here is the number of call sites in the adapter 79.13 +// as they are probably the instructions which generate some code. 79.14 +int ciMethod::code_size_for_inlining() { 79.15 + check_is_loaded(); 79.16 + 79.17 + // Method handle adapters 79.18 + if (is_method_handle_adapter()) { 79.19 + // Count call sites 79.20 + int call_site_count = 0; 79.21 + ciBytecodeStream iter(this); 79.22 + while (iter.next() != ciBytecodeStream::EOBC()) { 79.23 + if (Bytecodes::is_invoke(iter.cur_bc())) { 79.24 + call_site_count++; 79.25 + } 79.26 + } 79.27 + return call_site_count; 79.28 + } 79.29 + 79.30 + // Normal method 79.31 + return code_size(); 79.32 +} 79.33 + 79.34 +// ------------------------------------------------------------------ 79.35 // ciMethod::instructions_size 79.36 // 79.37 // This is a rough metric for "fat" methods, compared before inlining
80.1 --- a/src/share/vm/ci/ciMethod.hpp Thu Sep 08 16:59:27 2011 -0700 80.2 +++ b/src/share/vm/ci/ciMethod.hpp Fri Sep 09 16:17:16 2011 -0700 80.3 @@ -157,6 +157,9 @@ 80.4 int interpreter_invocation_count() const { check_is_loaded(); return _interpreter_invocation_count; } 80.5 int interpreter_throwout_count() const { check_is_loaded(); return _interpreter_throwout_count; } 80.6 80.7 + // Code size for inlining decisions. 80.8 + int code_size_for_inlining(); 80.9 + 80.10 int comp_level(); 80.11 int highest_osr_comp_level(); 80.12
81.1 --- a/src/share/vm/ci/ciMethodHandle.cpp Thu Sep 08 16:59:27 2011 -0700 81.2 +++ b/src/share/vm/ci/ciMethodHandle.cpp Fri Sep 09 16:17:16 2011 -0700 81.3 @@ -37,7 +37,7 @@ 81.4 // ciMethodHandle::get_adapter 81.5 // 81.6 // Return an adapter for this MethodHandle. 81.7 -ciMethod* ciMethodHandle::get_adapter_impl(bool is_invokedynamic) const { 81.8 +ciMethod* ciMethodHandle::get_adapter_impl(bool is_invokedynamic) { 81.9 VM_ENTRY_MARK; 81.10 Handle h(get_oop()); 81.11 methodHandle callee(_callee->get_methodOop()); 81.12 @@ -73,7 +73,7 @@ 81.13 // ciMethodHandle::get_adapter 81.14 // 81.15 // Return an adapter for this MethodHandle. 81.16 -ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const { 81.17 +ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) { 81.18 ciMethod* result = get_adapter_impl(is_invokedynamic); 81.19 if (result) { 81.20 // Fake up the MDO maturity. 81.21 @@ -86,11 +86,22 @@ 81.22 } 81.23 81.24 81.25 +#ifndef PRODUCT 81.26 // ------------------------------------------------------------------ 81.27 -// ciMethodHandle::print_impl 81.28 +// ciMethodHandle::print_chain_impl 81.29 // 81.30 // Implementation of the print method. 81.31 -void ciMethodHandle::print_impl(outputStream* st) { 81.32 - st->print(" type="); 81.33 - get_oop()->print(); 81.34 +void ciMethodHandle::print_chain_impl(outputStream* st) { 81.35 + ASSERT_IN_VM; 81.36 + MethodHandleChain::print(get_oop()); 81.37 } 81.38 + 81.39 + 81.40 +// ------------------------------------------------------------------ 81.41 +// ciMethodHandle::print_chain 81.42 +// 81.43 +// Implementation of the print_chain method. 81.44 +void ciMethodHandle::print_chain(outputStream* st) { 81.45 + GUARDED_VM_ENTRY(print_chain_impl(st);); 81.46 +} 81.47 +#endif
82.1 --- a/src/share/vm/ci/ciMethodHandle.hpp Thu Sep 08 16:59:27 2011 -0700 82.2 +++ b/src/share/vm/ci/ciMethodHandle.hpp Fri Sep 09 16:17:16 2011 -0700 82.3 @@ -37,19 +37,23 @@ 82.4 ciMethod* _callee; 82.5 ciMethod* _caller; 82.6 ciCallProfile _profile; 82.7 + ciMethod* _method_handle_adapter; 82.8 + ciMethod* _invokedynamic_adapter; 82.9 82.10 // Return an adapter for this MethodHandle. 82.11 - ciMethod* get_adapter_impl(bool is_invokedynamic) const; 82.12 - ciMethod* get_adapter( bool is_invokedynamic) const; 82.13 + ciMethod* get_adapter_impl(bool is_invokedynamic); 82.14 + ciMethod* get_adapter( bool is_invokedynamic); 82.15 82.16 protected: 82.17 - void print_impl(outputStream* st); 82.18 + void print_chain_impl(outputStream* st) PRODUCT_RETURN; 82.19 82.20 public: 82.21 ciMethodHandle(instanceHandle h_i) : 82.22 ciInstance(h_i), 82.23 _callee(NULL), 82.24 - _caller(NULL) 82.25 + _caller(NULL), 82.26 + _method_handle_adapter(NULL), 82.27 + _invokedynamic_adapter(NULL) 82.28 {} 82.29 82.30 // What kind of ciObject is this? 82.31 @@ -60,10 +64,22 @@ 82.32 void set_call_profile(ciCallProfile profile) { _profile = profile; } 82.33 82.34 // Return an adapter for a MethodHandle call. 82.35 - ciMethod* get_method_handle_adapter() const { return get_adapter(false); } 82.36 + ciMethod* get_method_handle_adapter() { 82.37 + if (_method_handle_adapter == NULL) { 82.38 + _method_handle_adapter = get_adapter(false); 82.39 + } 82.40 + return _method_handle_adapter; 82.41 + } 82.42 82.43 // Return an adapter for an invokedynamic call. 82.44 - ciMethod* get_invokedynamic_adapter() const { return get_adapter(true); } 82.45 + ciMethod* get_invokedynamic_adapter() { 82.46 + if (_invokedynamic_adapter == NULL) { 82.47 + _invokedynamic_adapter = get_adapter(true); 82.48 + } 82.49 + return _invokedynamic_adapter; 82.50 + } 82.51 + 82.52 + void print_chain(outputStream* st = tty) PRODUCT_RETURN; 82.53 }; 82.54 82.55 #endif // SHARE_VM_CI_CIMETHODHANDLE_HPP
83.1 --- a/src/share/vm/ci/ciObject.cpp Thu Sep 08 16:59:27 2011 -0700 83.2 +++ b/src/share/vm/ci/ciObject.cpp Fri Sep 09 16:17:16 2011 -0700 83.3 @@ -194,16 +194,26 @@ 83.4 // ciObject::should_be_constant() 83.5 bool ciObject::should_be_constant() { 83.6 if (ScavengeRootsInCode >= 2) return true; // force everybody to be a constant 83.7 - if (!JavaObjectsInPerm && !is_null_object()) { 83.8 + if (is_null_object()) return true; 83.9 + 83.10 + ciEnv* env = CURRENT_ENV; 83.11 + if (!JavaObjectsInPerm) { 83.12 // We want Strings and Classes to be embeddable by default since 83.13 // they used to be in the perm world. Not all Strings used to be 83.14 // embeddable but there's no easy way to distinguish the interned 83.15 // from the regulars ones so just treat them all that way. 83.16 - ciEnv* env = CURRENT_ENV; 83.17 if (klass() == env->String_klass() || klass() == env->Class_klass()) { 83.18 return true; 83.19 } 83.20 } 83.21 + if (EnableInvokeDynamic && 83.22 + (klass()->is_subclass_of(env->MethodHandle_klass()) || 83.23 + klass()->is_subclass_of(env->CallSite_klass()))) { 83.24 + assert(ScavengeRootsInCode >= 1, "must be"); 83.25 + // We want to treat these aggressively. 83.26 + return true; 83.27 + } 83.28 + 83.29 return handle() == NULL || is_perm(); 83.30 } 83.31
84.1 --- a/src/share/vm/ci/ciStreams.hpp Thu Sep 08 16:59:27 2011 -0700 84.2 +++ b/src/share/vm/ci/ciStreams.hpp Fri Sep 09 16:17:16 2011 -0700 84.3 @@ -129,7 +129,8 @@ 84.4 // Return current ByteCode and increment PC to next bytecode, skipping all 84.5 // intermediate constants. Returns EOBC at end. 84.6 // Expected usage: 84.7 - // while( (bc = iter.next()) != EOBC() ) { ... } 84.8 + // ciBytecodeStream iter(m); 84.9 + // while (iter.next() != ciBytecodeStream::EOBC()) { ... } 84.10 Bytecodes::Code next() { 84.11 _bc_start = _pc; // Capture start of bc 84.12 if( _pc >= _end ) return EOBC(); // End-Of-Bytecodes
85.1 --- a/src/share/vm/classfile/javaClasses.cpp Thu Sep 08 16:59:27 2011 -0700 85.2 +++ b/src/share/vm/classfile/javaClasses.cpp Fri Sep 09 16:17:16 2011 -0700 85.3 @@ -28,6 +28,7 @@ 85.4 #include "classfile/vmSymbols.hpp" 85.5 #include "code/debugInfo.hpp" 85.6 #include "code/pcDesc.hpp" 85.7 +#include "compiler/compilerOracle.hpp" 85.8 #include "interpreter/interpreter.hpp" 85.9 #include "memory/oopFactory.hpp" 85.10 #include "memory/resourceArea.hpp" 85.11 @@ -2323,6 +2324,8 @@ 85.12 85.13 int java_lang_invoke_AdapterMethodHandle::_conversion_offset; 85.14 85.15 +int java_lang_invoke_CountingMethodHandle::_vmcount_offset; 85.16 + 85.17 void java_lang_invoke_MethodHandle::compute_offsets() { 85.18 klassOop k = SystemDictionary::MethodHandle_klass(); 85.19 if (k != NULL && EnableInvokeDynamic) { 85.20 @@ -2371,6 +2374,23 @@ 85.21 } 85.22 } 85.23 85.24 +void java_lang_invoke_CountingMethodHandle::compute_offsets() { 85.25 + klassOop k = SystemDictionary::CountingMethodHandle_klass(); 85.26 + if (k != NULL && EnableInvokeDynamic) { 85.27 + compute_offset(_vmcount_offset, k, vmSymbols::vmcount_name(), vmSymbols::int_signature(), true); 85.28 + } 85.29 +} 85.30 + 85.31 +int java_lang_invoke_CountingMethodHandle::vmcount(oop mh) { 85.32 + assert(is_instance(mh), "CMH only"); 85.33 + return mh->int_field(_vmcount_offset); 85.34 +} 85.35 + 85.36 +void java_lang_invoke_CountingMethodHandle::set_vmcount(oop mh, int count) { 85.37 + assert(is_instance(mh), "CMH only"); 85.38 + mh->int_field_put(_vmcount_offset, count); 85.39 +} 85.40 + 85.41 oop java_lang_invoke_MethodHandle::type(oop mh) { 85.42 return mh->obj_field(_type_offset); 85.43 } 85.44 @@ -2674,6 +2694,17 @@ 85.45 if (k != NULL) { 85.46 compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_lang_invoke_MethodHandle_signature()); 85.47 } 85.48 + 85.49 + // Disallow compilation of CallSite.setTargetNormal and CallSite.setTargetVolatile 85.50 + // (For C2: keep this until we have throttling logic for uncommon traps.) 85.51 + if (k != NULL) { 85.52 + instanceKlass* ik = instanceKlass::cast(k); 85.53 + methodOop m_normal = ik->lookup_method(vmSymbols::setTargetNormal_name(), vmSymbols::setTarget_signature()); 85.54 + methodOop m_volatile = ik->lookup_method(vmSymbols::setTargetVolatile_name(), vmSymbols::setTarget_signature()); 85.55 + guarantee(m_normal && m_volatile, "must exist"); 85.56 + m_normal->set_not_compilable_quietly(); 85.57 + m_volatile->set_not_compilable_quietly(); 85.58 + } 85.59 } 85.60 85.61 oop java_lang_invoke_CallSite::target(oop site) { 85.62 @@ -3031,6 +3062,7 @@ 85.63 java_lang_invoke_MethodType::compute_offsets(); 85.64 java_lang_invoke_MethodTypeForm::compute_offsets(); 85.65 java_lang_invoke_CallSite::compute_offsets(); 85.66 + java_lang_invoke_CountingMethodHandle::compute_offsets(); 85.67 } 85.68 java_security_AccessControlContext::compute_offsets(); 85.69 // Initialize reflection classes. The layouts of these classes
86.1 --- a/src/share/vm/classfile/javaClasses.hpp Thu Sep 08 16:59:27 2011 -0700 86.2 +++ b/src/share/vm/classfile/javaClasses.hpp Fri Sep 09 16:17:16 2011 -0700 86.3 @@ -981,6 +981,34 @@ 86.4 }; 86.5 86.6 86.7 +// A simple class that maintains an invocation count 86.8 +class java_lang_invoke_CountingMethodHandle: public java_lang_invoke_MethodHandle { 86.9 + friend class JavaClasses; 86.10 + 86.11 + private: 86.12 + static int _vmcount_offset; 86.13 + static void compute_offsets(); 86.14 + 86.15 + public: 86.16 + // Accessors 86.17 + static int vmcount(oop mh); 86.18 + static void set_vmcount(oop mh, int count); 86.19 + 86.20 + // Testers 86.21 + static bool is_subclass(klassOop klass) { 86.22 + return SystemDictionary::CountingMethodHandle_klass() != NULL && 86.23 + Klass::cast(klass)->is_subclass_of(SystemDictionary::CountingMethodHandle_klass()); 86.24 + } 86.25 + static bool is_instance(oop obj) { 86.26 + return obj != NULL && is_subclass(obj->klass()); 86.27 + } 86.28 + 86.29 + // Accessors for code generation: 86.30 + static int vmcount_offset_in_bytes() { return _vmcount_offset; } 86.31 +}; 86.32 + 86.33 + 86.34 + 86.35 // Interface to java.lang.invoke.MemberName objects 86.36 // (These are a private interface for Java code to query the class hierarchy.) 86.37
87.1 --- a/src/share/vm/classfile/systemDictionary.hpp Thu Sep 08 16:59:27 2011 -0700 87.2 +++ b/src/share/vm/classfile/systemDictionary.hpp Fri Sep 09 16:17:16 2011 -0700 87.3 @@ -133,14 +133,14 @@ 87.4 template(reflect_Method_klass, java_lang_reflect_Method, Pre) \ 87.5 template(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre) \ 87.6 \ 87.7 - /* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \ 87.8 - /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ 87.9 - /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ 87.10 - template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \ 87.11 - template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ 87.12 - template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ 87.13 - template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \ 87.14 - template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ 87.15 + /* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \ 87.16 + /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ 87.17 + /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ 87.18 + template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \ 87.19 + template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ 87.20 + template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ 87.21 + template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \ 87.22 + template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ 87.23 template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \ 87.24 \ 87.25 /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \ 87.26 @@ -155,6 +155,7 @@ 87.27 template(BootstrapMethodError_klass, java_lang_BootstrapMethodError, Pre_JSR292) \ 87.28 template(WrongMethodTypeException_klass, java_lang_invoke_WrongMethodTypeException, Pre_JSR292) \ 87.29 template(CallSite_klass, java_lang_invoke_CallSite, Pre_JSR292) \ 87.30 + template(CountingMethodHandle_klass, java_lang_invoke_CountingMethodHandle, Opt) \ 87.31 template(ConstantCallSite_klass, java_lang_invoke_ConstantCallSite, Pre_JSR292) \ 87.32 template(MutableCallSite_klass, java_lang_invoke_MutableCallSite, Pre_JSR292) \ 87.33 template(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre_JSR292) \
88.1 --- a/src/share/vm/classfile/vmSymbols.hpp Thu Sep 08 16:59:27 2011 -0700 88.2 +++ b/src/share/vm/classfile/vmSymbols.hpp Fri Sep 09 16:17:16 2011 -0700 88.3 @@ -218,6 +218,7 @@ 88.4 template(returnType_name, "returnType") \ 88.5 template(signature_name, "signature") \ 88.6 template(slot_name, "slot") \ 88.7 + template(selectAlternative_name, "selectAlternative") \ 88.8 \ 88.9 /* Support for annotations (JDK 1.5 and above) */ \ 88.10 \ 88.11 @@ -246,9 +247,11 @@ 88.12 template(java_lang_invoke_MethodTypeForm_signature, "Ljava/lang/invoke/MethodTypeForm;") \ 88.13 template(java_lang_invoke_MemberName, "java/lang/invoke/MemberName") \ 88.14 template(java_lang_invoke_MethodHandleNatives, "java/lang/invoke/MethodHandleNatives") \ 88.15 + template(java_lang_invoke_MethodHandleImpl, "java/lang/invoke/MethodHandleImpl") \ 88.16 template(java_lang_invoke_AdapterMethodHandle, "java/lang/invoke/AdapterMethodHandle") \ 88.17 template(java_lang_invoke_BoundMethodHandle, "java/lang/invoke/BoundMethodHandle") \ 88.18 template(java_lang_invoke_DirectMethodHandle, "java/lang/invoke/DirectMethodHandle") \ 88.19 + template(java_lang_invoke_CountingMethodHandle, "java/lang/invoke/CountingMethodHandle") \ 88.20 /* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \ 88.21 template(findMethodHandleType_name, "findMethodHandleType") \ 88.22 template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \ 88.23 @@ -258,8 +261,12 @@ 88.24 template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;") \ 88.25 template(makeDynamicCallSite_name, "makeDynamicCallSite") \ 88.26 template(makeDynamicCallSite_signature, "(Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/invoke/MemberName;I)Ljava/lang/invoke/CallSite;") \ 88.27 + template(setTargetNormal_name, "setTargetNormal") \ 88.28 + template(setTargetVolatile_name, "setTargetVolatile") \ 88.29 + template(setTarget_signature, "(Ljava/lang/invoke/MethodHandle;)V") \ 88.30 NOT_LP64( do_alias(machine_word_signature, int_signature) ) \ 88.31 LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \ 88.32 + template(selectAlternative_signature, "(ZLjava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;") \ 88.33 \ 88.34 /* common method and field names */ \ 88.35 template(object_initializer_name, "<init>") \ 88.36 @@ -344,6 +351,7 @@ 88.37 template(vmmethod_name, "vmmethod") \ 88.38 template(vmtarget_name, "vmtarget") \ 88.39 template(vmentry_name, "vmentry") \ 88.40 + template(vmcount_name, "vmcount") \ 88.41 template(vmslots_name, "vmslots") \ 88.42 template(vmlayout_name, "vmlayout") \ 88.43 template(vmindex_name, "vmindex") \ 88.44 @@ -907,6 +915,8 @@ 88.45 do_intrinsic(_invokeVarargs, java_lang_invoke_MethodHandle, invokeVarargs_name, object_array_object_signature, F_R) \ 88.46 do_intrinsic(_invokeDynamic, java_lang_invoke_InvokeDynamic, star_name, object_array_object_signature, F_SN) \ 88.47 \ 88.48 + do_intrinsic(_selectAlternative, java_lang_invoke_MethodHandleImpl, selectAlternative_name, selectAlternative_signature, F_S) \ 88.49 + \ 88.50 /* unboxing methods: */ \ 88.51 do_intrinsic(_booleanValue, java_lang_Boolean, booleanValue_name, void_boolean_signature, F_R) \ 88.52 do_name( booleanValue_name, "booleanValue") \
89.1 --- a/src/share/vm/code/dependencies.cpp Thu Sep 08 16:59:27 2011 -0700 89.2 +++ b/src/share/vm/code/dependencies.cpp Fri Sep 09 16:17:16 2011 -0700 89.3 @@ -113,9 +113,9 @@ 89.4 assert_common_1(no_finalizable_subclasses, ctxk); 89.5 } 89.6 89.7 -void Dependencies::assert_call_site_target_value(ciKlass* ctxk, ciCallSite* call_site, ciMethodHandle* method_handle) { 89.8 - check_ctxk(ctxk); 89.9 - assert_common_3(call_site_target_value, ctxk, call_site, method_handle); 89.10 +void Dependencies::assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle) { 89.11 + check_ctxk(call_site->klass()); 89.12 + assert_common_2(call_site_target_value, call_site, method_handle); 89.13 } 89.14 89.15 // Helper function. If we are adding a new dep. under ctxk2, 89.16 @@ -135,7 +135,7 @@ 89.17 } 89.18 } 89.19 89.20 -void Dependencies::assert_common_1(Dependencies::DepType dept, ciObject* x) { 89.21 +void Dependencies::assert_common_1(DepType dept, ciObject* x) { 89.22 assert(dep_args(dept) == 1, "sanity"); 89.23 log_dependency(dept, x); 89.24 GrowableArray<ciObject*>* deps = _deps[dept]; 89.25 @@ -148,21 +148,37 @@ 89.26 } 89.27 } 89.28 89.29 -void Dependencies::assert_common_2(Dependencies::DepType dept, 89.30 - ciKlass* ctxk, ciObject* x) { 89.31 - assert(dep_context_arg(dept) == 0, "sanity"); 89.32 +void Dependencies::assert_common_2(DepType dept, 89.33 + ciObject* x0, ciObject* x1) { 89.34 assert(dep_args(dept) == 2, "sanity"); 89.35 - log_dependency(dept, ctxk, x); 89.36 + log_dependency(dept, x0, x1); 89.37 GrowableArray<ciObject*>* deps = _deps[dept]; 89.38 89.39 // see if the same (or a similar) dep is already recorded 89.40 - if (note_dep_seen(dept, x)) { 89.41 - // look in this bucket for redundant assertions 89.42 - const int stride = 2; 89.43 - for (int i = deps->length(); (i -= stride) >= 0; ) { 89.44 - ciObject* x1 = deps->at(i+1); 89.45 - if (x == x1) { // same subject; check the context 89.46 - if (maybe_merge_ctxk(deps, i+0, ctxk)) { 89.47 + bool has_ctxk = has_explicit_context_arg(dept); 89.48 + if (has_ctxk) { 89.49 + assert(dep_context_arg(dept) == 0, "sanity"); 89.50 + if (note_dep_seen(dept, x1)) { 89.51 + // look in this bucket for redundant assertions 89.52 + const int stride = 2; 89.53 + for (int i = deps->length(); (i -= stride) >= 0; ) { 89.54 + ciObject* y1 = deps->at(i+1); 89.55 + if (x1 == y1) { // same subject; check the context 89.56 + if (maybe_merge_ctxk(deps, i+0, x0->as_klass())) { 89.57 + return; 89.58 + } 89.59 + } 89.60 + } 89.61 + } 89.62 + } else { 89.63 + assert(dep_implicit_context_arg(dept) == 0, "sanity"); 89.64 + if (note_dep_seen(dept, x0) && note_dep_seen(dept, x1)) { 89.65 + // look in this bucket for redundant assertions 89.66 + const int stride = 2; 89.67 + for (int i = deps->length(); (i -= stride) >= 0; ) { 89.68 + ciObject* y0 = deps->at(i+0); 89.69 + ciObject* y1 = deps->at(i+1); 89.70 + if (x0 == y0 && x1 == y1) { 89.71 return; 89.72 } 89.73 } 89.74 @@ -170,11 +186,11 @@ 89.75 } 89.76 89.77 // append the assertion in the correct bucket: 89.78 - deps->append(ctxk); 89.79 - deps->append(x); 89.80 + deps->append(x0); 89.81 + deps->append(x1); 89.82 } 89.83 89.84 -void Dependencies::assert_common_3(Dependencies::DepType dept, 89.85 +void Dependencies::assert_common_3(DepType dept, 89.86 ciKlass* ctxk, ciObject* x, ciObject* x2) { 89.87 assert(dep_context_arg(dept) == 0, "sanity"); 89.88 assert(dep_args(dept) == 3, "sanity"); 89.89 @@ -361,7 +377,7 @@ 89.90 3, // unique_concrete_subtypes_2 ctxk, k1, k2 89.91 3, // unique_concrete_methods_2 ctxk, m1, m2 89.92 1, // no_finalizable_subclasses ctxk 89.93 - 3 // call_site_target_value ctxk, call_site, method_handle 89.94 + 2 // call_site_target_value call_site, method_handle 89.95 }; 89.96 89.97 const char* Dependencies::dep_name(Dependencies::DepType dept) { 89.98 @@ -375,10 +391,7 @@ 89.99 } 89.100 89.101 void Dependencies::check_valid_dependency_type(DepType dept) { 89.102 - for (int deptv = (int) FIRST_TYPE; deptv < (int) TYPE_LIMIT; deptv++) { 89.103 - if (dept == ((DepType) deptv)) return; 89.104 - } 89.105 - ShouldNotReachHere(); 89.106 + guarantee(FIRST_TYPE <= dept && dept < TYPE_LIMIT, err_msg("invalid dependency type: %d", (int) dept)); 89.107 } 89.108 89.109 // for the sake of the compiler log, print out current dependencies: 89.110 @@ -586,8 +599,7 @@ 89.111 code_byte -= ctxk_bit; 89.112 DepType dept = (DepType)code_byte; 89.113 _type = dept; 89.114 - guarantee((dept - FIRST_TYPE) < (TYPE_LIMIT - FIRST_TYPE), 89.115 - "bad dependency type tag"); 89.116 + Dependencies::check_valid_dependency_type(dept); 89.117 int stride = _dep_args[dept]; 89.118 assert(stride == dep_args(dept), "sanity"); 89.119 int skipj = -1; 89.120 @@ -615,18 +627,35 @@ 89.121 89.122 klassOop Dependencies::DepStream::context_type() { 89.123 assert(must_be_in_vm(), "raw oops here"); 89.124 - int ctxkj = dep_context_arg(_type); // -1 if no context arg 89.125 - if (ctxkj < 0) { 89.126 - return NULL; // for example, evol_method 89.127 - } else { 89.128 - oop k = recorded_oop_at(_xi[ctxkj]); 89.129 - if (k != NULL) { // context type was not compressed away 89.130 + 89.131 + // Most dependencies have an explicit context type argument. 89.132 + { 89.133 + int ctxkj = dep_context_arg(_type); // -1 if no explicit context arg 89.134 + if (ctxkj >= 0) { 89.135 + oop k = argument(ctxkj); 89.136 + if (k != NULL) { // context type was not compressed away 89.137 + assert(k->is_klass(), "type check"); 89.138 + return (klassOop) k; 89.139 + } 89.140 + // recompute "default" context type 89.141 + return ctxk_encoded_as_null(_type, argument(ctxkj+1)); 89.142 + } 89.143 + } 89.144 + 89.145 + // Some dependencies are using the klass of the first object 89.146 + // argument as implicit context type (e.g. call_site_target_value). 89.147 + { 89.148 + int ctxkj = dep_implicit_context_arg(_type); 89.149 + if (ctxkj >= 0) { 89.150 + oop k = argument(ctxkj)->klass(); 89.151 assert(k->is_klass(), "type check"); 89.152 return (klassOop) k; 89.153 - } else { // recompute "default" context type 89.154 - return ctxk_encoded_as_null(_type, recorded_oop_at(_xi[ctxkj+1])); 89.155 } 89.156 } 89.157 + 89.158 + // And some dependencies don't have a context type at all, 89.159 + // e.g. evol_method. 89.160 + return NULL; 89.161 } 89.162 89.163 /// Checking dependencies: 89.164 @@ -1409,21 +1438,20 @@ 89.165 } 89.166 89.167 89.168 -klassOop Dependencies::check_call_site_target_value(klassOop ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes) { 89.169 +klassOop Dependencies::check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes) { 89.170 assert(call_site ->is_a(SystemDictionary::CallSite_klass()), "sanity"); 89.171 assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "sanity"); 89.172 if (changes == NULL) { 89.173 // Validate all CallSites 89.174 if (java_lang_invoke_CallSite::target(call_site) != method_handle) 89.175 - return ctxk; // assertion failed 89.176 + return call_site->klass(); // assertion failed 89.177 } else { 89.178 // Validate the given CallSite 89.179 if (call_site == changes->call_site() && java_lang_invoke_CallSite::target(call_site) != changes->method_handle()) { 89.180 assert(method_handle != changes->method_handle(), "must be"); 89.181 - return ctxk; // assertion failed 89.182 + return call_site->klass(); // assertion failed 89.183 } 89.184 } 89.185 - assert(java_lang_invoke_CallSite::target(call_site) == method_handle, "should still be valid"); 89.186 return NULL; // assertion still valid 89.187 } 89.188 89.189 @@ -1488,7 +1516,7 @@ 89.190 klassOop witness = NULL; 89.191 switch (type()) { 89.192 case call_site_target_value: 89.193 - witness = check_call_site_target_value(context_type(), argument(1), argument(2), changes); 89.194 + witness = check_call_site_target_value(argument(0), argument(1), changes); 89.195 break; 89.196 default: 89.197 witness = NULL;
90.1 --- a/src/share/vm/code/dependencies.hpp Thu Sep 08 16:59:27 2011 -0700 90.2 +++ b/src/share/vm/code/dependencies.hpp Fri Sep 09 16:17:16 2011 -0700 90.3 @@ -166,9 +166,14 @@ 90.4 LG2_TYPE_LIMIT = 4, // assert(TYPE_LIMIT <= (1<<LG2_TYPE_LIMIT)) 90.5 90.6 // handy categorizations of dependency types: 90.7 - all_types = ((1<<TYPE_LIMIT)-1) & ((-1)<<FIRST_TYPE), 90.8 - non_ctxk_types = (1<<evol_method), 90.9 - ctxk_types = all_types & ~non_ctxk_types, 90.10 + all_types = ((1 << TYPE_LIMIT) - 1) & ((-1) << FIRST_TYPE), 90.11 + 90.12 + non_klass_types = (1 << call_site_target_value), 90.13 + klass_types = all_types & ~non_klass_types, 90.14 + 90.15 + non_ctxk_types = (1 << evol_method), 90.16 + implicit_ctxk_types = (1 << call_site_target_value), 90.17 + explicit_ctxk_types = all_types & ~(non_ctxk_types | implicit_ctxk_types), 90.18 90.19 max_arg_count = 3, // current maximum number of arguments (incl. ctxk) 90.20 90.21 @@ -184,9 +189,15 @@ 90.22 90.23 static const char* dep_name(DepType dept); 90.24 static int dep_args(DepType dept); 90.25 - static int dep_context_arg(DepType dept) { 90.26 - return dept_in_mask(dept, ctxk_types)? 0: -1; 90.27 - } 90.28 + 90.29 + static bool is_klass_type( DepType dept) { return dept_in_mask(dept, klass_types ); } 90.30 + 90.31 + static bool has_explicit_context_arg(DepType dept) { return dept_in_mask(dept, explicit_ctxk_types); } 90.32 + static bool has_implicit_context_arg(DepType dept) { return dept_in_mask(dept, implicit_ctxk_types); } 90.33 + 90.34 + static int dep_context_arg(DepType dept) { return has_explicit_context_arg(dept) ? 0 : -1; } 90.35 + static int dep_implicit_context_arg(DepType dept) { return has_implicit_context_arg(dept) ? 0 : -1; } 90.36 + 90.37 static void check_valid_dependency_type(DepType dept); 90.38 90.39 private: 90.40 @@ -250,8 +261,8 @@ 90.41 } 90.42 90.43 void assert_common_1(DepType dept, ciObject* x); 90.44 - void assert_common_2(DepType dept, ciKlass* ctxk, ciObject* x); 90.45 - void assert_common_3(DepType dept, ciKlass* ctxk, ciObject* x, ciObject* x2); 90.46 + void assert_common_2(DepType dept, ciObject* x0, ciObject* x1); 90.47 + void assert_common_3(DepType dept, ciKlass* ctxk, ciObject* x1, ciObject* x2); 90.48 90.49 public: 90.50 // Adding assertions to a new dependency set at compile time: 90.51 @@ -264,7 +275,7 @@ 90.52 void assert_abstract_with_exclusive_concrete_subtypes(ciKlass* ctxk, ciKlass* k1, ciKlass* k2); 90.53 void assert_exclusive_concrete_methods(ciKlass* ctxk, ciMethod* m1, ciMethod* m2); 90.54 void assert_has_no_finalizable_subclasses(ciKlass* ctxk); 90.55 - void assert_call_site_target_value(ciKlass* ctxk, ciCallSite* call_site, ciMethodHandle* method_handle); 90.56 + void assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle); 90.57 90.58 // Define whether a given method or type is concrete. 90.59 // These methods define the term "concrete" as used in this module. 90.60 @@ -318,7 +329,7 @@ 90.61 static klassOop check_exclusive_concrete_methods(klassOop ctxk, methodOop m1, methodOop m2, 90.62 KlassDepChange* changes = NULL); 90.63 static klassOop check_has_no_finalizable_subclasses(klassOop ctxk, KlassDepChange* changes = NULL); 90.64 - static klassOop check_call_site_target_value(klassOop ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes = NULL); 90.65 + static klassOop check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes = NULL); 90.66 // A returned klassOop is NULL if the dependency assertion is still 90.67 // valid. A non-NULL klassOop is a 'witness' to the assertion 90.68 // failure, a point in the class hierarchy where the assertion has 90.69 @@ -455,6 +466,8 @@ 90.70 oop argument(int i); // => recorded_oop_at(argument_index(i)) 90.71 klassOop context_type(); 90.72 90.73 + bool is_klass_type() { return Dependencies::is_klass_type(type()); } 90.74 + 90.75 methodOop method_argument(int i) { 90.76 oop x = argument(i); 90.77 assert(x->is_method(), "type");
91.1 --- a/src/share/vm/code/nmethod.cpp Thu Sep 08 16:59:27 2011 -0700 91.2 +++ b/src/share/vm/code/nmethod.cpp Fri Sep 09 16:17:16 2011 -0700 91.3 @@ -451,7 +451,6 @@ 91.4 _stack_traversal_mark = 0; 91.5 _unload_reported = false; // jvmti state 91.6 91.7 - NOT_PRODUCT(_has_debug_info = false); 91.8 #ifdef ASSERT 91.9 _oops_are_stale = false; 91.10 #endif
92.1 --- a/src/share/vm/code/nmethod.hpp Thu Sep 08 16:59:27 2011 -0700 92.2 +++ b/src/share/vm/code/nmethod.hpp Fri Sep 09 16:17:16 2011 -0700 92.3 @@ -191,8 +191,6 @@ 92.4 92.5 jbyte _scavenge_root_state; 92.6 92.7 - NOT_PRODUCT(bool _has_debug_info; ) 92.8 - 92.9 // Nmethod Flushing lock. If non-zero, then the nmethod is not removed 92.10 // and is not made into a zombie. However, once the nmethod is made into 92.11 // a zombie, it will be locked one final time if CompiledMethodUnload 92.12 @@ -329,11 +327,6 @@ 92.13 methodOop method() const { return _method; } 92.14 AbstractCompiler* compiler() const { return _compiler; } 92.15 92.16 -#ifndef PRODUCT 92.17 - bool has_debug_info() const { return _has_debug_info; } 92.18 - void set_has_debug_info(bool f) { _has_debug_info = false; } 92.19 -#endif // NOT PRODUCT 92.20 - 92.21 // type info 92.22 bool is_nmethod() const { return true; } 92.23 bool is_java_method() const { return !method()->is_native(); }
93.1 --- a/src/share/vm/code/pcDesc.cpp Thu Sep 08 16:59:27 2011 -0700 93.2 +++ b/src/share/vm/code/pcDesc.cpp Fri Sep 09 16:17:16 2011 -0700 93.3 @@ -30,11 +30,10 @@ 93.4 #include "memory/resourceArea.hpp" 93.5 93.6 PcDesc::PcDesc(int pc_offset, int scope_decode_offset, int obj_decode_offset) { 93.7 - assert(sizeof(PcDescFlags) <= 4, "occupies more than a word"); 93.8 _pc_offset = pc_offset; 93.9 _scope_decode_offset = scope_decode_offset; 93.10 _obj_decode_offset = obj_decode_offset; 93.11 - _flags.word = 0; 93.12 + _flags = 0; 93.13 } 93.14 93.15 address PcDesc::real_pc(const nmethod* code) const { 93.16 @@ -44,7 +43,7 @@ 93.17 void PcDesc::print(nmethod* code) { 93.18 #ifndef PRODUCT 93.19 ResourceMark rm; 93.20 - tty->print_cr("PcDesc(pc=0x%lx offset=%x bits=%x):", real_pc(code), pc_offset(), _flags.bits); 93.21 + tty->print_cr("PcDesc(pc=0x%lx offset=%x bits=%x):", real_pc(code), pc_offset(), _flags); 93.22 93.23 if (scope_decode_offset() == DebugInformationRecorder::serialized_null) { 93.24 return;
94.1 --- a/src/share/vm/code/pcDesc.hpp Thu Sep 08 16:59:27 2011 -0700 94.2 +++ b/src/share/vm/code/pcDesc.hpp Fri Sep 09 16:17:16 2011 -0700 94.3 @@ -39,15 +39,17 @@ 94.4 int _scope_decode_offset; // offset for scope in nmethod 94.5 int _obj_decode_offset; 94.6 94.7 - union PcDescFlags { 94.8 - int word; 94.9 - struct { 94.10 - unsigned int reexecute: 1; 94.11 - unsigned int is_method_handle_invoke: 1; 94.12 - unsigned int return_oop: 1; 94.13 - } bits; 94.14 - bool operator ==(const PcDescFlags& other) { return word == other.word; } 94.15 - } _flags; 94.16 + enum { 94.17 + PCDESC_reexecute = 1 << 0, 94.18 + PCDESC_is_method_handle_invoke = 1 << 1, 94.19 + PCDESC_return_oop = 1 << 2 94.20 + }; 94.21 + 94.22 + int _flags; 94.23 + 94.24 + void set_flag(int mask, bool z) { 94.25 + _flags = z ? (_flags | mask) : (_flags & ~mask); 94.26 + } 94.27 94.28 public: 94.29 int pc_offset() const { return _pc_offset; } 94.30 @@ -69,8 +71,8 @@ 94.31 }; 94.32 94.33 // Flags 94.34 - bool should_reexecute() const { return _flags.bits.reexecute; } 94.35 - void set_should_reexecute(bool z) { _flags.bits.reexecute = z; } 94.36 + bool should_reexecute() const { return (_flags & PCDESC_reexecute) != 0; } 94.37 + void set_should_reexecute(bool z) { set_flag(PCDESC_reexecute, z); } 94.38 94.39 // Does pd refer to the same information as pd? 94.40 bool is_same_info(const PcDesc* pd) { 94.41 @@ -79,11 +81,11 @@ 94.42 _flags == pd->_flags; 94.43 } 94.44 94.45 - bool is_method_handle_invoke() const { return _flags.bits.is_method_handle_invoke; } 94.46 - void set_is_method_handle_invoke(bool z) { _flags.bits.is_method_handle_invoke = z; } 94.47 + bool is_method_handle_invoke() const { return (_flags & PCDESC_is_method_handle_invoke) != 0; } 94.48 + void set_is_method_handle_invoke(bool z) { set_flag(PCDESC_is_method_handle_invoke, z); } 94.49 94.50 - bool return_oop() const { return _flags.bits.return_oop; } 94.51 - void set_return_oop(bool z) { _flags.bits.return_oop = z; } 94.52 + bool return_oop() const { return (_flags & PCDESC_return_oop) != 0; } 94.53 + void set_return_oop(bool z) { set_flag(PCDESC_return_oop, z); } 94.54 94.55 // Returns the real pc 94.56 address real_pc(const nmethod* code) const;
95.1 --- a/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp Thu Sep 08 16:59:27 2011 -0700 95.2 +++ b/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp Fri Sep 09 16:17:16 2011 -0700 95.3 @@ -1,5 +1,5 @@ 95.4 /* 95.5 - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 95.6 + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. 95.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 95.8 * 95.9 * This code is free software; you can redistribute it and/or modify it 95.10 @@ -26,6 +26,7 @@ 95.11 #include "gc_implementation/g1/collectionSetChooser.hpp" 95.12 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" 95.13 #include "gc_implementation/g1/g1CollectorPolicy.hpp" 95.14 +#include "gc_implementation/g1/g1ErgoVerbose.hpp" 95.15 #include "memory/space.inline.hpp" 95.16 95.17 CSetChooserCache::CSetChooserCache() { 95.18 @@ -358,6 +359,9 @@ 95.19 if (_cache.is_empty()) { 95.20 assert(_curMarkedIndex == _numMarkedRegions, 95.21 "if cache is empty, list should also be empty"); 95.22 + ergo_verbose0(ErgoCSetConstruction, 95.23 + "stop adding old regions to CSet", 95.24 + ergo_format_reason("cache is empty")); 95.25 return NULL; 95.26 } 95.27 95.28 @@ -368,10 +372,23 @@ 95.29 if (g1p->adaptive_young_list_length()) { 95.30 if (time_remaining - predicted_time < 0.0) { 95.31 g1h->check_if_region_is_too_expensive(predicted_time); 95.32 + ergo_verbose2(ErgoCSetConstruction, 95.33 + "stop adding old regions to CSet", 95.34 + ergo_format_reason("predicted old region time higher than remaining time") 95.35 + ergo_format_ms("predicted old region time") 95.36 + ergo_format_ms("remaining time"), 95.37 + predicted_time, time_remaining); 95.38 return NULL; 95.39 } 95.40 } else { 95.41 - if (predicted_time > 2.0 * avg_prediction) { 95.42 + double threshold = 2.0 * avg_prediction; 95.43 + if (predicted_time > threshold) { 95.44 + ergo_verbose2(ErgoCSetConstruction, 95.45 + "stop adding old regions to CSet", 95.46 + ergo_format_reason("predicted old region time higher than threshold") 95.47 + ergo_format_ms("predicted old region time") 95.48 + ergo_format_ms("threshold"), 95.49 + predicted_time, threshold); 95.50 return NULL; 95.51 } 95.52 }
96.1 --- a/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Thu Sep 08 16:59:27 2011 -0700 96.2 +++ b/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Fri Sep 09 16:17:16 2011 -0700 96.3 @@ -91,7 +91,7 @@ 96.4 } 96.5 } 96.6 96.7 - g1p->check_prediction_validity(); 96.8 + g1p->revise_young_list_target_length_if_necessary(); 96.9 } 96.10 } 96.11
97.1 --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Sep 08 16:59:27 2011 -0700 97.2 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Sep 09 16:17:16 2011 -0700 97.3 @@ -28,6 +28,7 @@ 97.4 #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" 97.5 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" 97.6 #include "gc_implementation/g1/g1CollectorPolicy.hpp" 97.7 +#include "gc_implementation/g1/g1ErgoVerbose.hpp" 97.8 #include "gc_implementation/g1/g1OopClosures.inline.hpp" 97.9 #include "gc_implementation/g1/g1RemSet.hpp" 97.10 #include "gc_implementation/g1/heapRegionRemSet.hpp" 97.11 @@ -1727,18 +1728,21 @@ 97.12 97.13 size_t known_garbage_bytes = 97.14 g1_par_count_task.used_bytes() - g1_par_count_task.live_bytes(); 97.15 -#if 0 97.16 - gclog_or_tty->print_cr("used %1.2lf, live %1.2lf, garbage %1.2lf", 97.17 - (double) g1_par_count_task.used_bytes() / (double) (1024 * 1024), 97.18 - (double) g1_par_count_task.live_bytes() / (double) (1024 * 1024), 97.19 - (double) known_garbage_bytes / (double) (1024 * 1024)); 97.20 -#endif // 0 97.21 g1p->set_known_garbage_bytes(known_garbage_bytes); 97.22 97.23 size_t start_used_bytes = g1h->used(); 97.24 _at_least_one_mark_complete = true; 97.25 g1h->set_marking_complete(); 97.26 97.27 + ergo_verbose4(ErgoConcCycles, 97.28 + "finish cleanup", 97.29 + ergo_format_byte("occupancy") 97.30 + ergo_format_byte("capacity") 97.31 + ergo_format_byte_perc("known garbage"), 97.32 + start_used_bytes, g1h->capacity(), 97.33 + known_garbage_bytes, 97.34 + ((double) known_garbage_bytes / (double) g1h->capacity()) * 100.0); 97.35 + 97.36 double count_end = os::elapsedTime(); 97.37 double this_final_counting_time = (count_end - start); 97.38 if (G1PrintParCleanupStats) {
98.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Sep 08 16:59:27 2011 -0700 98.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Sep 09 16:17:16 2011 -0700 98.3 @@ -31,6 +31,7 @@ 98.4 #include "gc_implementation/g1/g1AllocRegion.inline.hpp" 98.5 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" 98.6 #include "gc_implementation/g1/g1CollectorPolicy.hpp" 98.7 +#include "gc_implementation/g1/g1ErgoVerbose.hpp" 98.8 #include "gc_implementation/g1/g1MarkSweep.hpp" 98.9 #include "gc_implementation/g1/g1OopClosures.inline.hpp" 98.10 #include "gc_implementation/g1/g1RemSet.inline.hpp" 98.11 @@ -577,6 +578,11 @@ 98.12 res = new_region_try_secondary_free_list(); 98.13 } 98.14 if (res == NULL && do_expand) { 98.15 + ergo_verbose1(ErgoHeapSizing, 98.16 + "attempt heap expansion", 98.17 + ergo_format_reason("region allocation request failed") 98.18 + ergo_format_byte("allocation request"), 98.19 + word_size * HeapWordSize); 98.20 if (expand(word_size * HeapWordSize)) { 98.21 // Even though the heap was expanded, it might not have reached 98.22 // the desired size. So, we cannot assume that the allocation 98.23 @@ -790,6 +796,11 @@ 98.24 // room available. 98.25 assert(num_regions > fs, "earlier allocation should have succeeded"); 98.26 98.27 + ergo_verbose1(ErgoHeapSizing, 98.28 + "attempt heap expansion", 98.29 + ergo_format_reason("humongous allocation request failed") 98.30 + ergo_format_byte("allocation request"), 98.31 + word_size * HeapWordSize); 98.32 if (expand((num_regions - fs) * HeapRegion::GrainBytes)) { 98.33 // Even though the heap was expanded, it might not have 98.34 // reached the desired size. So, we cannot assume that the 98.35 @@ -906,6 +917,8 @@ 98.36 98.37 if (GC_locker::is_active_and_needs_gc()) { 98.38 if (g1_policy()->can_expand_young_list()) { 98.39 + // No need for an ergo verbose message here, 98.40 + // can_expand_young_list() does this when it returns true. 98.41 result = _mutator_alloc_region.attempt_allocation_force(word_size, 98.42 false /* bot_updates */); 98.43 if (result != NULL) { 98.44 @@ -1477,63 +1490,34 @@ 98.45 // we'll try to make the capacity smaller than it, not greater). 98.46 maximum_desired_capacity = MAX2(maximum_desired_capacity, min_heap_size); 98.47 98.48 - if (PrintGC && Verbose) { 98.49 - const double free_percentage = 98.50 - (double) free_after_gc / (double) capacity_after_gc; 98.51 - gclog_or_tty->print_cr("Computing new size after full GC "); 98.52 - gclog_or_tty->print_cr(" " 98.53 - " minimum_free_percentage: %6.2f", 98.54 - minimum_free_percentage); 98.55 - gclog_or_tty->print_cr(" " 98.56 - " maximum_free_percentage: %6.2f", 98.57 - maximum_free_percentage); 98.58 - gclog_or_tty->print_cr(" " 98.59 - " capacity: %6.1fK" 98.60 - " minimum_desired_capacity: %6.1fK" 98.61 - " maximum_desired_capacity: %6.1fK", 98.62 - (double) capacity_after_gc / (double) K, 98.63 - (double) minimum_desired_capacity / (double) K, 98.64 - (double) maximum_desired_capacity / (double) K); 98.65 - gclog_or_tty->print_cr(" " 98.66 - " free_after_gc: %6.1fK" 98.67 - " used_after_gc: %6.1fK", 98.68 - (double) free_after_gc / (double) K, 98.69 - (double) used_after_gc / (double) K); 98.70 - gclog_or_tty->print_cr(" " 98.71 - " free_percentage: %6.2f", 98.72 - free_percentage); 98.73 - } 98.74 if (capacity_after_gc < minimum_desired_capacity) { 98.75 // Don't expand unless it's significant 98.76 size_t expand_bytes = minimum_desired_capacity - capacity_after_gc; 98.77 - if (expand(expand_bytes)) { 98.78 - if (PrintGC && Verbose) { 98.79 - gclog_or_tty->print_cr(" " 98.80 - " expanding:" 98.81 - " max_heap_size: %6.1fK" 98.82 - " minimum_desired_capacity: %6.1fK" 98.83 - " expand_bytes: %6.1fK", 98.84 - (double) max_heap_size / (double) K, 98.85 - (double) minimum_desired_capacity / (double) K, 98.86 - (double) expand_bytes / (double) K); 98.87 - } 98.88 - } 98.89 + ergo_verbose4(ErgoHeapSizing, 98.90 + "attempt heap expansion", 98.91 + ergo_format_reason("capacity lower than " 98.92 + "min desired capacity after Full GC") 98.93 + ergo_format_byte("capacity") 98.94 + ergo_format_byte("occupancy") 98.95 + ergo_format_byte_perc("min desired capacity"), 98.96 + capacity_after_gc, used_after_gc, 98.97 + minimum_desired_capacity, (double) MinHeapFreeRatio); 98.98 + expand(expand_bytes); 98.99 98.100 // No expansion, now see if we want to shrink 98.101 } else if (capacity_after_gc > maximum_desired_capacity) { 98.102 // Capacity too large, compute shrinking size 98.103 size_t shrink_bytes = capacity_after_gc - maximum_desired_capacity; 98.104 + ergo_verbose4(ErgoHeapSizing, 98.105 + "attempt heap shrinking", 98.106 + ergo_format_reason("capacity higher than " 98.107 + "max desired capacity after Full GC") 98.108 + ergo_format_byte("capacity") 98.109 + ergo_format_byte("occupancy") 98.110 + ergo_format_byte_perc("max desired capacity"), 98.111 + capacity_after_gc, used_after_gc, 98.112 + maximum_desired_capacity, (double) MaxHeapFreeRatio); 98.113 shrink(shrink_bytes); 98.114 - if (PrintGC && Verbose) { 98.115 - gclog_or_tty->print_cr(" " 98.116 - " shrinking:" 98.117 - " min_heap_size: %6.1fK" 98.118 - " maximum_desired_capacity: %6.1fK" 98.119 - " shrink_bytes: %6.1fK", 98.120 - (double) min_heap_size / (double) K, 98.121 - (double) maximum_desired_capacity / (double) K, 98.122 - (double) shrink_bytes / (double) K); 98.123 - } 98.124 } 98.125 } 98.126 98.127 @@ -1619,6 +1603,11 @@ 98.128 verify_region_sets_optional(); 98.129 98.130 size_t expand_bytes = MAX2(word_size * HeapWordSize, MinHeapDeltaBytes); 98.131 + ergo_verbose1(ErgoHeapSizing, 98.132 + "attempt heap expansion", 98.133 + ergo_format_reason("allocation request failed") 98.134 + ergo_format_byte("allocation request"), 98.135 + word_size * HeapWordSize); 98.136 if (expand(expand_bytes)) { 98.137 _hrs.verify_optional(); 98.138 verify_region_sets_optional(); 98.139 @@ -1646,11 +1635,11 @@ 98.140 size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes); 98.141 aligned_expand_bytes = align_size_up(aligned_expand_bytes, 98.142 HeapRegion::GrainBytes); 98.143 - 98.144 - if (Verbose && PrintGC) { 98.145 - gclog_or_tty->print("Expanding garbage-first heap from %ldK by %ldK", 98.146 - old_mem_size/K, aligned_expand_bytes/K); 98.147 - } 98.148 + ergo_verbose2(ErgoHeapSizing, 98.149 + "expand the heap", 98.150 + ergo_format_byte("requested expansion amount") 98.151 + ergo_format_byte("attempted expansion amount"), 98.152 + expand_bytes, aligned_expand_bytes); 98.153 98.154 // First commit the memory. 98.155 HeapWord* old_end = (HeapWord*) _g1_storage.high(); 98.156 @@ -1693,7 +1682,11 @@ 98.157 } 98.158 assert(curr == mr.end(), "post-condition"); 98.159 } 98.160 + g1_policy()->record_new_heap_size(n_regions()); 98.161 } else { 98.162 + ergo_verbose0(ErgoHeapSizing, 98.163 + "did not expand the heap", 98.164 + ergo_format_reason("heap expansion operation failed")); 98.165 // The expansion of the virtual storage space was unsuccessful. 98.166 // Let's see if it was because we ran out of swap. 98.167 if (G1ExitOnExpansionFailure && 98.168 @@ -1702,13 +1695,6 @@ 98.169 vm_exit_out_of_memory(aligned_expand_bytes, "G1 heap expansion"); 98.170 } 98.171 } 98.172 - 98.173 - if (Verbose && PrintGC) { 98.174 - size_t new_mem_size = _g1_storage.committed_size(); 98.175 - gclog_or_tty->print_cr("...%s, expanded to %ldK", 98.176 - (successful ? "Successful" : "Failed"), 98.177 - new_mem_size/K); 98.178 - } 98.179 return successful; 98.180 } 98.181 98.182 @@ -1722,6 +1708,13 @@ 98.183 MemRegion mr = _hrs.shrink_by(aligned_shrink_bytes, &num_regions_deleted); 98.184 HeapWord* old_end = (HeapWord*) _g1_storage.high(); 98.185 assert(mr.end() == old_end, "post-condition"); 98.186 + 98.187 + ergo_verbose3(ErgoHeapSizing, 98.188 + "shrink the heap", 98.189 + ergo_format_byte("requested shrinking amount") 98.190 + ergo_format_byte("aligned shrinking amount") 98.191 + ergo_format_byte("attempted shrinking amount"), 98.192 + shrink_bytes, aligned_shrink_bytes, mr.byte_size()); 98.193 if (mr.byte_size() > 0) { 98.194 if (_hr_printer.is_active()) { 98.195 HeapWord* curr = mr.end(); 98.196 @@ -1740,13 +1733,11 @@ 98.197 _expansion_regions += num_regions_deleted; 98.198 update_committed_space(old_end, new_end); 98.199 HeapRegionRemSet::shrink_heap(n_regions()); 98.200 - 98.201 - if (Verbose && PrintGC) { 98.202 - size_t new_mem_size = _g1_storage.committed_size(); 98.203 - gclog_or_tty->print_cr("Shrinking garbage-first heap from %ldK by %ldK to %ldK", 98.204 - old_mem_size/K, aligned_shrink_bytes/K, 98.205 - new_mem_size/K); 98.206 - } 98.207 + g1_policy()->record_new_heap_size(n_regions()); 98.208 + } else { 98.209 + ergo_verbose0(ErgoHeapSizing, 98.210 + "did not shrink the heap", 98.211 + ergo_format_reason("heap shrinking operation failed")); 98.212 } 98.213 } 98.214 98.215 @@ -3534,6 +3525,19 @@ 98.216 98.217 init_mutator_alloc_region(); 98.218 98.219 + { 98.220 + size_t expand_bytes = g1_policy()->expansion_amount(); 98.221 + if (expand_bytes > 0) { 98.222 + size_t bytes_before = capacity(); 98.223 + if (!expand(expand_bytes)) { 98.224 + // We failed to expand the heap so let's verify that 98.225 + // committed/uncommitted amount match the backing store 98.226 + assert(capacity() == _g1_storage.committed_size(), "committed size mismatch"); 98.227 + assert(max_capacity() == _g1_storage.reserved_size(), "reserved size mismatch"); 98.228 + } 98.229 + } 98.230 + } 98.231 + 98.232 double end_time_sec = os::elapsedTime(); 98.233 double pause_time_ms = (end_time_sec - start_time_sec) * MILLIUNITS; 98.234 g1_policy()->record_pause_time_ms(pause_time_ms); 98.235 @@ -3579,6 +3583,8 @@ 98.236 size_t expand_bytes = g1_policy()->expansion_amount(); 98.237 if (expand_bytes > 0) { 98.238 size_t bytes_before = capacity(); 98.239 + // No need for an ergo verbose message here, 98.240 + // expansion_amount() does this when it returns a value > 0. 98.241 if (!expand(expand_bytes)) { 98.242 // We failed to expand the heap so let's verify that 98.243 // committed/uncommitted amount match the backing store 98.244 @@ -3732,13 +3738,6 @@ 98.245 bool do_object_b(oop p) { 98.246 // It is reachable if it is outside the collection set, or is inside 98.247 // and forwarded. 98.248 - 98.249 -#ifdef G1_DEBUG 98.250 - gclog_or_tty->print_cr("is alive "PTR_FORMAT" in CS %d forwarded %d overall %d", 98.251 - (void*) p, _g1->obj_in_cs(p), p->is_forwarded(), 98.252 - !_g1->obj_in_cs(p) || p->is_forwarded()); 98.253 -#endif // G1_DEBUG 98.254 - 98.255 return !_g1->obj_in_cs(p) || p->is_forwarded(); 98.256 } 98.257 }; 98.258 @@ -3750,20 +3749,9 @@ 98.259 void do_oop(narrowOop* p) { guarantee(false, "Not needed"); } 98.260 void do_oop( oop* p) { 98.261 oop obj = *p; 98.262 -#ifdef G1_DEBUG 98.263 - if (PrintGC && Verbose) { 98.264 - gclog_or_tty->print_cr("keep alive *"PTR_FORMAT" = "PTR_FORMAT" "PTR_FORMAT, 98.265 - p, (void*) obj, (void*) *p); 98.266 - } 98.267 -#endif // G1_DEBUG 98.268 - 98.269 if (_g1->obj_in_cs(obj)) { 98.270 assert( obj->is_forwarded(), "invariant" ); 98.271 *p = obj->forwardee(); 98.272 -#ifdef G1_DEBUG 98.273 - gclog_or_tty->print_cr(" in CSet: moved "PTR_FORMAT" -> "PTR_FORMAT, 98.274 - (void*) obj, (void*) *p); 98.275 -#endif // G1_DEBUG 98.276 } 98.277 } 98.278 }; 98.279 @@ -4069,6 +4057,23 @@ 98.280 } 98.281 #endif // PRODUCT 98.282 98.283 +G1ParGCAllocBuffer::G1ParGCAllocBuffer(size_t gclab_word_size) : 98.284 + ParGCAllocBuffer(gclab_word_size), 98.285 + _should_mark_objects(false), 98.286 + _bitmap(G1CollectedHeap::heap()->reserved_region().start(), gclab_word_size), 98.287 + _retired(false) 98.288 +{ 98.289 + //_should_mark_objects is set to true when G1ParCopyHelper needs to 98.290 + // mark the forwarded location of an evacuated object. 98.291 + // We set _should_mark_objects to true if marking is active, i.e. when we 98.292 + // need to propagate a mark, or during an initial mark pause, i.e. when we 98.293 + // need to mark objects immediately reachable by the roots. 98.294 + if (G1CollectedHeap::heap()->mark_in_progress() || 98.295 + G1CollectedHeap::heap()->g1_policy()->during_initial_mark_pause()) { 98.296 + _should_mark_objects = true; 98.297 + } 98.298 +} 98.299 + 98.300 G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, int queue_num) 98.301 : _g1h(g1h), 98.302 _refs(g1h->task_queue(queue_num)), 98.303 @@ -4184,12 +4189,14 @@ 98.304 98.305 G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : 98.306 _g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()), 98.307 - _par_scan_state(par_scan_state) { } 98.308 - 98.309 -template <class T> void G1ParCopyHelper::mark_forwardee(T* p) { 98.310 - // This is called _after_ do_oop_work has been called, hence after 98.311 - // the object has been relocated to its new location and *p points 98.312 - // to its new location. 98.313 + _par_scan_state(par_scan_state), 98.314 + _during_initial_mark(_g1->g1_policy()->during_initial_mark_pause()), 98.315 + _mark_in_progress(_g1->mark_in_progress()) { } 98.316 + 98.317 +template <class T> void G1ParCopyHelper::mark_object(T* p) { 98.318 + // This is called from do_oop_work for objects that are not 98.319 + // in the collection set. Objects in the collection set 98.320 + // are marked after they have been evacuated. 98.321 98.322 T heap_oop = oopDesc::load_heap_oop(p); 98.323 if (!oopDesc::is_null(heap_oop)) { 98.324 @@ -4201,7 +4208,7 @@ 98.325 } 98.326 } 98.327 98.328 -oop G1ParCopyHelper::copy_to_survivor_space(oop old) { 98.329 +oop G1ParCopyHelper::copy_to_survivor_space(oop old, bool should_mark_copy) { 98.330 size_t word_sz = old->size(); 98.331 HeapRegion* from_region = _g1->heap_region_containing_raw(old); 98.332 // +1 to make the -1 indexes valid... 98.333 @@ -4257,8 +4264,8 @@ 98.334 obj->set_mark(m); 98.335 } 98.336 98.337 - // preserve "next" mark bit 98.338 - if (_g1->mark_in_progress() && !_g1->is_obj_ill(old)) { 98.339 + // Mark the evacuated object or propagate "next" mark bit 98.340 + if (should_mark_copy) { 98.341 if (!use_local_bitmaps || 98.342 !_par_scan_state->alloc_buffer(alloc_purpose)->mark(obj_ptr)) { 98.343 // if we couldn't mark it on the local bitmap (this happens when 98.344 @@ -4266,11 +4273,12 @@ 98.345 // the bullet and do the standard parallel mark 98.346 _cm->markAndGrayObjectIfNecessary(obj); 98.347 } 98.348 -#if 1 98.349 + 98.350 if (_g1->isMarkedNext(old)) { 98.351 + // Unmark the object's old location so that marking 98.352 + // doesn't think the old object is alive. 98.353 _cm->nextMarkBitMap()->parClear((HeapWord*)old); 98.354 } 98.355 -#endif 98.356 } 98.357 98.358 size_t* surv_young_words = _par_scan_state->surviving_young_words(); 98.359 @@ -4293,26 +4301,62 @@ 98.360 return obj; 98.361 } 98.362 98.363 -template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_forwardee> 98.364 +template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_object> 98.365 template <class T> 98.366 -void G1ParCopyClosure <do_gen_barrier, barrier, do_mark_forwardee> 98.367 +void G1ParCopyClosure<do_gen_barrier, barrier, do_mark_object> 98.368 ::do_oop_work(T* p) { 98.369 oop obj = oopDesc::load_decode_heap_oop(p); 98.370 assert(barrier != G1BarrierRS || obj != NULL, 98.371 "Precondition: G1BarrierRS implies obj is nonNull"); 98.372 98.373 + // Marking: 98.374 + // If the object is in the collection set, then the thread 98.375 + // that copies the object should mark, or propagate the 98.376 + // mark to, the evacuated object. 98.377 + // If the object is not in the collection set then we 98.378 + // should call the mark_object() method depending on the 98.379 + // value of the template parameter do_mark_object (which will 98.380 + // be true for root scanning closures during an initial mark 98.381 + // pause). 98.382 + // The mark_object() method first checks whether the object 98.383 + // is marked and, if not, attempts to mark the object. 98.384 + 98.385 // here the null check is implicit in the cset_fast_test() test 98.386 if (_g1->in_cset_fast_test(obj)) { 98.387 if (obj->is_forwarded()) { 98.388 oopDesc::encode_store_heap_oop(p, obj->forwardee()); 98.389 + // If we are a root scanning closure during an initial 98.390 + // mark pause (i.e. do_mark_object will be true) then 98.391 + // we also need to handle marking of roots in the 98.392 + // event of an evacuation failure. In the event of an 98.393 + // evacuation failure, the object is forwarded to itself 98.394 + // and not copied so let's mark it here. 98.395 + if (do_mark_object && obj->forwardee() == obj) { 98.396 + mark_object(p); 98.397 + } 98.398 } else { 98.399 - oop copy_oop = copy_to_survivor_space(obj); 98.400 + // We need to mark the copied object if we're a root scanning 98.401 + // closure during an initial mark pause (i.e. do_mark_object 98.402 + // will be true), or the object is already marked and we need 98.403 + // to propagate the mark to the evacuated copy. 98.404 + bool should_mark_copy = do_mark_object || 98.405 + _during_initial_mark || 98.406 + (_mark_in_progress && !_g1->is_obj_ill(obj)); 98.407 + 98.408 + oop copy_oop = copy_to_survivor_space(obj, should_mark_copy); 98.409 oopDesc::encode_store_heap_oop(p, copy_oop); 98.410 } 98.411 // When scanning the RS, we only care about objs in CS. 98.412 if (barrier == G1BarrierRS) { 98.413 _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); 98.414 } 98.415 + } else { 98.416 + // The object is not in collection set. If we're a root scanning 98.417 + // closure during an initial mark pause (i.e. do_mark_object will 98.418 + // be true) then attempt to mark the object. 98.419 + if (do_mark_object) { 98.420 + mark_object(p); 98.421 + } 98.422 } 98.423 98.424 if (barrier == G1BarrierEvac && obj != NULL) { 98.425 @@ -4557,7 +4601,6 @@ 98.426 // keep entries (which are added by the marking threads) on them 98.427 // live until they can be processed at the end of marking. 98.428 ref_processor()->weak_oops_do(&buf_scan_non_heap_roots); 98.429 - ref_processor()->oops_do(&buf_scan_non_heap_roots); 98.430 } 98.431 98.432 // Finish up any enqueued closure apps (attributed as object copy time).
99.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Sep 08 16:59:27 2011 -0700 99.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Sep 09 16:17:16 2011 -0700 99.3 @@ -1715,26 +1715,22 @@ 99.4 class G1ParGCAllocBuffer: public ParGCAllocBuffer { 99.5 private: 99.6 bool _retired; 99.7 - bool _during_marking; 99.8 + bool _should_mark_objects; 99.9 GCLabBitMap _bitmap; 99.10 99.11 public: 99.12 - G1ParGCAllocBuffer(size_t gclab_word_size) : 99.13 - ParGCAllocBuffer(gclab_word_size), 99.14 - _during_marking(G1CollectedHeap::heap()->mark_in_progress()), 99.15 - _bitmap(G1CollectedHeap::heap()->reserved_region().start(), gclab_word_size), 99.16 - _retired(false) 99.17 - { } 99.18 + G1ParGCAllocBuffer(size_t gclab_word_size); 99.19 99.20 inline bool mark(HeapWord* addr) { 99.21 guarantee(use_local_bitmaps, "invariant"); 99.22 - assert(_during_marking, "invariant"); 99.23 + assert(_should_mark_objects, "invariant"); 99.24 return _bitmap.mark(addr); 99.25 } 99.26 99.27 inline void set_buf(HeapWord* buf) { 99.28 - if (use_local_bitmaps && _during_marking) 99.29 + if (use_local_bitmaps && _should_mark_objects) { 99.30 _bitmap.set_buffer(buf); 99.31 + } 99.32 ParGCAllocBuffer::set_buf(buf); 99.33 _retired = false; 99.34 } 99.35 @@ -1742,7 +1738,7 @@ 99.36 inline void retire(bool end_of_gc, bool retain) { 99.37 if (_retired) 99.38 return; 99.39 - if (use_local_bitmaps && _during_marking) { 99.40 + if (use_local_bitmaps && _should_mark_objects) { 99.41 _bitmap.retire(); 99.42 } 99.43 ParGCAllocBuffer::retire(end_of_gc, retain);
100.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Sep 08 16:59:27 2011 -0700 100.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Sep 09 16:17:16 2011 -0700 100.3 @@ -28,6 +28,7 @@ 100.4 #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" 100.5 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" 100.6 #include "gc_implementation/g1/g1CollectorPolicy.hpp" 100.7 +#include "gc_implementation/g1/g1ErgoVerbose.hpp" 100.8 #include "gc_implementation/g1/heapRegionRemSet.hpp" 100.9 #include "gc_implementation/shared/gcPolicyCounters.hpp" 100.10 #include "runtime/arguments.hpp" 100.11 @@ -145,6 +146,7 @@ 100.12 _stop_world_start(0.0), 100.13 _all_stop_world_times_ms(new NumberSeq()), 100.14 _all_yield_times_ms(new NumberSeq()), 100.15 + _using_new_ratio_calculations(false), 100.16 100.17 _all_mod_union_times_ms(new NumberSeq()), 100.18 100.19 @@ -271,15 +273,26 @@ 100.20 _recorded_survivor_tail(NULL), 100.21 _survivors_age_table(true), 100.22 100.23 - _gc_overhead_perc(0.0) 100.24 - 100.25 -{ 100.26 + _gc_overhead_perc(0.0) { 100.27 + 100.28 // Set up the region size and associated fields. Given that the 100.29 // policy is created before the heap, we have to set this up here, 100.30 // so it's done as soon as possible. 100.31 HeapRegion::setup_heap_region_size(Arguments::min_heap_size()); 100.32 HeapRegionRemSet::setup_remset_size(); 100.33 100.34 + G1ErgoVerbose::initialize(); 100.35 + if (PrintAdaptiveSizePolicy) { 100.36 + // Currently, we only use a single switch for all the heuristics. 100.37 + G1ErgoVerbose::set_enabled(true); 100.38 + // Given that we don't currently have a verboseness level 100.39 + // parameter, we'll hardcode this to high. This can be easily 100.40 + // changed in the future. 100.41 + G1ErgoVerbose::set_level(ErgoHigh); 100.42 + } else { 100.43 + G1ErgoVerbose::set_enabled(false); 100.44 + } 100.45 + 100.46 // Verify PLAB sizes 100.47 const uint region_size = HeapRegion::GrainWords; 100.48 if (YoungPLABSize > region_size || OldPLABSize > region_size) { 100.49 @@ -402,7 +415,7 @@ 100.50 _concurrent_mark_cleanup_times_ms->add(0.20); 100.51 _tenuring_threshold = MaxTenuringThreshold; 100.52 // _max_survivor_regions will be calculated by 100.53 - // calculate_young_list_target_length() during initialization. 100.54 + // update_young_list_target_length() during initialization. 100.55 _max_survivor_regions = 0; 100.56 100.57 assert(GCTimeRatio > 0, 100.58 @@ -410,6 +423,18 @@ 100.59 "if a user set it to 0"); 100.60 _gc_overhead_perc = 100.0 * (1.0 / (1.0 + GCTimeRatio)); 100.61 100.62 + uintx reserve_perc = G1ReservePercent; 100.63 + // Put an artificial ceiling on this so that it's not set to a silly value. 100.64 + if (reserve_perc > 50) { 100.65 + reserve_perc = 50; 100.66 + warning("G1ReservePercent is set to a value that is too large, " 100.67 + "it's been updated to %u", reserve_perc); 100.68 + } 100.69 + _reserve_factor = (double) reserve_perc / 100.0; 100.70 + // This will be set when the heap is expanded 100.71 + // for the first time during initialization. 100.72 + _reserve_regions = 0; 100.73 + 100.74 initialize_all(); 100.75 } 100.76 100.77 @@ -434,16 +459,15 @@ 100.78 // ParallelScavengeHeap::initialize()). We might change this in the 100.79 // future, but it's a good start. 100.80 class G1YoungGenSizer : public TwoGenerationCollectorPolicy { 100.81 - size_t size_to_region_num(size_t byte_size) { 100.82 - return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes); 100.83 - } 100.84 100.85 public: 100.86 G1YoungGenSizer() { 100.87 initialize_flags(); 100.88 initialize_size_info(); 100.89 } 100.90 - 100.91 + size_t size_to_region_num(size_t byte_size) { 100.92 + return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes); 100.93 + } 100.94 size_t min_young_region_num() { 100.95 return size_to_region_num(_min_gen0_size); 100.96 } 100.97 @@ -455,6 +479,13 @@ 100.98 } 100.99 }; 100.100 100.101 +void G1CollectorPolicy::update_young_list_size_using_newratio(size_t number_of_heap_regions) { 100.102 + assert(number_of_heap_regions > 0, "Heap must be initialized"); 100.103 + size_t young_size = number_of_heap_regions / (NewRatio + 1); 100.104 + _min_desired_young_length = young_size; 100.105 + _max_desired_young_length = young_size; 100.106 +} 100.107 + 100.108 void G1CollectorPolicy::init() { 100.109 // Set aside an initial future to_space. 100.110 _g1 = G1CollectedHeap::heap(); 100.111 @@ -465,18 +496,35 @@ 100.112 100.113 G1YoungGenSizer sizer; 100.114 size_t initial_region_num = sizer.initial_young_region_num(); 100.115 - 100.116 - if (UseAdaptiveSizePolicy) { 100.117 - set_adaptive_young_list_length(true); 100.118 + _min_desired_young_length = sizer.min_young_region_num(); 100.119 + _max_desired_young_length = sizer.max_young_region_num(); 100.120 + 100.121 + if (FLAG_IS_CMDLINE(NewRatio)) { 100.122 + if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) { 100.123 + gclog_or_tty->print_cr("-XX:NewSize and -XX:MaxNewSize overrides -XX:NewRatio"); 100.124 + } else { 100.125 + // Treat NewRatio as a fixed size that is only recalculated when the heap size changes 100.126 + size_t heap_regions = sizer.size_to_region_num(_g1->n_regions()); 100.127 + update_young_list_size_using_newratio(heap_regions); 100.128 + _using_new_ratio_calculations = true; 100.129 + } 100.130 + } 100.131 + 100.132 + // GenCollectorPolicy guarantees that min <= initial <= max. 100.133 + // Asserting here just to state that we rely on this property. 100.134 + assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values"); 100.135 + assert(initial_region_num <= _max_desired_young_length, "Initial young gen size too large"); 100.136 + assert(_min_desired_young_length <= initial_region_num, "Initial young gen size too small"); 100.137 + 100.138 + set_adaptive_young_list_length(_min_desired_young_length < _max_desired_young_length); 100.139 + if (adaptive_young_list_length()) { 100.140 _young_list_fixed_length = 0; 100.141 } else { 100.142 - set_adaptive_young_list_length(false); 100.143 _young_list_fixed_length = initial_region_num; 100.144 } 100.145 _free_regions_at_end_of_collection = _g1->free_regions(); 100.146 - calculate_young_list_min_length(); 100.147 - guarantee( _young_list_min_length == 0, "invariant, not enough info" ); 100.148 - calculate_young_list_target_length(); 100.149 + update_young_list_target_length(); 100.150 + _prev_eden_capacity = _young_list_target_length * HeapRegion::GrainBytes; 100.151 100.152 // We may immediately start allocating regions and placing them on the 100.153 // collection set list. Initialize the per-collection set info 100.154 @@ -484,236 +532,259 @@ 100.155 } 100.156 100.157 // Create the jstat counters for the policy. 100.158 -void G1CollectorPolicy::initialize_gc_policy_counters() 100.159 -{ 100.160 +void G1CollectorPolicy::initialize_gc_policy_counters() { 100.161 _gc_policy_counters = new GCPolicyCounters("GarbageFirst", 1, 3); 100.162 } 100.163 100.164 -void G1CollectorPolicy::calculate_young_list_min_length() { 100.165 - _young_list_min_length = 0; 100.166 - 100.167 - if (!adaptive_young_list_length()) 100.168 - return; 100.169 - 100.170 - if (_alloc_rate_ms_seq->num() > 3) { 100.171 - double now_sec = os::elapsedTime(); 100.172 - double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0; 100.173 - double alloc_rate_ms = predict_alloc_rate_ms(); 100.174 - size_t min_regions = (size_t) ceil(alloc_rate_ms * when_ms); 100.175 - size_t current_region_num = _g1->young_list()->length(); 100.176 - _young_list_min_length = min_regions + current_region_num; 100.177 +bool G1CollectorPolicy::predict_will_fit(size_t young_length, 100.178 + double base_time_ms, 100.179 + size_t base_free_regions, 100.180 + double target_pause_time_ms) { 100.181 + if (young_length >= base_free_regions) { 100.182 + // end condition 1: not enough space for the young regions 100.183 + return false; 100.184 + } 100.185 + 100.186 + double accum_surv_rate = accum_yg_surv_rate_pred((int)(young_length - 1)); 100.187 + size_t bytes_to_copy = 100.188 + (size_t) (accum_surv_rate * (double) HeapRegion::GrainBytes); 100.189 + double copy_time_ms = predict_object_copy_time_ms(bytes_to_copy); 100.190 + double young_other_time_ms = predict_young_other_time_ms(young_length); 100.191 + double pause_time_ms = base_time_ms + copy_time_ms + young_other_time_ms; 100.192 + if (pause_time_ms > target_pause_time_ms) { 100.193 + // end condition 2: prediction is over the target pause time 100.194 + return false; 100.195 + } 100.196 + 100.197 + size_t free_bytes = 100.198 + (base_free_regions - young_length) * HeapRegion::GrainBytes; 100.199 + if ((2.0 * sigma()) * (double) bytes_to_copy > (double) free_bytes) { 100.200 + // end condition 3: out-of-space (conservatively!) 100.201 + return false; 100.202 + } 100.203 + 100.204 + // success! 100.205 + return true; 100.206 +} 100.207 + 100.208 +void G1CollectorPolicy::record_new_heap_size(size_t new_number_of_regions) { 100.209 + // re-calculate the necessary reserve 100.210 + double reserve_regions_d = (double) new_number_of_regions * _reserve_factor; 100.211 + // We use ceiling so that if reserve_regions_d is > 0.0 (but 100.212 + // smaller than 1.0) we'll get 1. 100.213 + _reserve_regions = (size_t) ceil(reserve_regions_d); 100.214 + 100.215 + if (_using_new_ratio_calculations) { 100.216 + // -XX:NewRatio was specified so we need to update the 100.217 + // young gen length when the heap size has changed. 100.218 + update_young_list_size_using_newratio(new_number_of_regions); 100.219 } 100.220 } 100.221 100.222 -void G1CollectorPolicy::calculate_young_list_target_length() { 100.223 +size_t G1CollectorPolicy::calculate_young_list_desired_min_length( 100.224 + size_t base_min_length) { 100.225 + size_t desired_min_length = 0; 100.226 if (adaptive_young_list_length()) { 100.227 - size_t rs_lengths = (size_t) get_new_prediction(_rs_lengths_seq); 100.228 - calculate_young_list_target_length(rs_lengths); 100.229 - } else { 100.230 - if (full_young_gcs()) 100.231 - _young_list_target_length = _young_list_fixed_length; 100.232 - else 100.233 - _young_list_target_length = _young_list_fixed_length / 2; 100.234 + if (_alloc_rate_ms_seq->num() > 3) { 100.235 + double now_sec = os::elapsedTime(); 100.236 + double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0; 100.237 + double alloc_rate_ms = predict_alloc_rate_ms(); 100.238 + desired_min_length = (size_t) ceil(alloc_rate_ms * when_ms); 100.239 + } else { 100.240 + // otherwise we don't have enough info to make the prediction 100.241 + } 100.242 } 100.243 - 100.244 - // Make sure we allow the application to allocate at least one 100.245 - // region before we need to do a collection again. 100.246 - size_t min_length = _g1->young_list()->length() + 1; 100.247 - _young_list_target_length = MAX2(_young_list_target_length, min_length); 100.248 - calculate_max_gc_locker_expansion(); 100.249 - calculate_survivors_policy(); 100.250 + desired_min_length += base_min_length; 100.251 + // make sure we don't go below any user-defined minimum bound 100.252 + return MAX2(_min_desired_young_length, desired_min_length); 100.253 } 100.254 100.255 -void G1CollectorPolicy::calculate_young_list_target_length(size_t rs_lengths) { 100.256 - guarantee( adaptive_young_list_length(), "pre-condition" ); 100.257 - guarantee( !_in_marking_window || !_last_full_young_gc, "invariant" ); 100.258 - 100.259 - double start_time_sec = os::elapsedTime(); 100.260 - size_t min_reserve_perc = MAX2((size_t)2, (size_t)G1ReservePercent); 100.261 - min_reserve_perc = MIN2((size_t) 50, min_reserve_perc); 100.262 - size_t reserve_regions = 100.263 - (size_t) ((double) min_reserve_perc * (double) _g1->n_regions() / 100.0); 100.264 - 100.265 - if (full_young_gcs() && _free_regions_at_end_of_collection > 0) { 100.266 - // we are in fully-young mode and there are free regions in the heap 100.267 - 100.268 - double survivor_regions_evac_time = 100.269 - predict_survivor_regions_evac_time(); 100.270 - 100.271 - double target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; 100.272 - size_t pending_cards = (size_t) get_new_prediction(_pending_cards_seq); 100.273 - size_t adj_rs_lengths = rs_lengths + predict_rs_length_diff(); 100.274 - size_t scanned_cards = predict_young_card_num(adj_rs_lengths); 100.275 - double base_time_ms = predict_base_elapsed_time_ms(pending_cards, scanned_cards) 100.276 - + survivor_regions_evac_time; 100.277 - 100.278 - // the result 100.279 - size_t final_young_length = 0; 100.280 - 100.281 - size_t init_free_regions = 100.282 - MAX2((size_t)0, _free_regions_at_end_of_collection - reserve_regions); 100.283 - 100.284 - // if we're still under the pause target... 100.285 - if (base_time_ms <= target_pause_time_ms) { 100.286 - // We make sure that the shortest young length that makes sense 100.287 - // fits within the target pause time. 100.288 - size_t min_young_length = 1; 100.289 - 100.290 - if (predict_will_fit(min_young_length, base_time_ms, 100.291 - init_free_regions, target_pause_time_ms)) { 100.292 - // The shortest young length will fit within the target pause time; 100.293 - // we'll now check whether the absolute maximum number of young 100.294 - // regions will fit in the target pause time. If not, we'll do 100.295 - // a binary search between min_young_length and max_young_length 100.296 - size_t abs_max_young_length = _free_regions_at_end_of_collection - 1; 100.297 - size_t max_young_length = abs_max_young_length; 100.298 - 100.299 - if (max_young_length > min_young_length) { 100.300 - // Let's check if the initial max young length will fit within the 100.301 - // target pause. If so then there is no need to search for a maximal 100.302 - // young length - we'll return the initial maximum 100.303 - 100.304 - if (predict_will_fit(max_young_length, base_time_ms, 100.305 - init_free_regions, target_pause_time_ms)) { 100.306 - // The maximum young length will satisfy the target pause time. 100.307 - // We are done so set min young length to this maximum length. 100.308 - // The code after the loop will then set final_young_length using 100.309 - // the value cached in the minimum length. 100.310 - min_young_length = max_young_length; 100.311 - } else { 100.312 - // The maximum possible number of young regions will not fit within 100.313 - // the target pause time so let's search.... 100.314 - 100.315 - size_t diff = (max_young_length - min_young_length) / 2; 100.316 - max_young_length = min_young_length + diff; 100.317 - 100.318 - while (max_young_length > min_young_length) { 100.319 - if (predict_will_fit(max_young_length, base_time_ms, 100.320 - init_free_regions, target_pause_time_ms)) { 100.321 - 100.322 - // The current max young length will fit within the target 100.323 - // pause time. Note we do not exit the loop here. By setting 100.324 - // min = max, and then increasing the max below means that 100.325 - // we will continue searching for an upper bound in the 100.326 - // range [max..max+diff] 100.327 - min_young_length = max_young_length; 100.328 - } 100.329 - diff = (max_young_length - min_young_length) / 2; 100.330 - max_young_length = min_young_length + diff; 100.331 - } 100.332 - // the above loop found a maximal young length that will fit 100.333 - // within the target pause time. 100.334 - } 100.335 - assert(min_young_length <= abs_max_young_length, "just checking"); 100.336 - } 100.337 - final_young_length = min_young_length; 100.338 - } 100.339 - } 100.340 - // and we're done! 100.341 - 100.342 - // we should have at least one region in the target young length 100.343 - _young_list_target_length = 100.344 - final_young_length + _recorded_survivor_regions; 100.345 - 100.346 - // let's keep an eye of how long we spend on this calculation 100.347 - // right now, I assume that we'll print it when we need it; we 100.348 - // should really adde it to the breakdown of a pause 100.349 - double end_time_sec = os::elapsedTime(); 100.350 - double elapsed_time_ms = (end_time_sec - start_time_sec) * 1000.0; 100.351 - 100.352 -#ifdef TRACE_CALC_YOUNG_LENGTH 100.353 - // leave this in for debugging, just in case 100.354 - gclog_or_tty->print_cr("target = %1.1lf ms, young = " SIZE_FORMAT ", " 100.355 - "elapsed %1.2lf ms, (%s%s) " SIZE_FORMAT SIZE_FORMAT, 100.356 - target_pause_time_ms, 100.357 - _young_list_target_length 100.358 - elapsed_time_ms, 100.359 - full_young_gcs() ? "full" : "partial", 100.360 - during_initial_mark_pause() ? " i-m" : "", 100.361 - _in_marking_window, 100.362 - _in_marking_window_im); 100.363 -#endif // TRACE_CALC_YOUNG_LENGTH 100.364 - 100.365 - if (_young_list_target_length < _young_list_min_length) { 100.366 - // bummer; this means that, if we do a pause when the maximal 100.367 - // length dictates, we'll violate the pause spacing target (the 100.368 - // min length was calculate based on the application's current 100.369 - // alloc rate); 100.370 - 100.371 - // so, we have to bite the bullet, and allocate the minimum 100.372 - // number. We'll violate our target, but we just can't meet it. 100.373 - 100.374 -#ifdef TRACE_CALC_YOUNG_LENGTH 100.375 - // leave this in for debugging, just in case 100.376 - gclog_or_tty->print_cr("adjusted target length from " 100.377 - SIZE_FORMAT " to " SIZE_FORMAT, 100.378 - _young_list_target_length, _young_list_min_length); 100.379 -#endif // TRACE_CALC_YOUNG_LENGTH 100.380 - 100.381 - _young_list_target_length = _young_list_min_length; 100.382 +size_t G1CollectorPolicy::calculate_young_list_desired_max_length() { 100.383 + // Here, we might want to also take into account any additional 100.384 + // constraints (i.e., user-defined minimum bound). Currently, we 100.385 + // effectively don't set this bound. 100.386 + return _max_desired_young_length; 100.387 +} 100.388 + 100.389 +void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) { 100.390 + if (rs_lengths == (size_t) -1) { 100.391 + // if it's set to the default value (-1), we should predict it; 100.392 + // otherwise, use the given value. 100.393 + rs_lengths = (size_t) get_new_prediction(_rs_lengths_seq); 100.394 + } 100.395 + 100.396 + // Calculate the absolute and desired min bounds. 100.397 + 100.398 + // This is how many young regions we already have (currently: the survivors). 100.399 + size_t base_min_length = recorded_survivor_regions(); 100.400 + // This is the absolute minimum young length, which ensures that we 100.401 + // can allocate one eden region in the worst-case. 100.402 + size_t absolute_min_length = base_min_length + 1; 100.403 + size_t desired_min_length = 100.404 + calculate_young_list_desired_min_length(base_min_length); 100.405 + if (desired_min_length < absolute_min_length) { 100.406 + desired_min_length = absolute_min_length; 100.407 + } 100.408 + 100.409 + // Calculate the absolute and desired max bounds. 100.410 + 100.411 + // We will try our best not to "eat" into the reserve. 100.412 + size_t absolute_max_length = 0; 100.413 + if (_free_regions_at_end_of_collection > _reserve_regions) { 100.414 + absolute_max_length = _free_regions_at_end_of_collection - _reserve_regions; 100.415 + } 100.416 + size_t desired_max_length = calculate_young_list_desired_max_length(); 100.417 + if (desired_max_length > absolute_max_length) { 100.418 + desired_max_length = absolute_max_length; 100.419 + } 100.420 + 100.421 + size_t young_list_target_length = 0; 100.422 + if (adaptive_young_list_length()) { 100.423 + if (full_young_gcs()) { 100.424 + young_list_target_length = 100.425 + calculate_young_list_target_length(rs_lengths, 100.426 + base_min_length, 100.427 + desired_min_length, 100.428 + desired_max_length); 100.429 + _rs_lengths_prediction = rs_lengths; 100.430 + } else { 100.431 + // Don't calculate anything and let the code below bound it to 100.432 + // the desired_min_length, i.e., do the next GC as soon as 100.433 + // possible to maximize how many old regions we can add to it. 100.434 } 100.435 } else { 100.436 - // we are in a partially-young mode or we've run out of regions (due 100.437 - // to evacuation failure) 100.438 - 100.439 -#ifdef TRACE_CALC_YOUNG_LENGTH 100.440 - // leave this in for debugging, just in case 100.441 - gclog_or_tty->print_cr("(partial) setting target to " SIZE_FORMAT 100.442 - _young_list_min_length); 100.443 -#endif // TRACE_CALC_YOUNG_LENGTH 100.444 - // we'll do the pause as soon as possible by choosing the minimum 100.445 - _young_list_target_length = _young_list_min_length; 100.446 + if (full_young_gcs()) { 100.447 + young_list_target_length = _young_list_fixed_length; 100.448 + } else { 100.449 + // A bit arbitrary: during partially-young GCs we allocate half 100.450 + // the young regions to try to add old regions to the CSet. 100.451 + young_list_target_length = _young_list_fixed_length / 2; 100.452 + // We choose to accept that we might go under the desired min 100.453 + // length given that we intentionally ask for a smaller young gen. 100.454 + desired_min_length = absolute_min_length; 100.455 + } 100.456 } 100.457 100.458 - _rs_lengths_prediction = rs_lengths; 100.459 + // Make sure we don't go over the desired max length, nor under the 100.460 + // desired min length. In case they clash, desired_min_length wins 100.461 + // which is why that test is second. 100.462 + if (young_list_target_length > desired_max_length) { 100.463 + young_list_target_length = desired_max_length; 100.464 + } 100.465 + if (young_list_target_length < desired_min_length) { 100.466 + young_list_target_length = desired_min_length; 100.467 + } 100.468 + 100.469 + assert(young_list_target_length > recorded_survivor_regions(), 100.470 + "we should be able to allocate at least one eden region"); 100.471 + assert(young_list_target_length >= absolute_min_length, "post-condition"); 100.472 + _young_list_target_length = young_list_target_length; 100.473 + 100.474 + update_max_gc_locker_expansion(); 100.475 } 100.476 100.477 -// This is used by: calculate_young_list_target_length(rs_length). It 100.478 -// returns true iff: 100.479 -// the predicted pause time for the given young list will not overflow 100.480 -// the target pause time 100.481 -// and: 100.482 -// the predicted amount of surviving data will not overflow the 100.483 -// the amount of free space available for survivor regions. 100.484 -// 100.485 -bool 100.486 -G1CollectorPolicy::predict_will_fit(size_t young_length, 100.487 - double base_time_ms, 100.488 - size_t init_free_regions, 100.489 - double target_pause_time_ms) { 100.490 - 100.491 - if (young_length >= init_free_regions) 100.492 - // end condition 1: not enough space for the young regions 100.493 - return false; 100.494 - 100.495 - double accum_surv_rate_adj = 0.0; 100.496 - double accum_surv_rate = 100.497 - accum_yg_surv_rate_pred((int)(young_length - 1)) - accum_surv_rate_adj; 100.498 - 100.499 - size_t bytes_to_copy = 100.500 - (size_t) (accum_surv_rate * (double) HeapRegion::GrainBytes); 100.501 - 100.502 - double copy_time_ms = predict_object_copy_time_ms(bytes_to_copy); 100.503 - 100.504 - double young_other_time_ms = 100.505 - predict_young_other_time_ms(young_length); 100.506 - 100.507 - double pause_time_ms = 100.508 - base_time_ms + copy_time_ms + young_other_time_ms; 100.509 - 100.510 - if (pause_time_ms > target_pause_time_ms) 100.511 - // end condition 2: over the target pause time 100.512 - return false; 100.513 - 100.514 - size_t free_bytes = 100.515 - (init_free_regions - young_length) * HeapRegion::GrainBytes; 100.516 - 100.517 - if ((2.0 + sigma()) * (double) bytes_to_copy > (double) free_bytes) 100.518 - // end condition 3: out of to-space (conservatively) 100.519 - return false; 100.520 - 100.521 - // success! 100.522 - return true; 100.523 +size_t 100.524 +G1CollectorPolicy::calculate_young_list_target_length(size_t rs_lengths, 100.525 + size_t base_min_length, 100.526 + size_t desired_min_length, 100.527 + size_t desired_max_length) { 100.528 + assert(adaptive_young_list_length(), "pre-condition"); 100.529 + assert(full_young_gcs(), "only call this for fully-young GCs"); 100.530 + 100.531 + // In case some edge-condition makes the desired max length too small... 100.532 + if (desired_max_length <= desired_min_length) { 100.533 + return desired_min_length; 100.534 + } 100.535 + 100.536 + // We'll adjust min_young_length and max_young_length not to include 100.537 + // the already allocated young regions (i.e., so they reflect the 100.538 + // min and max eden regions we'll allocate). The base_min_length 100.539 + // will be reflected in the predictions by the 100.540 + // survivor_regions_evac_time prediction. 100.541 + assert(desired_min_length > base_min_length, "invariant"); 100.542 + size_t min_young_length = desired_min_length - base_min_length; 100.543 + assert(desired_max_length > base_min_length, "invariant"); 100.544 + size_t max_young_length = desired_max_length - base_min_length; 100.545 + 100.546 + double target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; 100.547 + double survivor_regions_evac_time = predict_survivor_regions_evac_time(); 100.548 + size_t pending_cards = (size_t) get_new_prediction(_pending_cards_seq); 100.549 + size_t adj_rs_lengths = rs_lengths + predict_rs_length_diff(); 100.550 + size_t scanned_cards = predict_young_card_num(adj_rs_lengths); 100.551 + double base_time_ms = 100.552 + predict_base_elapsed_time_ms(pending_cards, scanned_cards) + 100.553 + survivor_regions_evac_time; 100.554 + size_t available_free_regions = _free_regions_at_end_of_collection; 100.555 + size_t base_free_regions = 0; 100.556 + if (available_free_regions > _reserve_regions) { 100.557 + base_free_regions = available_free_regions - _reserve_regions; 100.558 + } 100.559 + 100.560 + // Here, we will make sure that the shortest young length that 100.561 + // makes sense fits within the target pause time. 100.562 + 100.563 + if (predict_will_fit(min_young_length, base_time_ms, 100.564 + base_free_regions, target_pause_time_ms)) { 100.565 + // The shortest young length will fit into the target pause time; 100.566 + // we'll now check whether the absolute maximum number of young 100.567 + // regions will fit in the target pause time. If not, we'll do 100.568 + // a binary search between min_young_length and max_young_length. 100.569 + if (predict_will_fit(max_young_length, base_time_ms, 100.570 + base_free_regions, target_pause_time_ms)) { 100.571 + // The maximum young length will fit into the target pause time. 100.572 + // We are done so set min young length to the maximum length (as 100.573 + // the result is assumed to be returned in min_young_length). 100.574 + min_young_length = max_young_length; 100.575 + } else { 100.576 + // The maximum possible number of young regions will not fit within 100.577 + // the target pause time so we'll search for the optimal 100.578 + // length. The loop invariants are: 100.579 + // 100.580 + // min_young_length < max_young_length 100.581 + // min_young_length is known to fit into the target pause time 100.582 + // max_young_length is known not to fit into the target pause time 100.583 + // 100.584 + // Going into the loop we know the above hold as we've just 100.585 + // checked them. Every time around the loop we check whether 100.586 + // the middle value between min_young_length and 100.587 + // max_young_length fits into the target pause time. If it 100.588 + // does, it becomes the new min. If it doesn't, it becomes 100.589 + // the new max. This way we maintain the loop invariants. 100.590 + 100.591 + assert(min_young_length < max_young_length, "invariant"); 100.592 + size_t diff = (max_young_length - min_young_length) / 2; 100.593 + while (diff > 0) { 100.594 + size_t young_length = min_young_length + diff; 100.595 + if (predict_will_fit(young_length, base_time_ms, 100.596 + base_free_regions, target_pause_time_ms)) { 100.597 + min_young_length = young_length; 100.598 + } else { 100.599 + max_young_length = young_length; 100.600 + } 100.601 + assert(min_young_length < max_young_length, "invariant"); 100.602 + diff = (max_young_length - min_young_length) / 2; 100.603 + } 100.604 + // The results is min_young_length which, according to the 100.605 + // loop invariants, should fit within the target pause time. 100.606 + 100.607 + // These are the post-conditions of the binary search above: 100.608 + assert(min_young_length < max_young_length, 100.609 + "otherwise we should have discovered that max_young_length " 100.610 + "fits into the pause target and not done the binary search"); 100.611 + assert(predict_will_fit(min_young_length, base_time_ms, 100.612 + base_free_regions, target_pause_time_ms), 100.613 + "min_young_length, the result of the binary search, should " 100.614 + "fit into the pause target"); 100.615 + assert(!predict_will_fit(min_young_length + 1, base_time_ms, 100.616 + base_free_regions, target_pause_time_ms), 100.617 + "min_young_length, the result of the binary search, should be " 100.618 + "optimal, so no larger length should fit into the pause target"); 100.619 + } 100.620 + } else { 100.621 + // Even the minimum length doesn't fit into the pause time 100.622 + // target, return it as the result nevertheless. 100.623 + } 100.624 + return base_min_length + min_young_length; 100.625 } 100.626 100.627 double G1CollectorPolicy::predict_survivor_regions_evac_time() { 100.628 @@ -726,17 +797,19 @@ 100.629 return survivor_regions_evac_time; 100.630 } 100.631 100.632 -void G1CollectorPolicy::check_prediction_validity() { 100.633 +void G1CollectorPolicy::revise_young_list_target_length_if_necessary() { 100.634 guarantee( adaptive_young_list_length(), "should not call this otherwise" ); 100.635 100.636 size_t rs_lengths = _g1->young_list()->sampled_rs_lengths(); 100.637 if (rs_lengths > _rs_lengths_prediction) { 100.638 // add 10% to avoid having to recalculate often 100.639 size_t rs_lengths_prediction = rs_lengths * 1100 / 1000; 100.640 - calculate_young_list_target_length(rs_lengths_prediction); 100.641 + update_young_list_target_length(rs_lengths_prediction); 100.642 } 100.643 } 100.644 100.645 + 100.646 + 100.647 HeapWord* G1CollectorPolicy::mem_allocate_work(size_t size, 100.648 bool is_tlab, 100.649 bool* gc_overhead_limit_was_exceeded) { 100.650 @@ -843,8 +916,7 @@ 100.651 _free_regions_at_end_of_collection = _g1->free_regions(); 100.652 // Reset survivors SurvRateGroup. 100.653 _survivor_surv_rate_group->reset(); 100.654 - calculate_young_list_min_length(); 100.655 - calculate_young_list_target_length(); 100.656 + update_young_list_target_length(); 100.657 } 100.658 100.659 void G1CollectorPolicy::record_stop_world_start() { 100.660 @@ -859,6 +931,11 @@ 100.661 gclog_or_tty->print(" (%s)", full_young_gcs() ? "young" : "partial"); 100.662 } 100.663 100.664 + // We only need to do this here as the policy will only be applied 100.665 + // to the GC we're about to start. so, no point is calculating this 100.666 + // every time we calculate / recalculate the target young length. 100.667 + update_survivors_policy(); 100.668 + 100.669 assert(_g1->used() == _g1->recalculate_used(), 100.670 err_msg("sanity, used: "SIZE_FORMAT" recalculate_used: "SIZE_FORMAT, 100.671 _g1->used(), _g1->recalculate_used())); 100.672 @@ -959,11 +1036,9 @@ 100.673 G1CollectorPolicy:: 100.674 record_concurrent_mark_cleanup_end_work1(size_t freed_bytes, 100.675 size_t max_live_bytes) { 100.676 - if (_n_marks < 2) _n_marks++; 100.677 - if (G1PolicyVerbose > 0) 100.678 - gclog_or_tty->print_cr("At end of marking, max_live is " SIZE_FORMAT " MB " 100.679 - " (of " SIZE_FORMAT " MB heap).", 100.680 - max_live_bytes/M, _g1->capacity()/M); 100.681 + if (_n_marks < 2) { 100.682 + _n_marks++; 100.683 + } 100.684 } 100.685 100.686 // The important thing about this is that it includes "os::elapsedTime". 100.687 @@ -977,14 +1052,6 @@ 100.688 _mmu_tracker->add_pause(_mark_cleanup_start_sec, end_time_sec, true); 100.689 100.690 _num_markings++; 100.691 - 100.692 - // We did a marking, so reset the "since_last_mark" variables. 100.693 - double considerConcMarkCost = 1.0; 100.694 - // If there are available processors, concurrent activity is free... 100.695 - if (Threads::number_of_non_daemon_threads() * 2 < 100.696 - os::active_processor_count()) { 100.697 - considerConcMarkCost = 0.0; 100.698 - } 100.699 _n_pauses_at_mark_end = _n_pauses; 100.700 _n_marks_since_last_pause++; 100.701 } 100.702 @@ -994,8 +1061,6 @@ 100.703 _should_revert_to_full_young_gcs = false; 100.704 _last_full_young_gc = true; 100.705 _in_marking_window = false; 100.706 - if (adaptive_young_list_length()) 100.707 - calculate_young_list_target_length(); 100.708 } 100.709 100.710 void G1CollectorPolicy::record_concurrent_pause() { 100.711 @@ -1148,20 +1213,37 @@ 100.712 if (last_pause_included_initial_mark) 100.713 record_concurrent_mark_init_end(0.0); 100.714 100.715 - size_t min_used_targ = 100.716 + size_t marking_initiating_used_threshold = 100.717 (_g1->capacity() / 100) * InitiatingHeapOccupancyPercent; 100.718 100.719 - 100.720 if (!_g1->mark_in_progress() && !_last_full_young_gc) { 100.721 assert(!last_pause_included_initial_mark, "invariant"); 100.722 - if (cur_used_bytes > min_used_targ && 100.723 - cur_used_bytes > _prev_collection_pause_used_at_end_bytes) { 100.724 + if (cur_used_bytes > marking_initiating_used_threshold) { 100.725 + if (cur_used_bytes > _prev_collection_pause_used_at_end_bytes) { 100.726 assert(!during_initial_mark_pause(), "we should not see this here"); 100.727 100.728 + ergo_verbose3(ErgoConcCycles, 100.729 + "request concurrent cycle initiation", 100.730 + ergo_format_reason("occupancy higher than threshold") 100.731 + ergo_format_byte("occupancy") 100.732 + ergo_format_byte_perc("threshold"), 100.733 + cur_used_bytes, 100.734 + marking_initiating_used_threshold, 100.735 + (double) InitiatingHeapOccupancyPercent); 100.736 + 100.737 // Note: this might have already been set, if during the last 100.738 // pause we decided to start a cycle but at the beginning of 100.739 // this pause we decided to postpone it. That's OK. 100.740 set_initiate_conc_mark_if_possible(); 100.741 + } else { 100.742 + ergo_verbose2(ErgoConcCycles, 100.743 + "do not request concurrent cycle initiation", 100.744 + ergo_format_reason("occupancy lower than previous occupancy") 100.745 + ergo_format_byte("occupancy") 100.746 + ergo_format_byte("previous occupancy"), 100.747 + cur_used_bytes, 100.748 + _prev_collection_pause_used_at_end_bytes); 100.749 + } 100.750 } 100.751 } 100.752 100.753 @@ -1437,16 +1519,45 @@ 100.754 } 100.755 100.756 if (_last_full_young_gc) { 100.757 + ergo_verbose2(ErgoPartiallyYoungGCs, 100.758 + "start partially-young GCs", 100.759 + ergo_format_byte_perc("known garbage"), 100.760 + _known_garbage_bytes, _known_garbage_ratio * 100.0); 100.761 set_full_young_gcs(false); 100.762 _last_full_young_gc = false; 100.763 } 100.764 100.765 if ( !_last_young_gc_full ) { 100.766 - if ( _should_revert_to_full_young_gcs || 100.767 - _known_garbage_ratio < 0.05 || 100.768 - (adaptive_young_list_length() && 100.769 - (get_gc_eff_factor() * cur_efficiency < predict_young_gc_eff())) ) { 100.770 - set_full_young_gcs(true); 100.771 + if (_should_revert_to_full_young_gcs) { 100.772 + ergo_verbose2(ErgoPartiallyYoungGCs, 100.773 + "end partially-young GCs", 100.774 + ergo_format_reason("partially-young GCs end requested") 100.775 + ergo_format_byte_perc("known garbage"), 100.776 + _known_garbage_bytes, _known_garbage_ratio * 100.0); 100.777 + set_full_young_gcs(true); 100.778 + } else if (_known_garbage_ratio < 0.05) { 100.779 + ergo_verbose3(ErgoPartiallyYoungGCs, 100.780 + "end partially-young GCs", 100.781 + ergo_format_reason("known garbage percent lower than threshold") 100.782 + ergo_format_byte_perc("known garbage") 100.783 + ergo_format_perc("threshold"), 100.784 + _known_garbage_bytes, _known_garbage_ratio * 100.0, 100.785 + 0.05 * 100.0); 100.786 + set_full_young_gcs(true); 100.787 + } else if (adaptive_young_list_length() && 100.788 + (get_gc_eff_factor() * cur_efficiency < predict_young_gc_eff())) { 100.789 + ergo_verbose5(ErgoPartiallyYoungGCs, 100.790 + "end partially-young GCs", 100.791 + ergo_format_reason("current GC efficiency lower than " 100.792 + "predicted fully-young GC efficiency") 100.793 + ergo_format_double("GC efficiency factor") 100.794 + ergo_format_double("current GC efficiency") 100.795 + ergo_format_double("predicted fully-young GC efficiency") 100.796 + ergo_format_byte_perc("known garbage"), 100.797 + get_gc_eff_factor(), cur_efficiency, 100.798 + predict_young_gc_eff(), 100.799 + _known_garbage_bytes, _known_garbage_ratio * 100.0); 100.800 + set_full_young_gcs(true); 100.801 } 100.802 } 100.803 _should_revert_to_full_young_gcs = false; 100.804 @@ -1600,8 +1711,7 @@ 100.805 _in_marking_window = new_in_marking_window; 100.806 _in_marking_window_im = new_in_marking_window_im; 100.807 _free_regions_at_end_of_collection = _g1->free_regions(); 100.808 - calculate_young_list_min_length(); 100.809 - calculate_young_list_target_length(); 100.810 + update_young_list_target_length(); 100.811 100.812 // Note that _mmu_tracker->max_gc_time() returns the time in seconds. 100.813 double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0; 100.814 @@ -1622,20 +1732,26 @@ 100.815 size_t used_before_gc = _cur_collection_pause_used_at_start_bytes; 100.816 size_t used = _g1->used(); 100.817 size_t capacity = _g1->capacity(); 100.818 + size_t eden_capacity = 100.819 + (_young_list_target_length * HeapRegion::GrainBytes) - survivor_bytes; 100.820 100.821 gclog_or_tty->print_cr( 100.822 - " [Eden: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" " 100.823 - "Survivors: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" " 100.824 - "Heap: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->" 100.825 - EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")]", 100.826 - EXT_SIZE_PARAMS(_eden_bytes_before_gc), 100.827 - EXT_SIZE_PARAMS(eden_bytes), 100.828 - EXT_SIZE_PARAMS(_survivor_bytes_before_gc), 100.829 - EXT_SIZE_PARAMS(survivor_bytes), 100.830 - EXT_SIZE_PARAMS(used_before_gc), 100.831 - EXT_SIZE_PARAMS(_capacity_before_gc), 100.832 - EXT_SIZE_PARAMS(used), 100.833 - EXT_SIZE_PARAMS(capacity)); 100.834 + " [Eden: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT") " 100.835 + "Survivors: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" " 100.836 + "Heap: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->" 100.837 + EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")]", 100.838 + EXT_SIZE_PARAMS(_eden_bytes_before_gc), 100.839 + EXT_SIZE_PARAMS(_prev_eden_capacity), 100.840 + EXT_SIZE_PARAMS(eden_bytes), 100.841 + EXT_SIZE_PARAMS(eden_capacity), 100.842 + EXT_SIZE_PARAMS(_survivor_bytes_before_gc), 100.843 + EXT_SIZE_PARAMS(survivor_bytes), 100.844 + EXT_SIZE_PARAMS(used_before_gc), 100.845 + EXT_SIZE_PARAMS(_capacity_before_gc), 100.846 + EXT_SIZE_PARAMS(used), 100.847 + EXT_SIZE_PARAMS(capacity)); 100.848 + 100.849 + _prev_eden_capacity = eden_capacity; 100.850 } else if (PrintGC) { 100.851 _g1->print_size_transition(gclog_or_tty, 100.852 _cur_collection_pause_used_at_start_bytes, 100.853 @@ -1877,6 +1993,12 @@ 100.854 // I don't think we need to do this when in young GC mode since 100.855 // marking will be initiated next time we hit the soft limit anyway... 100.856 if (predicted_time_ms > _expensive_region_limit_ms) { 100.857 + ergo_verbose2(ErgoPartiallyYoungGCs, 100.858 + "request partially-young GCs end", 100.859 + ergo_format_reason("predicted region time higher than threshold") 100.860 + ergo_format_ms("predicted region time") 100.861 + ergo_format_ms("threshold"), 100.862 + predicted_time_ms, _expensive_region_limit_ms); 100.863 // no point in doing another partial one 100.864 _should_revert_to_full_young_gcs = true; 100.865 } 100.866 @@ -1986,7 +2108,9 @@ 100.867 } 100.868 100.869 size_t G1CollectorPolicy::expansion_amount() { 100.870 - if ((recent_avg_pause_time_ratio() * 100.0) > _gc_overhead_perc) { 100.871 + double recent_gc_overhead = recent_avg_pause_time_ratio() * 100.0; 100.872 + double threshold = _gc_overhead_perc; 100.873 + if (recent_gc_overhead > threshold) { 100.874 // We will double the existing space, or take 100.875 // G1ExpandByPercentOfAvailable % of the available expansion 100.876 // space, whichever is smaller, bounded below by a minimum 100.877 @@ -2001,20 +2125,19 @@ 100.878 expand_bytes = MIN2(expand_bytes_via_pct, committed_bytes); 100.879 expand_bytes = MAX2(expand_bytes, min_expand_bytes); 100.880 expand_bytes = MIN2(expand_bytes, uncommitted_bytes); 100.881 - if (G1PolicyVerbose > 1) { 100.882 - gclog_or_tty->print("Decided to expand: ratio = %5.2f, " 100.883 - "committed = %d%s, uncommited = %d%s, via pct = %d%s.\n" 100.884 - " Answer = %d.\n", 100.885 - recent_avg_pause_time_ratio(), 100.886 - byte_size_in_proper_unit(committed_bytes), 100.887 - proper_unit_for_byte_size(committed_bytes), 100.888 - byte_size_in_proper_unit(uncommitted_bytes), 100.889 - proper_unit_for_byte_size(uncommitted_bytes), 100.890 - byte_size_in_proper_unit(expand_bytes_via_pct), 100.891 - proper_unit_for_byte_size(expand_bytes_via_pct), 100.892 - byte_size_in_proper_unit(expand_bytes), 100.893 - proper_unit_for_byte_size(expand_bytes)); 100.894 - } 100.895 + 100.896 + ergo_verbose5(ErgoHeapSizing, 100.897 + "attempt heap expansion", 100.898 + ergo_format_reason("recent GC overhead higher than " 100.899 + "threshold after GC") 100.900 + ergo_format_perc("recent GC overhead") 100.901 + ergo_format_perc("threshold") 100.902 + ergo_format_byte("uncommitted") 100.903 + ergo_format_byte_perc("calculated expansion amount"), 100.904 + recent_gc_overhead, threshold, 100.905 + uncommitted_bytes, 100.906 + expand_bytes_via_pct, (double) G1ExpandByPercentOfAvailable); 100.907 + 100.908 return expand_bytes; 100.909 } else { 100.910 return 0; 100.911 @@ -2237,8 +2360,7 @@ 100.912 #endif // PRODUCT 100.913 } 100.914 100.915 -void 100.916 -G1CollectorPolicy::update_region_num(bool young) { 100.917 +void G1CollectorPolicy::update_region_num(bool young) { 100.918 if (young) { 100.919 ++_region_num_young; 100.920 } else { 100.921 @@ -2270,7 +2392,7 @@ 100.922 }; 100.923 } 100.924 100.925 -void G1CollectorPolicy::calculate_max_gc_locker_expansion() { 100.926 +void G1CollectorPolicy::update_max_gc_locker_expansion() { 100.927 size_t expansion_region_num = 0; 100.928 if (GCLockerEdenExpansionPercent > 0) { 100.929 double perc = (double) GCLockerEdenExpansionPercent / 100.0; 100.930 @@ -2286,9 +2408,13 @@ 100.931 } 100.932 100.933 // Calculates survivor space parameters. 100.934 -void G1CollectorPolicy::calculate_survivors_policy() 100.935 -{ 100.936 - _max_survivor_regions = _young_list_target_length / SurvivorRatio; 100.937 +void G1CollectorPolicy::update_survivors_policy() { 100.938 + double max_survivor_regions_d = 100.939 + (double) _young_list_target_length / (double) SurvivorRatio; 100.940 + // We use ceiling so that if max_survivor_regions_d is > 0.0 (but 100.941 + // smaller than 1.0) we'll get 1. 100.942 + _max_survivor_regions = (size_t) ceil(max_survivor_regions_d); 100.943 + 100.944 _tenuring_threshold = _survivors_age_table.compute_tenuring_threshold( 100.945 HeapRegion::GrainWords * _max_survivor_regions); 100.946 } 100.947 @@ -2315,13 +2441,23 @@ 100.948 } 100.949 #endif 100.950 100.951 -bool 100.952 -G1CollectorPolicy::force_initial_mark_if_outside_cycle() { 100.953 +bool G1CollectorPolicy::force_initial_mark_if_outside_cycle( 100.954 + GCCause::Cause gc_cause) { 100.955 bool during_cycle = _g1->concurrent_mark()->cmThread()->during_cycle(); 100.956 if (!during_cycle) { 100.957 + ergo_verbose1(ErgoConcCycles, 100.958 + "request concurrent cycle initiation", 100.959 + ergo_format_reason("requested by GC cause") 100.960 + ergo_format_str("GC cause"), 100.961 + GCCause::to_string(gc_cause)); 100.962 set_initiate_conc_mark_if_possible(); 100.963 return true; 100.964 } else { 100.965 + ergo_verbose1(ErgoConcCycles, 100.966 + "do not request concurrent cycle initiation", 100.967 + ergo_format_reason("concurrent cycle already in progress") 100.968 + ergo_format_str("GC cause"), 100.969 + GCCause::to_string(gc_cause)); 100.970 return false; 100.971 } 100.972 } 100.973 @@ -2353,6 +2489,10 @@ 100.974 // And we can now clear initiate_conc_mark_if_possible() as 100.975 // we've already acted on it. 100.976 clear_initiate_conc_mark_if_possible(); 100.977 + 100.978 + ergo_verbose0(ErgoConcCycles, 100.979 + "initiate concurrent cycle", 100.980 + ergo_format_reason("concurrent cycle initiation requested")); 100.981 } else { 100.982 // The concurrent marking thread is still finishing up the 100.983 // previous cycle. If we start one right now the two cycles 100.984 @@ -2366,6 +2506,9 @@ 100.985 // and, if it's in a yield point, it's waiting for us to 100.986 // finish. So, at this point we will not start a cycle and we'll 100.987 // let the concurrent marking thread complete the last one. 100.988 + ergo_verbose0(ErgoConcCycles, 100.989 + "do not initiate concurrent cycle", 100.990 + ergo_format_reason("concurrent cycle already in progress")); 100.991 } 100.992 } 100.993 } 100.994 @@ -2756,6 +2899,8 @@ 100.995 // Set this here - in case we're not doing young collections. 100.996 double non_young_start_time_sec = os::elapsedTime(); 100.997 100.998 + YoungList* young_list = _g1->young_list(); 100.999 + 100.1000 start_recording_regions(); 100.1001 100.1002 guarantee(target_pause_time_ms > 0.0, 100.1003 @@ -2768,61 +2913,62 @@ 100.1004 100.1005 double time_remaining_ms = target_pause_time_ms - base_time_ms; 100.1006 100.1007 + ergo_verbose3(ErgoCSetConstruction | ErgoHigh, 100.1008 + "start choosing CSet", 100.1009 + ergo_format_ms("predicted base time") 100.1010 + ergo_format_ms("remaining time") 100.1011 + ergo_format_ms("target pause time"), 100.1012 + base_time_ms, time_remaining_ms, target_pause_time_ms); 100.1013 + 100.1014 // the 10% and 50% values are arbitrary... 100.1015 - if (time_remaining_ms < 0.10 * target_pause_time_ms) { 100.1016 + double threshold = 0.10 * target_pause_time_ms; 100.1017 + if (time_remaining_ms < threshold) { 100.1018 + double prev_time_remaining_ms = time_remaining_ms; 100.1019 time_remaining_ms = 0.50 * target_pause_time_ms; 100.1020 _within_target = false; 100.1021 + ergo_verbose3(ErgoCSetConstruction, 100.1022 + "adjust remaining time", 100.1023 + ergo_format_reason("remaining time lower than threshold") 100.1024 + ergo_format_ms("remaining time") 100.1025 + ergo_format_ms("threshold") 100.1026 + ergo_format_ms("adjusted remaining time"), 100.1027 + prev_time_remaining_ms, threshold, time_remaining_ms); 100.1028 } else { 100.1029 _within_target = true; 100.1030 } 100.1031 100.1032 - // We figure out the number of bytes available for future to-space. 100.1033 - // For new regions without marking information, we must assume the 100.1034 - // worst-case of complete survival. If we have marking information for a 100.1035 - // region, we can bound the amount of live data. We can add a number of 100.1036 - // such regions, as long as the sum of the live data bounds does not 100.1037 - // exceed the available evacuation space. 100.1038 - size_t max_live_bytes = _g1->free_regions() * HeapRegion::GrainBytes; 100.1039 - 100.1040 - size_t expansion_bytes = 100.1041 - _g1->expansion_regions() * HeapRegion::GrainBytes; 100.1042 + size_t expansion_bytes = _g1->expansion_regions() * HeapRegion::GrainBytes; 100.1043 + 100.1044 + HeapRegion* hr; 100.1045 + double young_start_time_sec = os::elapsedTime(); 100.1046 100.1047 _collection_set_bytes_used_before = 0; 100.1048 _collection_set_size = 0; 100.1049 - 100.1050 - // Adjust for expansion and slop. 100.1051 - max_live_bytes = max_live_bytes + expansion_bytes; 100.1052 - 100.1053 - HeapRegion* hr; 100.1054 - double young_start_time_sec = os::elapsedTime(); 100.1055 - 100.1056 - if (G1PolicyVerbose > 0) { 100.1057 - gclog_or_tty->print_cr("Adding %d young regions to the CSet", 100.1058 - _g1->young_list()->length()); 100.1059 - } 100.1060 - 100.1061 _young_cset_length = 0; 100.1062 _last_young_gc_full = full_young_gcs() ? true : false; 100.1063 100.1064 - if (_last_young_gc_full) 100.1065 + if (_last_young_gc_full) { 100.1066 ++_full_young_pause_num; 100.1067 - else 100.1068 + } else { 100.1069 ++_partial_young_pause_num; 100.1070 + } 100.1071 100.1072 // The young list is laid with the survivor regions from the previous 100.1073 // pause are appended to the RHS of the young list, i.e. 100.1074 // [Newly Young Regions ++ Survivors from last pause]. 100.1075 100.1076 - hr = _g1->young_list()->first_survivor_region(); 100.1077 + size_t survivor_region_num = young_list->survivor_length(); 100.1078 + size_t eden_region_num = young_list->length() - survivor_region_num; 100.1079 + size_t old_region_num = 0; 100.1080 + hr = young_list->first_survivor_region(); 100.1081 while (hr != NULL) { 100.1082 assert(hr->is_survivor(), "badly formed young list"); 100.1083 hr->set_young(); 100.1084 hr = hr->get_next_young_region(); 100.1085 } 100.1086 100.1087 - // Clear the fields that point to the survivor list - they are 100.1088 - // all young now. 100.1089 - _g1->young_list()->clear_survivors(); 100.1090 + // Clear the fields that point to the survivor list - they are all young now. 100.1091 + young_list->clear_survivors(); 100.1092 100.1093 if (_g1->mark_in_progress()) 100.1094 _g1->concurrent_mark()->register_collection_set_finger(_inc_cset_max_finger); 100.1095 @@ -2831,14 +2977,17 @@ 100.1096 _collection_set = _inc_cset_head; 100.1097 _collection_set_size = _inc_cset_size; 100.1098 _collection_set_bytes_used_before = _inc_cset_bytes_used_before; 100.1099 - 100.1100 - // For young regions in the collection set, we assume the worst 100.1101 - // case of complete survival 100.1102 - max_live_bytes -= _inc_cset_size * HeapRegion::GrainBytes; 100.1103 - 100.1104 time_remaining_ms -= _inc_cset_predicted_elapsed_time_ms; 100.1105 predicted_pause_time_ms += _inc_cset_predicted_elapsed_time_ms; 100.1106 100.1107 + ergo_verbose3(ErgoCSetConstruction | ErgoHigh, 100.1108 + "add young regions to CSet", 100.1109 + ergo_format_region("eden") 100.1110 + ergo_format_region("survivors") 100.1111 + ergo_format_ms("predicted young region time"), 100.1112 + eden_region_num, survivor_region_num, 100.1113 + _inc_cset_predicted_elapsed_time_ms); 100.1114 + 100.1115 // The number of recorded young regions is the incremental 100.1116 // collection set's current size 100.1117 set_recorded_young_regions(_inc_cset_size); 100.1118 @@ -2848,14 +2997,7 @@ 100.1119 set_predicted_bytes_to_copy(_inc_cset_predicted_bytes_to_copy); 100.1120 #endif // PREDICTIONS_VERBOSE 100.1121 100.1122 - if (G1PolicyVerbose > 0) { 100.1123 - gclog_or_tty->print_cr(" Added " PTR_FORMAT " Young Regions to CS.", 100.1124 - _inc_cset_size); 100.1125 - gclog_or_tty->print_cr(" (" SIZE_FORMAT " KB left in heap.)", 100.1126 - max_live_bytes/K); 100.1127 - } 100.1128 - 100.1129 - assert(_inc_cset_size == _g1->young_list()->length(), "Invariant"); 100.1130 + assert(_inc_cset_size == young_list->length(), "Invariant"); 100.1131 100.1132 double young_end_time_sec = os::elapsedTime(); 100.1133 _recorded_young_cset_choice_time_ms = 100.1134 @@ -2869,6 +3011,8 @@ 100.1135 NumberSeq seq; 100.1136 double avg_prediction = 100000000000000000.0; // something very large 100.1137 100.1138 + size_t prev_collection_set_size = _collection_set_size; 100.1139 + double prev_predicted_pause_time_ms = predicted_pause_time_ms; 100.1140 do { 100.1141 hr = _collectionSetChooser->getNextMarkedRegion(time_remaining_ms, 100.1142 avg_prediction); 100.1143 @@ -2878,23 +3022,58 @@ 100.1144 predicted_pause_time_ms += predicted_time_ms; 100.1145 add_to_collection_set(hr); 100.1146 record_non_young_cset_region(hr); 100.1147 - max_live_bytes -= MIN2(hr->max_live_bytes(), max_live_bytes); 100.1148 - if (G1PolicyVerbose > 0) { 100.1149 - gclog_or_tty->print_cr(" (" SIZE_FORMAT " KB left in heap.)", 100.1150 - max_live_bytes/K); 100.1151 - } 100.1152 seq.add(predicted_time_ms); 100.1153 avg_prediction = seq.avg() + seq.sd(); 100.1154 } 100.1155 - should_continue = 100.1156 - ( hr != NULL) && 100.1157 - ( (adaptive_young_list_length()) ? time_remaining_ms > 0.0 100.1158 - : _collection_set_size < _young_list_fixed_length ); 100.1159 + 100.1160 + should_continue = true; 100.1161 + if (hr == NULL) { 100.1162 + // No need for an ergo verbose message here, 100.1163 + // getNextMarkRegion() does this when it returns NULL. 100.1164 + should_continue = false; 100.1165 + } else { 100.1166 + if (adaptive_young_list_length()) { 100.1167 + if (time_remaining_ms < 0.0) { 100.1168 + ergo_verbose1(ErgoCSetConstruction, 100.1169 + "stop adding old regions to CSet", 100.1170 + ergo_format_reason("remaining time is lower than 0") 100.1171 + ergo_format_ms("remaining time"), 100.1172 + time_remaining_ms); 100.1173 + should_continue = false; 100.1174 + } 100.1175 + } else { 100.1176 + if (_collection_set_size < _young_list_fixed_length) { 100.1177 + ergo_verbose2(ErgoCSetConstruction, 100.1178 + "stop adding old regions to CSet", 100.1179 + ergo_format_reason("CSet length lower than target") 100.1180 + ergo_format_region("CSet") 100.1181 + ergo_format_region("young target"), 100.1182 + _collection_set_size, _young_list_fixed_length); 100.1183 + should_continue = false; 100.1184 + } 100.1185 + } 100.1186 + } 100.1187 } while (should_continue); 100.1188 100.1189 if (!adaptive_young_list_length() && 100.1190 - _collection_set_size < _young_list_fixed_length) 100.1191 + _collection_set_size < _young_list_fixed_length) { 100.1192 + ergo_verbose2(ErgoCSetConstruction, 100.1193 + "request partially-young GCs end", 100.1194 + ergo_format_reason("CSet length lower than target") 100.1195 + ergo_format_region("CSet") 100.1196 + ergo_format_region("young target"), 100.1197 + _collection_set_size, _young_list_fixed_length); 100.1198 _should_revert_to_full_young_gcs = true; 100.1199 + } 100.1200 + 100.1201 + old_region_num = _collection_set_size - prev_collection_set_size; 100.1202 + 100.1203 + ergo_verbose2(ErgoCSetConstruction | ErgoHigh, 100.1204 + "add old regions to CSet", 100.1205 + ergo_format_region("old") 100.1206 + ergo_format_ms("predicted old region time"), 100.1207 + old_region_num, 100.1208 + predicted_pause_time_ms - prev_predicted_pause_time_ms); 100.1209 } 100.1210 100.1211 stop_incremental_cset_building(); 100.1212 @@ -2903,6 +3082,16 @@ 100.1213 100.1214 end_recording_regions(); 100.1215 100.1216 + ergo_verbose5(ErgoCSetConstruction, 100.1217 + "finish choosing CSet", 100.1218 + ergo_format_region("eden") 100.1219 + ergo_format_region("survivors") 100.1220 + ergo_format_region("old") 100.1221 + ergo_format_ms("predicted pause time") 100.1222 + ergo_format_ms("target pause time"), 100.1223 + eden_region_num, survivor_region_num, old_region_num, 100.1224 + predicted_pause_time_ms, target_pause_time_ms); 100.1225 + 100.1226 double non_young_end_time_sec = os::elapsedTime(); 100.1227 _recorded_non_young_cset_choice_time_ms = 100.1228 (non_young_end_time_sec - non_young_start_time_sec) * 1000.0; 100.1229 @@ -2914,12 +3103,6 @@ 100.1230 } 100.1231 100.1232 void G1CollectorPolicy_BestRegionsFirst:: 100.1233 -expand_if_possible(size_t numRegions) { 100.1234 - size_t expansion_bytes = numRegions * HeapRegion::GrainBytes; 100.1235 - _g1->expand(expansion_bytes); 100.1236 -} 100.1237 - 100.1238 -void G1CollectorPolicy_BestRegionsFirst:: 100.1239 record_collection_pause_end() { 100.1240 G1CollectorPolicy::record_collection_pause_end(); 100.1241 assert(assertMarkedBytesDataOK(), "Marked regions not OK at pause end.");
101.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Sep 08 16:59:27 2011 -0700 101.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Fri Sep 09 16:17:16 2011 -0700 101.3 @@ -183,9 +183,9 @@ 101.4 // if true, then it tries to dynamically adjust the length of the 101.5 // young list 101.6 bool _adaptive_young_list_length; 101.7 - size_t _young_list_min_length; 101.8 size_t _young_list_target_length; 101.9 size_t _young_list_fixed_length; 101.10 + size_t _prev_eden_capacity; // used for logging 101.11 101.12 // The max number of regions we can extend the eden by while the GC 101.13 // locker is active. This should be >= _young_list_target_length; 101.14 @@ -207,6 +207,9 @@ 101.15 101.16 double _gc_overhead_perc; 101.17 101.18 + double _reserve_factor; 101.19 + size_t _reserve_regions; 101.20 + 101.21 bool during_marking() { 101.22 return _during_marking; 101.23 } 101.24 @@ -243,6 +246,10 @@ 101.25 101.26 TruncatedSeq* _max_conc_overhead_seq; 101.27 101.28 + bool _using_new_ratio_calculations; 101.29 + size_t _min_desired_young_length; // as set on the command line or default calculations 101.30 + size_t _max_desired_young_length; // as set on the command line or default calculations 101.31 + 101.32 size_t _recorded_young_regions; 101.33 size_t _recorded_non_young_regions; 101.34 size_t _recorded_region_num; 101.35 @@ -456,12 +463,6 @@ 101.36 size_t predict_bytes_to_copy(HeapRegion* hr); 101.37 double predict_region_elapsed_time_ms(HeapRegion* hr, bool young); 101.38 101.39 - // for use by: calculate_young_list_target_length(rs_length) 101.40 - bool predict_will_fit(size_t young_region_num, 101.41 - double base_time_ms, 101.42 - size_t init_free_regions, 101.43 - double target_pause_time_ms); 101.44 - 101.45 void start_recording_regions(); 101.46 void record_cset_region_info(HeapRegion* hr, bool young); 101.47 void record_non_young_cset_region(HeapRegion* hr); 101.48 @@ -493,7 +494,6 @@ 101.49 101.50 // </NEW PREDICTION> 101.51 101.52 -public: 101.53 void cset_regions_freed() { 101.54 bool propagate = _last_young_gc_full && !_in_marking_window; 101.55 _short_lived_surv_rate_group->all_surviving_words_recorded(propagate); 101.56 @@ -772,9 +772,41 @@ 101.57 double _mark_cleanup_start_sec; 101.58 double _mark_closure_time_ms; 101.59 101.60 - void calculate_young_list_min_length(); 101.61 - void calculate_young_list_target_length(); 101.62 - void calculate_young_list_target_length(size_t rs_lengths); 101.63 + // Update the young list target length either by setting it to the 101.64 + // desired fixed value or by calculating it using G1's pause 101.65 + // prediction model. If no rs_lengths parameter is passed, predict 101.66 + // the RS lengths using the prediction model, otherwise use the 101.67 + // given rs_lengths as the prediction. 101.68 + void update_young_list_target_length(size_t rs_lengths = (size_t) -1); 101.69 + 101.70 + // Calculate and return the minimum desired young list target 101.71 + // length. This is the minimum desired young list length according 101.72 + // to the user's inputs. 101.73 + size_t calculate_young_list_desired_min_length(size_t base_min_length); 101.74 + 101.75 + // Calculate and return the maximum desired young list target 101.76 + // length. This is the maximum desired young list length according 101.77 + // to the user's inputs. 101.78 + size_t calculate_young_list_desired_max_length(); 101.79 + 101.80 + // Calculate and return the maximum young list target length that 101.81 + // can fit into the pause time goal. The parameters are: rs_lengths 101.82 + // represent the prediction of how large the young RSet lengths will 101.83 + // be, base_min_length is the alreay existing number of regions in 101.84 + // the young list, min_length and max_length are the desired min and 101.85 + // max young list length according to the user's inputs. 101.86 + size_t calculate_young_list_target_length(size_t rs_lengths, 101.87 + size_t base_min_length, 101.88 + size_t desired_min_length, 101.89 + size_t desired_max_length); 101.90 + 101.91 + // Check whether a given young length (young_length) fits into the 101.92 + // given target pause time and whether the prediction for the amount 101.93 + // of objects to be copied for the given length will fit into the 101.94 + // given free space (expressed by base_free_regions). It is used by 101.95 + // calculate_young_list_target_length(). 101.96 + bool predict_will_fit(size_t young_length, double base_time_ms, 101.97 + size_t base_free_regions, double target_pause_time_ms); 101.98 101.99 public: 101.100 101.101 @@ -786,7 +818,10 @@ 101.102 return CollectorPolicy::G1CollectorPolicyKind; 101.103 } 101.104 101.105 - void check_prediction_validity(); 101.106 + // Check the current value of the young list RSet lengths and 101.107 + // compare it against the last prediction. If the current value is 101.108 + // higher, recalculate the young list target length prediction. 101.109 + void revise_young_list_target_length_if_necessary(); 101.110 101.111 size_t bytes_in_collection_set() { 101.112 return _bytes_in_collection_set_before_gc; 101.113 @@ -796,6 +831,9 @@ 101.114 return _all_pause_times_ms->num() + 1; 101.115 } 101.116 101.117 + // This should be called after the heap is resized. 101.118 + void record_new_heap_size(size_t new_number_of_regions); 101.119 + 101.120 protected: 101.121 101.122 // Count the number of bytes used in the CS. 101.123 @@ -807,6 +845,8 @@ 101.124 size_t max_live_bytes); 101.125 void record_concurrent_mark_cleanup_end_work2(); 101.126 101.127 + void update_young_list_size_using_newratio(size_t number_of_heap_regions); 101.128 + 101.129 public: 101.130 101.131 virtual void init(); 101.132 @@ -1045,7 +1085,7 @@ 101.133 // new cycle, as long as we are not already in one. It's best if it 101.134 // is called during a safepoint when the test whether a cycle is in 101.135 // progress or not is stable. 101.136 - bool force_initial_mark_if_outside_cycle(); 101.137 + bool force_initial_mark_if_outside_cycle(GCCause::Cause gc_cause); 101.138 101.139 // This is called at the very beginning of an evacuation pause (it 101.140 // has to be the first thing that the pause does). If 101.141 @@ -1204,10 +1244,10 @@ 101.142 _survivors_age_table.merge_par(age_table); 101.143 } 101.144 101.145 - void calculate_max_gc_locker_expansion(); 101.146 + void update_max_gc_locker_expansion(); 101.147 101.148 // Calculates survivor space parameters. 101.149 - void calculate_survivors_policy(); 101.150 + void update_survivors_policy(); 101.151 101.152 }; 101.153 101.154 @@ -1234,8 +1274,6 @@ 101.155 101.156 class G1CollectorPolicy_BestRegionsFirst: public G1CollectorPolicy { 101.157 CollectionSetChooser* _collectionSetChooser; 101.158 - // If the estimated is less then desirable, resize if possible. 101.159 - void expand_if_possible(size_t numRegions); 101.160 101.161 virtual void choose_collection_set(double target_pause_time_ms); 101.162 virtual void record_collection_pause_start(double start_time_sec, 101.163 @@ -1269,8 +1307,4 @@ 101.164 return (sum_of_squares - 2.0 * avg * sum + n_d * avg * avg) / n_d; 101.165 } 101.166 101.167 -// Local Variables: *** 101.168 -// c-indentation-style: gnu *** 101.169 -// End: *** 101.170 - 101.171 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTORPOLICY_HPP
102.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 102.2 +++ b/src/share/vm/gc_implementation/g1/g1ErgoVerbose.cpp Fri Sep 09 16:17:16 2011 -0700 102.3 @@ -0,0 +1,65 @@ 102.4 +/* 102.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 102.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 102.7 + * 102.8 + * This code is free software; you can redistribute it and/or modify it 102.9 + * under the terms of the GNU General Public License version 2 only, as 102.10 + * published by the Free Software Foundation. 102.11 + * 102.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 102.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 102.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 102.15 + * version 2 for more details (a copy is included in the LICENSE file that 102.16 + * accompanied this code). 102.17 + * 102.18 + * You should have received a copy of the GNU General Public License version 102.19 + * 2 along with this work; if not, write to the Free Software Foundation, 102.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 102.21 + * 102.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 102.23 + * or visit www.oracle.com if you need additional information or have any 102.24 + * questions. 102.25 + * 102.26 + */ 102.27 + 102.28 +#include "precompiled.hpp" 102.29 +#include "gc_implementation/g1/g1ErgoVerbose.hpp" 102.30 +#include "utilities/ostream.hpp" 102.31 + 102.32 +ErgoLevel G1ErgoVerbose::_level; 102.33 +bool G1ErgoVerbose::_enabled[ErgoHeuristicNum]; 102.34 + 102.35 +void G1ErgoVerbose::initialize() { 102.36 + set_level(ErgoLow); 102.37 + set_enabled(false); 102.38 +} 102.39 + 102.40 +void G1ErgoVerbose::set_level(ErgoLevel level) { 102.41 + _level = level; 102.42 +} 102.43 + 102.44 +void G1ErgoVerbose::set_enabled(ErgoHeuristic n, bool enabled) { 102.45 + assert(0 <= n && n < ErgoHeuristicNum, "pre-condition"); 102.46 + _enabled[n] = enabled; 102.47 +} 102.48 + 102.49 +void G1ErgoVerbose::set_enabled(bool enabled) { 102.50 + for (int n = 0; n < ErgoHeuristicNum; n += 1) { 102.51 + set_enabled((ErgoHeuristic) n, enabled); 102.52 + } 102.53 +} 102.54 + 102.55 +const char* G1ErgoVerbose::to_string(int tag) { 102.56 + ErgoHeuristic n = extract_heuristic(tag); 102.57 + switch (n) { 102.58 + case ErgoHeapSizing: return "Heap Sizing"; 102.59 + case ErgoCSetConstruction: return "CSet Construction"; 102.60 + case ErgoConcCycles: return "Concurrent Cycles"; 102.61 + case ErgoPartiallyYoungGCs: return "Partially-Young GCs"; 102.62 + default: 102.63 + ShouldNotReachHere(); 102.64 + // Keep the Windows compiler happy 102.65 + return NULL; 102.66 + } 102.67 +} 102.68 +
103.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 103.2 +++ b/src/share/vm/gc_implementation/g1/g1ErgoVerbose.hpp Fri Sep 09 16:17:16 2011 -0700 103.3 @@ -0,0 +1,197 @@ 103.4 +/* 103.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 103.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 103.7 + * 103.8 + * This code is free software; you can redistribute it and/or modify it 103.9 + * under the terms of the GNU General Public License version 2 only, as 103.10 + * published by the Free Software Foundation. 103.11 + * 103.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 103.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 103.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 103.15 + * version 2 for more details (a copy is included in the LICENSE file that 103.16 + * accompanied this code). 103.17 + * 103.18 + * You should have received a copy of the GNU General Public License version 103.19 + * 2 along with this work; if not, write to the Free Software Foundation, 103.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 103.21 + * 103.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 103.23 + * or visit www.oracle.com if you need additional information or have any 103.24 + * questions. 103.25 + * 103.26 + */ 103.27 + 103.28 +#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1ERGOVERBOSE_HPP 103.29 +#define SHARE_VM_GC_IMPLEMENTATION_G1_G1ERGOVERBOSE_HPP 103.30 + 103.31 +#include "memory/allocation.hpp" 103.32 +#include "utilities/debug.hpp" 103.33 + 103.34 +// The log of G1's heuristic decisions comprises of a series of 103.35 +// records which have a similar format in order to maintain 103.36 +// consistency across records and ultimately easier parsing of the 103.37 +// output, if we ever choose to do that. Each record consists of: 103.38 +// * A time stamp to be able to easily correlate each record with 103.39 +// other events. 103.40 +// * A unique string to allow us to easily identify such records. 103.41 +// * The name of the heuristic the record corresponds to. 103.42 +// * An action string which describes the action that G1 did or is 103.43 +// about to do. 103.44 +// * An optional reason string which describes the reason for the 103.45 +// action. 103.46 +// * An optional number of name/value pairs which contributed to the 103.47 +// decision to take the action described in the record. 103.48 +// 103.49 +// Each record is associated with a "tag" which is the combination of 103.50 +// the heuristic the record corresponds to, as well as the min level 103.51 +// of verboseness at which the record should be printed. The tag is 103.52 +// checked against the current settings to determine whether the record 103.53 +// should be printed or not. 103.54 + 103.55 +// The available verboseness levels. 103.56 +typedef enum { 103.57 + // Determine which part of the tag is occupied by the level. 103.58 + ErgoLevelShift = 8, 103.59 + ErgoLevelMask = ~((1 << ErgoLevelShift) - 1), 103.60 + 103.61 + // ErgoLow is 0 so that we don't have to explicitly or a heuristic 103.62 + // id with ErgoLow to keep its use simpler. 103.63 + ErgoLow = 0, 103.64 + ErgoHigh = 1 << ErgoLevelShift, 103.65 +} ErgoLevel; 103.66 + 103.67 +// The available heuristics. 103.68 +typedef enum { 103.69 + // Determines which part of the tag is occupied by the heuristic id. 103.70 + ErgoHeuristicMask = ~ErgoLevelMask, 103.71 + 103.72 + ErgoHeapSizing = 0, 103.73 + ErgoCSetConstruction, 103.74 + ErgoConcCycles, 103.75 + ErgoPartiallyYoungGCs, 103.76 + 103.77 + ErgoHeuristicNum 103.78 +} ErgoHeuristic; 103.79 + 103.80 +class G1ErgoVerbose : AllStatic { 103.81 +private: 103.82 + // Determines the minimum verboseness level at which records will be 103.83 + // printed. 103.84 + static ErgoLevel _level; 103.85 + // Determines which heuristics are currently enabled. 103.86 + static bool _enabled[ErgoHeuristicNum]; 103.87 + 103.88 + static ErgoLevel extract_level(int tag) { 103.89 + return (ErgoLevel) (tag & ErgoLevelMask); 103.90 + } 103.91 + 103.92 + static ErgoHeuristic extract_heuristic(int tag) { 103.93 + return (ErgoHeuristic) (tag & ErgoHeuristicMask); 103.94 + } 103.95 + 103.96 +public: 103.97 + // Needs to be explicitly called at GC initialization. 103.98 + static void initialize(); 103.99 + 103.100 + static void set_level(ErgoLevel level); 103.101 + static void set_enabled(ErgoHeuristic h, bool enabled); 103.102 + // It is applied to all heuristics. 103.103 + static void set_enabled(bool enabled); 103.104 + 103.105 + static bool enabled(int tag) { 103.106 + ErgoLevel level = extract_level(tag); 103.107 + ErgoHeuristic n = extract_heuristic(tag); 103.108 + return level <= _level && _enabled[n]; 103.109 + } 103.110 + 103.111 + // Extract the heuristic id from the tag and return a string with 103.112 + // its name. 103.113 + static const char* to_string(int tag); 103.114 +}; 103.115 + 103.116 +// The macros below generate the format string for values of different 103.117 +// types and/or metrics. 103.118 + 103.119 +// The reason for the action is optional and is handled specially: the 103.120 +// reason string is concatenated here so it's not necessary to pass it 103.121 +// as a parameter. 103.122 +#define ergo_format_reason(_reason_) ", reason: " _reason_ 103.123 + 103.124 +// Single parameter format strings 103.125 +#define ergo_format_str(_name_) ", " _name_ ": %s" 103.126 +#define ergo_format_region(_name_) ", " _name_ ": "SIZE_FORMAT" regions" 103.127 +#define ergo_format_byte(_name_) ", " _name_ ": "SIZE_FORMAT" bytes" 103.128 +#define ergo_format_double(_name_) ", " _name_ ": %1.2f" 103.129 +#define ergo_format_perc(_name_) ", " _name_ ": %1.2f %%" 103.130 +#define ergo_format_ms(_name_) ", " _name_ ": %1.2f ms" 103.131 + 103.132 +// Double parameter format strings 103.133 +#define ergo_format_byte_perc(_name_) \ 103.134 + ", " _name_ ": "SIZE_FORMAT" bytes (%1.2f %%)" 103.135 + 103.136 +// Generates the format string 103.137 +#define ergo_format(_action_, _extra_format_) \ 103.138 + " %1.3f: [G1Ergonomics (%s) " _action_ _extra_format_ "]" 103.139 + 103.140 +// Conditionally, prints an ergonomic decision record. _extra_format_ 103.141 +// is the format string for the optional items we'd like to print 103.142 +// (i.e., the decision's reason and any associated values). This 103.143 +// string should be built up using the ergo_*_format macros (see 103.144 +// above) to ensure consistency. 103.145 +// 103.146 +// Since we cannot rely on the compiler supporting variable argument 103.147 +// macros, this macro accepts a fixed number of arguments and passes 103.148 +// them to the print method. For convenience, we have wrapper macros 103.149 +// below which take a specific number of arguments and set the rest to 103.150 +// a default value. 103.151 +#define ergo_verbose_common(_tag_, _action_, _extra_format_, \ 103.152 + _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, _arg5_) \ 103.153 + do { \ 103.154 + if (G1ErgoVerbose::enabled((_tag_))) { \ 103.155 + gclog_or_tty->print_cr(ergo_format(_action_, _extra_format_), \ 103.156 + os::elapsedTime(), \ 103.157 + G1ErgoVerbose::to_string((_tag_)), \ 103.158 + (_arg0_), (_arg1_), (_arg2_), \ 103.159 + (_arg3_), (_arg4_), (_arg5_)); \ 103.160 + } \ 103.161 + } while (0) 103.162 + 103.163 + 103.164 +#define ergo_verbose(_tag_, _action_) \ 103.165 + ergo_verbose_common(_tag_, _action_, "", 0, 0, 0, 0, 0, 0) 103.166 + 103.167 +#define ergo_verbose0(_tag_, _action_, _extra_format_) \ 103.168 + ergo_verbose_common(_tag_, _action_, _extra_format_, 0, 0, 0, 0, 0, 0) 103.169 + 103.170 +#define ergo_verbose1(_tag_, _action_, _extra_format_, \ 103.171 + _arg0_) \ 103.172 + ergo_verbose_common(_tag_, _action_, _extra_format_, \ 103.173 + _arg0_, 0, 0, 0, 0, 0) 103.174 + 103.175 +#define ergo_verbose2(_tag_, _action_, _extra_format_, \ 103.176 + _arg0_, _arg1_) \ 103.177 + ergo_verbose_common(_tag_, _action_, _extra_format_, \ 103.178 + _arg0_, _arg1_, 0, 0, 0, 0) 103.179 + 103.180 +#define ergo_verbose3(_tag_, _action_, _extra_format_, \ 103.181 + _arg0_, _arg1_, _arg2_) \ 103.182 + ergo_verbose_common(_tag_, _action_, _extra_format_, \ 103.183 + _arg0_, _arg1_, _arg2_, 0, 0, 0) 103.184 + 103.185 +#define ergo_verbose4(_tag_, _action_, _extra_format_, \ 103.186 + _arg0_, _arg1_, _arg2_, _arg3_) \ 103.187 + ergo_verbose_common(_tag_, _action_, _extra_format_, \ 103.188 + _arg0_, _arg1_, _arg2_, _arg3_, 0, 0) 103.189 + 103.190 +#define ergo_verbose5(_tag_, _action_, _extra_format_, \ 103.191 + _arg0_, _arg1_, _arg2_, _arg3_, _arg4_) \ 103.192 + ergo_verbose_common(_tag_, _action_, _extra_format_, \ 103.193 + _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, 0) 103.194 + 103.195 +#define ergo_verbose6(_tag_, _action_, _extra_format_, \ 103.196 + _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, _arg5_) \ 103.197 + ergo_verbose_common(_tag_, _action_, _extra_format_, \ 103.198 + _arg0_, _arg1_, _arg2_, _arg3_, _arg4_, _arg5_) 103.199 + 103.200 +#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1ERGOVERBOSE_HPP
104.1 --- a/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp Thu Sep 08 16:59:27 2011 -0700 104.2 +++ b/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp Fri Sep 09 16:17:16 2011 -0700 104.3 @@ -1,5 +1,5 @@ 104.4 /* 104.5 - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 104.6 + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. 104.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 104.8 * 104.9 * This code is free software; you can redistribute it and/or modify it 104.10 @@ -97,10 +97,6 @@ 104.11 // or performance (we are GC'ing most of the time anyway!), 104.12 // simply overwrite the oldest entry in the tracker. 104.13 104.14 - if (G1PolicyVerbose > 1) { 104.15 - warning("MMU Tracker Queue overflow. Replacing earliest entry."); 104.16 - } 104.17 - 104.18 _head_index = trim_index(_head_index + 1); 104.19 assert(_head_index == _tail_index, "Because we have a full circular buffer"); 104.20 _tail_index = trim_index(_tail_index + 1);
105.1 --- a/src/share/vm/gc_implementation/g1/g1OopClosures.hpp Thu Sep 08 16:59:27 2011 -0700 105.2 +++ b/src/share/vm/gc_implementation/g1/g1OopClosures.hpp Fri Sep 09 16:17:16 2011 -0700 105.3 @@ -50,6 +50,8 @@ 105.4 G1RemSet* _g1_rem; 105.5 ConcurrentMark* _cm; 105.6 G1ParScanThreadState* _par_scan_state; 105.7 + bool _during_initial_mark; 105.8 + bool _mark_in_progress; 105.9 public: 105.10 G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state); 105.11 bool apply_to_weak_ref_discovered_field() { return true; } 105.12 @@ -102,8 +104,8 @@ 105.13 class G1ParCopyHelper : public G1ParClosureSuper { 105.14 G1ParScanClosure *_scanner; 105.15 protected: 105.16 - template <class T> void mark_forwardee(T* p); 105.17 - oop copy_to_survivor_space(oop obj); 105.18 + template <class T> void mark_object(T* p); 105.19 + oop copy_to_survivor_space(oop obj, bool should_mark_copy); 105.20 public: 105.21 G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, 105.22 G1ParScanClosure *scanner) : 105.23 @@ -111,7 +113,7 @@ 105.24 }; 105.25 105.26 template<bool do_gen_barrier, G1Barrier barrier, 105.27 - bool do_mark_forwardee> 105.28 + bool do_mark_object> 105.29 class G1ParCopyClosure : public G1ParCopyHelper { 105.30 G1ParScanClosure _scanner; 105.31 template <class T> void do_oop_work(T* p); 105.32 @@ -120,8 +122,6 @@ 105.33 _scanner(g1, par_scan_state), G1ParCopyHelper(g1, par_scan_state, &_scanner) { } 105.34 template <class T> void do_oop_nv(T* p) { 105.35 do_oop_work(p); 105.36 - if (do_mark_forwardee) 105.37 - mark_forwardee(p); 105.38 } 105.39 virtual void do_oop(oop* p) { do_oop_nv(p); } 105.40 virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
106.1 --- a/src/share/vm/gc_implementation/g1/g1_globals.hpp Thu Sep 08 16:59:27 2011 -0700 106.2 +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp Fri Sep 09 16:17:16 2011 -0700 106.3 @@ -124,9 +124,6 @@ 106.4 develop(bool, G1RSBarrierNullFilter, true, \ 106.5 "If true, generate null-pointer filtering code in RS barrier") \ 106.6 \ 106.7 - develop(bool, G1PrintCTFilterStats, false, \ 106.8 - "If true, print stats on RS filtering effectiveness") \ 106.9 - \ 106.10 develop(bool, G1DeferredRSUpdate, true, \ 106.11 "If true, use deferred RS updates") \ 106.12 \ 106.13 @@ -137,9 +134,9 @@ 106.14 develop(bool, G1RSCountHisto, false, \ 106.15 "If true, print a histogram of RS occupancies after each pause") \ 106.16 \ 106.17 - product(bool, G1PrintRegionLivenessInfo, false, \ 106.18 - "Prints the liveness information for all regions in the heap " \ 106.19 - "at the end of a marking cycle.") \ 106.20 + diagnostic(bool, G1PrintRegionLivenessInfo, false, \ 106.21 + "Prints the liveness information for all regions in the heap " \ 106.22 + "at the end of a marking cycle.") \ 106.23 \ 106.24 develop(bool, G1PrintParCleanupStats, false, \ 106.25 "When true, print extra stats about parallel cleanup.") \ 106.26 @@ -231,7 +228,7 @@ 106.27 "the number of regions for which we'll print a surv rate " \ 106.28 "summary.") \ 106.29 \ 106.30 - product(intx, G1ReservePercent, 10, \ 106.31 + product(uintx, G1ReservePercent, 10, \ 106.32 "It determines the minimum reserve we should have in the heap " \ 106.33 "to minimize the probability of promotion failure.") \ 106.34 \
107.1 --- a/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp Thu Sep 08 16:59:27 2011 -0700 107.2 +++ b/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp Fri Sep 09 16:17:16 2011 -0700 107.3 @@ -36,7 +36,7 @@ 107.4 }; 107.5 107.6 template<bool do_gen_barrier, G1Barrier barrier, 107.7 - bool do_mark_forwardee> 107.8 + bool do_mark_object> 107.9 class G1ParCopyClosure; 107.10 class G1ParScanClosure; 107.11 class G1ParPushHeapRSClosure;
108.1 --- a/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Thu Sep 08 16:59:27 2011 -0700 108.2 +++ b/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Fri Sep 09 16:17:16 2011 -0700 108.3 @@ -98,7 +98,7 @@ 108.4 108.5 // At this point we are supposed to start a concurrent cycle. We 108.6 // will do so if one is not already in progress. 108.7 - bool res = g1h->g1_policy()->force_initial_mark_if_outside_cycle(); 108.8 + bool res = g1h->g1_policy()->force_initial_mark_if_outside_cycle(_gc_cause); 108.9 108.10 // The above routine returns true if we were able to force the 108.11 // next GC pause to be an initial mark; it returns false if a
109.1 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Thu Sep 08 16:59:27 2011 -0700 109.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Fri Sep 09 16:17:16 2011 -0700 109.3 @@ -909,10 +909,6 @@ 109.4 } 109.5 young_gen()->verify(allow_dirty); 109.6 } 109.7 - if (!silent) { 109.8 - gclog_or_tty->print("ref_proc "); 109.9 - } 109.10 - ReferenceProcessor::verify(); 109.11 } 109.12 109.13 void ParallelScavengeHeap::print_heap_change(size_t prev_used) {
110.1 --- a/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Thu Sep 08 16:59:27 2011 -0700 110.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Fri Sep 09 16:17:16 2011 -0700 110.3 @@ -80,10 +80,6 @@ 110.4 Universe::oops_do(&mark_and_push_closure); 110.5 break; 110.6 110.7 - case reference_processing: 110.8 - ReferenceProcessor::oops_do(&mark_and_push_closure); 110.9 - break; 110.10 - 110.11 case jni_handles: 110.12 JNIHandles::oops_do(&mark_and_push_closure); 110.13 break;
111.1 --- a/src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp Thu Sep 08 16:59:27 2011 -0700 111.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp Fri Sep 09 16:17:16 2011 -0700 111.3 @@ -98,8 +98,7 @@ 111.4 management = 6, 111.5 jvmti = 7, 111.6 system_dictionary = 8, 111.7 - reference_processing = 9, 111.8 - code_cache = 10 111.9 + code_cache = 9 111.10 }; 111.11 private: 111.12 RootType _root_type;
112.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu Sep 08 16:59:27 2011 -0700 112.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Sep 09 16:17:16 2011 -0700 112.3 @@ -516,7 +516,6 @@ 112.4 { 112.5 ParallelScavengeHeap::ParStrongRootsScope psrs; 112.6 Universe::oops_do(mark_and_push_closure()); 112.7 - ReferenceProcessor::oops_do(mark_and_push_closure()); 112.8 JNIHandles::oops_do(mark_and_push_closure()); // Global (strong) JNI handles 112.9 CodeBlobToOopClosure each_active_code_blob(mark_and_push_closure(), /*do_marking=*/ true); 112.10 Threads::oops_do(mark_and_push_closure(), &each_active_code_blob); 112.11 @@ -623,7 +622,6 @@ 112.12 112.13 // General strong roots. 112.14 Universe::oops_do(adjust_root_pointer_closure()); 112.15 - ReferenceProcessor::oops_do(adjust_root_pointer_closure()); 112.16 JNIHandles::oops_do(adjust_root_pointer_closure()); // Global (strong) JNI handles 112.17 Threads::oops_do(adjust_root_pointer_closure(), NULL); 112.18 ObjectSynchronizer::oops_do(adjust_root_pointer_closure());
113.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Sep 08 16:59:27 2011 -0700 113.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Sep 09 16:17:16 2011 -0700 113.3 @@ -2445,7 +2445,6 @@ 113.4 113.5 // General strong roots. 113.6 Universe::oops_do(adjust_root_pointer_closure()); 113.7 - ReferenceProcessor::oops_do(adjust_root_pointer_closure()); 113.8 JNIHandles::oops_do(adjust_root_pointer_closure()); // Global (strong) JNI handles 113.9 Threads::oops_do(adjust_root_pointer_closure(), NULL); 113.10 ObjectSynchronizer::oops_do(adjust_root_pointer_closure());
114.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp Thu Sep 08 16:59:27 2011 -0700 114.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp Fri Sep 09 16:17:16 2011 -0700 114.3 @@ -55,7 +55,6 @@ 114.4 switch (_root_type) { 114.5 case universe: 114.6 Universe::oops_do(&roots_closure); 114.7 - ReferenceProcessor::oops_do(&roots_closure); 114.8 break; 114.9 114.10 case jni_handles:
115.1 --- a/src/share/vm/gc_interface/collectedHeap.cpp Thu Sep 08 16:59:27 2011 -0700 115.2 +++ b/src/share/vm/gc_interface/collectedHeap.cpp Fri Sep 09 16:17:16 2011 -0700 115.3 @@ -157,8 +157,14 @@ 115.4 // ..and clear it. 115.5 Copy::zero_to_words(obj, new_tlab_size); 115.6 } else { 115.7 - // ...and clear just the allocated object. 115.8 - Copy::zero_to_words(obj, size); 115.9 + // ...and zap just allocated object. 115.10 +#ifdef ASSERT 115.11 + // Skip mangling the space corresponding to the object header to 115.12 + // ensure that the returned space is not considered parsable by 115.13 + // any concurrent GC thread. 115.14 + size_t hdr_size = oopDesc::header_size(); 115.15 + Copy::fill_to_words(obj + hdr_size, new_tlab_size - hdr_size, badHeapWordVal); 115.16 +#endif // ASSERT 115.17 } 115.18 thread->tlab().fill(obj, obj + size, new_tlab_size); 115.19 return obj;
116.1 --- a/src/share/vm/gc_interface/collectedHeap.inline.hpp Thu Sep 08 16:59:27 2011 -0700 116.2 +++ b/src/share/vm/gc_interface/collectedHeap.inline.hpp Fri Sep 09 16:17:16 2011 -0700 116.3 @@ -287,7 +287,10 @@ 116.4 assert(size >= 0, "int won't convert to size_t"); 116.5 HeapWord* obj = common_permanent_mem_allocate_init(size, CHECK_NULL); 116.6 post_allocation_setup_no_klass_install(klass, obj, size); 116.7 - NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); 116.8 +#ifndef PRODUCT 116.9 + const size_t hs = oopDesc::header_size(); 116.10 + Universe::heap()->check_for_bad_heap_word_value(obj+hs, size-hs); 116.11 +#endif 116.12 return (oop)obj; 116.13 } 116.14
117.1 --- a/src/share/vm/interpreter/bytecodes.hpp Thu Sep 08 16:59:27 2011 -0700 117.2 +++ b/src/share/vm/interpreter/bytecodes.hpp Fri Sep 09 16:17:16 2011 -0700 117.3 @@ -419,6 +419,8 @@ 117.4 117.5 static bool is_zero_const (Code code) { return (code == _aconst_null || code == _iconst_0 117.6 || code == _fconst_0 || code == _dconst_0); } 117.7 + static bool is_invoke (Code code) { return (_invokevirtual <= code && code <= _invokedynamic); } 117.8 + 117.9 static int compute_flags (const char* format, int more_flags = 0); // compute the flags 117.10 static int flags (int code, bool is_wide) { 117.11 assert(code == (u_char)code, "must be a byte");
118.1 --- a/src/share/vm/interpreter/interpreterRuntime.cpp Thu Sep 08 16:59:27 2011 -0700 118.2 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp Fri Sep 09 16:17:16 2011 -0700 118.3 @@ -555,7 +555,7 @@ 118.4 assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "must be"); 118.5 118.6 { 118.7 - // Walk all nmethods depending on CallSite 118.8 + // Walk all nmethods depending on this call site. 118.9 MutexLocker mu(Compile_lock, thread); 118.10 Universe::flush_dependents_on(call_site, method_handle); 118.11 } 118.12 @@ -1244,7 +1244,7 @@ 118.13 // preparing the same method will be sure to see non-null entry & mirror. 118.14 IRT_END 118.15 118.16 -#if defined(IA32) || defined(AMD64) 118.17 +#if defined(IA32) || defined(AMD64) || defined(ARM) 118.18 IRT_LEAF(void, InterpreterRuntime::popframe_move_outgoing_args(JavaThread* thread, void* src_address, void* dest_address)) 118.19 if (src_address == dest_address) { 118.20 return;
119.1 --- a/src/share/vm/interpreter/interpreterRuntime.hpp Thu Sep 08 16:59:27 2011 -0700 119.2 +++ b/src/share/vm/interpreter/interpreterRuntime.hpp Fri Sep 09 16:17:16 2011 -0700 119.3 @@ -141,8 +141,8 @@ 119.4 methodOopDesc* method, 119.5 intptr_t* from, intptr_t* to); 119.6 119.7 -#if defined(IA32) || defined(AMD64) 119.8 - // Popframe support (only needed on x86 and AMD64) 119.9 +#if defined(IA32) || defined(AMD64) || defined(ARM) 119.10 + // Popframe support (only needed on x86, AMD64 and ARM) 119.11 static void popframe_move_outgoing_args(JavaThread* thread, void* src_address, void* dest_address); 119.12 #endif 119.13
120.1 --- a/src/share/vm/memory/genCollectedHeap.cpp Thu Sep 08 16:59:27 2011 -0700 120.2 +++ b/src/share/vm/memory/genCollectedHeap.cpp Fri Sep 09 16:17:16 2011 -0700 120.3 @@ -1269,10 +1269,6 @@ 120.4 gclog_or_tty->print("remset "); 120.5 } 120.6 rem_set()->verify(); 120.7 - if (!silent) { 120.8 - gclog_or_tty->print("ref_proc "); 120.9 - } 120.10 - ReferenceProcessor::verify(); 120.11 } 120.12 120.13 void GenCollectedHeap::print() const { print_on(tty); }
121.1 --- a/src/share/vm/memory/referenceProcessor.cpp Thu Sep 08 16:59:27 2011 -0700 121.2 +++ b/src/share/vm/memory/referenceProcessor.cpp Fri Sep 09 16:17:16 2011 -0700 121.3 @@ -35,15 +35,15 @@ 121.4 121.5 ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL; 121.6 ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy = NULL; 121.7 -oop ReferenceProcessor::_sentinelRef = NULL; 121.8 const int subclasses_of_ref = REF_PHANTOM - REF_OTHER; 121.9 +bool ReferenceProcessor::_pending_list_uses_discovered_field = false; 121.10 121.11 // List of discovered references. 121.12 class DiscoveredList { 121.13 public: 121.14 DiscoveredList() : _len(0), _compressed_head(0), _oop_head(NULL) { } 121.15 oop head() const { 121.16 - return UseCompressedOops ? oopDesc::decode_heap_oop_not_null(_compressed_head) : 121.17 + return UseCompressedOops ? oopDesc::decode_heap_oop(_compressed_head) : 121.18 _oop_head; 121.19 } 121.20 HeapWord* adr_head() { 121.21 @@ -53,12 +53,12 @@ 121.22 void set_head(oop o) { 121.23 if (UseCompressedOops) { 121.24 // Must compress the head ptr. 121.25 - _compressed_head = oopDesc::encode_heap_oop_not_null(o); 121.26 + _compressed_head = oopDesc::encode_heap_oop(o); 121.27 } else { 121.28 _oop_head = o; 121.29 } 121.30 } 121.31 - bool empty() const { return head() == ReferenceProcessor::sentinel_ref(); } 121.32 + bool empty() const { return head() == NULL; } 121.33 size_t length() { return _len; } 121.34 void set_length(size_t len) { _len = len; } 121.35 void inc_length(size_t inc) { _len += inc; assert(_len > 0, "Error"); } 121.36 @@ -76,21 +76,9 @@ 121.37 } 121.38 121.39 void ReferenceProcessor::init_statics() { 121.40 - assert(_sentinelRef == NULL, "should be initialized precisely once"); 121.41 - EXCEPTION_MARK; 121.42 - _sentinelRef = instanceKlass::cast( 121.43 - SystemDictionary::Reference_klass())-> 121.44 - allocate_permanent_instance(THREAD); 121.45 - 121.46 // Initialize the master soft ref clock. 121.47 java_lang_ref_SoftReference::set_clock(os::javaTimeMillis()); 121.48 121.49 - if (HAS_PENDING_EXCEPTION) { 121.50 - Handle ex(THREAD, PENDING_EXCEPTION); 121.51 - vm_exit_during_initialization(ex); 121.52 - } 121.53 - assert(_sentinelRef != NULL && _sentinelRef->is_oop(), 121.54 - "Just constructed it!"); 121.55 _always_clear_soft_ref_policy = new AlwaysClearPolicy(); 121.56 _default_soft_ref_policy = new COMPILER2_PRESENT(LRUMaxHeapPolicy()) 121.57 NOT_COMPILER2(LRUCurrentHeapPolicy()); 121.58 @@ -100,6 +88,7 @@ 121.59 guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery || 121.60 RefDiscoveryPolicy == ReferentBasedDiscovery, 121.61 "Unrecongnized RefDiscoveryPolicy"); 121.62 + _pending_list_uses_discovered_field = JDK_Version::current().pending_list_uses_discovered_field(); 121.63 } 121.64 121.65 ReferenceProcessor::ReferenceProcessor(MemRegion span, 121.66 @@ -130,13 +119,12 @@ 121.67 _discoveredWeakRefs = &_discoveredSoftRefs[_max_num_q]; 121.68 _discoveredFinalRefs = &_discoveredWeakRefs[_max_num_q]; 121.69 _discoveredPhantomRefs = &_discoveredFinalRefs[_max_num_q]; 121.70 - assert(sentinel_ref() != NULL, "_sentinelRef is NULL"); 121.71 - // Initialized all entries to _sentinelRef 121.72 + // Initialized all entries to NULL 121.73 for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { 121.74 - _discoveredSoftRefs[i].set_head(sentinel_ref()); 121.75 + _discoveredSoftRefs[i].set_head(NULL); 121.76 _discoveredSoftRefs[i].set_length(0); 121.77 } 121.78 - // If we do barreirs, cache a copy of the barrier set. 121.79 + // If we do barriers, cache a copy of the barrier set. 121.80 if (discovered_list_needs_barrier) { 121.81 _bs = Universe::heap()->barrier_set(); 121.82 } 121.83 @@ -167,10 +155,6 @@ 121.84 } 121.85 } 121.86 121.87 -void ReferenceProcessor::oops_do(OopClosure* f) { 121.88 - f->do_oop(adr_sentinel_ref()); 121.89 -} 121.90 - 121.91 void ReferenceProcessor::update_soft_ref_master_clock() { 121.92 // Update (advance) the soft ref master clock field. This must be done 121.93 // after processing the soft ref list. 121.94 @@ -283,8 +267,6 @@ 121.95 } 121.96 #endif 121.97 JNIHandles::weak_oops_do(is_alive, keep_alive); 121.98 - // Finally remember to keep sentinel around 121.99 - keep_alive->do_oop(adr_sentinel_ref()); 121.100 complete_gc->do_void(); 121.101 } 121.102 121.103 @@ -327,46 +309,77 @@ 121.104 void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list, 121.105 HeapWord* pending_list_addr) { 121.106 // Given a list of refs linked through the "discovered" field 121.107 - // (java.lang.ref.Reference.discovered) chain them through the 121.108 - // "next" field (java.lang.ref.Reference.next) and prepend 121.109 - // to the pending list. 121.110 + // (java.lang.ref.Reference.discovered), self-loop their "next" field 121.111 + // thus distinguishing them from active References, then 121.112 + // prepend them to the pending list. 121.113 + // BKWRD COMPATIBILITY NOTE: For older JDKs (prior to the fix for 4956777), 121.114 + // the "next" field is used to chain the pending list, not the discovered 121.115 + // field. 121.116 + 121.117 if (TraceReferenceGC && PrintGCDetails) { 121.118 gclog_or_tty->print_cr("ReferenceProcessor::enqueue_discovered_reflist list " 121.119 INTPTR_FORMAT, (address)refs_list.head()); 121.120 } 121.121 - oop obj = refs_list.head(); 121.122 - // Walk down the list, copying the discovered field into 121.123 - // the next field and clearing it (except for the last 121.124 - // non-sentinel object which is treated specially to avoid 121.125 - // confusion with an active reference). 121.126 - while (obj != sentinel_ref()) { 121.127 - assert(obj->is_instanceRef(), "should be reference object"); 121.128 - oop next = java_lang_ref_Reference::discovered(obj); 121.129 - if (TraceReferenceGC && PrintGCDetails) { 121.130 - gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next " INTPTR_FORMAT, 121.131 - obj, next); 121.132 + 121.133 + oop obj = NULL; 121.134 + oop next_d = refs_list.head(); 121.135 + if (pending_list_uses_discovered_field()) { // New behaviour 121.136 + // Walk down the list, self-looping the next field 121.137 + // so that the References are not considered active. 121.138 + while (obj != next_d) { 121.139 + obj = next_d; 121.140 + assert(obj->is_instanceRef(), "should be reference object"); 121.141 + next_d = java_lang_ref_Reference::discovered(obj); 121.142 + if (TraceReferenceGC && PrintGCDetails) { 121.143 + gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT, 121.144 + obj, next_d); 121.145 + } 121.146 + assert(java_lang_ref_Reference::next(obj) == NULL, 121.147 + "Reference not active; should not be discovered"); 121.148 + // Self-loop next, so as to make Ref not active. 121.149 + java_lang_ref_Reference::set_next(obj, obj); 121.150 + if (next_d == obj) { // obj is last 121.151 + // Swap refs_list into pendling_list_addr and 121.152 + // set obj's discovered to what we read from pending_list_addr. 121.153 + oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr); 121.154 + // Need oop_check on pending_list_addr above; 121.155 + // see special oop-check code at the end of 121.156 + // enqueue_discovered_reflists() further below. 121.157 + java_lang_ref_Reference::set_discovered(obj, old); // old may be NULL 121.158 + } 121.159 } 121.160 - assert(java_lang_ref_Reference::next(obj) == NULL, 121.161 - "The reference should not be enqueued"); 121.162 - if (next == sentinel_ref()) { // obj is last 121.163 - // Swap refs_list into pendling_list_addr and 121.164 - // set obj's next to what we read from pending_list_addr. 121.165 - oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr); 121.166 - // Need oop_check on pending_list_addr above; 121.167 - // see special oop-check code at the end of 121.168 - // enqueue_discovered_reflists() further below. 121.169 - if (old == NULL) { 121.170 - // obj should be made to point to itself, since 121.171 - // pending list was empty. 121.172 - java_lang_ref_Reference::set_next(obj, obj); 121.173 + } else { // Old behaviour 121.174 + // Walk down the list, copying the discovered field into 121.175 + // the next field and clearing the discovered field. 121.176 + while (obj != next_d) { 121.177 + obj = next_d; 121.178 + assert(obj->is_instanceRef(), "should be reference object"); 121.179 + next_d = java_lang_ref_Reference::discovered(obj); 121.180 + if (TraceReferenceGC && PrintGCDetails) { 121.181 + gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT, 121.182 + obj, next_d); 121.183 + } 121.184 + assert(java_lang_ref_Reference::next(obj) == NULL, 121.185 + "The reference should not be enqueued"); 121.186 + if (next_d == obj) { // obj is last 121.187 + // Swap refs_list into pendling_list_addr and 121.188 + // set obj's next to what we read from pending_list_addr. 121.189 + oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr); 121.190 + // Need oop_check on pending_list_addr above; 121.191 + // see special oop-check code at the end of 121.192 + // enqueue_discovered_reflists() further below. 121.193 + if (old == NULL) { 121.194 + // obj should be made to point to itself, since 121.195 + // pending list was empty. 121.196 + java_lang_ref_Reference::set_next(obj, obj); 121.197 + } else { 121.198 + java_lang_ref_Reference::set_next(obj, old); 121.199 + } 121.200 } else { 121.201 - java_lang_ref_Reference::set_next(obj, old); 121.202 + java_lang_ref_Reference::set_next(obj, next_d); 121.203 } 121.204 - } else { 121.205 - java_lang_ref_Reference::set_next(obj, next); 121.206 + java_lang_ref_Reference::set_discovered(obj, (oop) NULL); 121.207 } 121.208 - java_lang_ref_Reference::set_discovered(obj, (oop) NULL); 121.209 - obj = next; 121.210 } 121.211 } 121.212 121.213 @@ -376,10 +389,9 @@ 121.214 RefProcEnqueueTask(ReferenceProcessor& ref_processor, 121.215 DiscoveredList discovered_refs[], 121.216 HeapWord* pending_list_addr, 121.217 - oop sentinel_ref, 121.218 int n_queues) 121.219 : EnqueueTask(ref_processor, discovered_refs, 121.220 - pending_list_addr, sentinel_ref, n_queues) 121.221 + pending_list_addr, n_queues) 121.222 { } 121.223 121.224 virtual void work(unsigned int work_id) { 121.225 @@ -396,7 +408,7 @@ 121.226 j++, index += _n_queues) { 121.227 _ref_processor.enqueue_discovered_reflist( 121.228 _refs_lists[index], _pending_list_addr); 121.229 - _refs_lists[index].set_head(_sentinel_ref); 121.230 + _refs_lists[index].set_head(NULL); 121.231 _refs_lists[index].set_length(0); 121.232 } 121.233 } 121.234 @@ -408,13 +420,13 @@ 121.235 if (_processing_is_mt && task_executor != NULL) { 121.236 // Parallel code 121.237 RefProcEnqueueTask tsk(*this, _discoveredSoftRefs, 121.238 - pending_list_addr, sentinel_ref(), _max_num_q); 121.239 + pending_list_addr, _max_num_q); 121.240 task_executor->execute(tsk); 121.241 } else { 121.242 // Serial code: call the parent class's implementation 121.243 for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { 121.244 enqueue_discovered_reflist(_discoveredSoftRefs[i], pending_list_addr); 121.245 - _discoveredSoftRefs[i].set_head(sentinel_ref()); 121.246 + _discoveredSoftRefs[i].set_head(NULL); 121.247 _discoveredSoftRefs[i].set_length(0); 121.248 } 121.249 } 121.250 @@ -428,7 +440,7 @@ 121.251 BoolObjectClosure* is_alive); 121.252 121.253 // End Of List. 121.254 - inline bool has_next() const { return _next != ReferenceProcessor::sentinel_ref(); } 121.255 + inline bool has_next() const { return _ref != NULL; } 121.256 121.257 // Get oop to the Reference object. 121.258 inline oop obj() const { return _ref; } 121.259 @@ -468,9 +480,13 @@ 121.260 inline void update_discovered() { 121.261 // First _prev_next ref actually points into DiscoveredList (gross). 121.262 if (UseCompressedOops) { 121.263 - _keep_alive->do_oop((narrowOop*)_prev_next); 121.264 + if (!oopDesc::is_null(*(narrowOop*)_prev_next)) { 121.265 + _keep_alive->do_oop((narrowOop*)_prev_next); 121.266 + } 121.267 } else { 121.268 - _keep_alive->do_oop((oop*)_prev_next); 121.269 + if (!oopDesc::is_null(*(oop*)_prev_next)) { 121.270 + _keep_alive->do_oop((oop*)_prev_next); 121.271 + } 121.272 } 121.273 } 121.274 121.275 @@ -488,6 +504,7 @@ 121.276 private: 121.277 DiscoveredList& _refs_list; 121.278 HeapWord* _prev_next; 121.279 + oop _prev; 121.280 oop _ref; 121.281 HeapWord* _discovered_addr; 121.282 oop _next; 121.283 @@ -509,6 +526,7 @@ 121.284 BoolObjectClosure* is_alive) 121.285 : _refs_list(refs_list), 121.286 _prev_next(refs_list.adr_head()), 121.287 + _prev(NULL), 121.288 _ref(refs_list.head()), 121.289 #ifdef ASSERT 121.290 _first_seen(refs_list.head()), 121.291 @@ -517,7 +535,7 @@ 121.292 _processed(0), 121.293 _removed(0), 121.294 #endif 121.295 - _next(refs_list.head()), 121.296 + _next(NULL), 121.297 _keep_alive(keep_alive), 121.298 _is_alive(is_alive) 121.299 { } 121.300 @@ -544,26 +562,43 @@ 121.301 121.302 inline void DiscoveredListIterator::next() { 121.303 _prev_next = _discovered_addr; 121.304 + _prev = _ref; 121.305 move_to_next(); 121.306 } 121.307 121.308 inline void DiscoveredListIterator::remove() { 121.309 assert(_ref->is_oop(), "Dropping a bad reference"); 121.310 oop_store_raw(_discovered_addr, NULL); 121.311 + 121.312 // First _prev_next ref actually points into DiscoveredList (gross). 121.313 + oop new_next; 121.314 + if (_next == _ref) { 121.315 + // At the end of the list, we should make _prev point to itself. 121.316 + // If _ref is the first ref, then _prev_next will be in the DiscoveredList, 121.317 + // and _prev will be NULL. 121.318 + new_next = _prev; 121.319 + } else { 121.320 + new_next = _next; 121.321 + } 121.322 + 121.323 if (UseCompressedOops) { 121.324 // Remove Reference object from list. 121.325 - oopDesc::encode_store_heap_oop_not_null((narrowOop*)_prev_next, _next); 121.326 + oopDesc::encode_store_heap_oop((narrowOop*)_prev_next, new_next); 121.327 } else { 121.328 // Remove Reference object from list. 121.329 - oopDesc::store_heap_oop((oop*)_prev_next, _next); 121.330 + oopDesc::store_heap_oop((oop*)_prev_next, new_next); 121.331 } 121.332 NOT_PRODUCT(_removed++); 121.333 _refs_list.dec_length(1); 121.334 } 121.335 121.336 inline void DiscoveredListIterator::move_to_next() { 121.337 - _ref = _next; 121.338 + if (_ref == _next) { 121.339 + // End of the list. 121.340 + _ref = NULL; 121.341 + } else { 121.342 + _ref = _next; 121.343 + } 121.344 assert(_ref != _first_seen, "cyclic ref_list found"); 121.345 NOT_PRODUCT(_processed++); 121.346 } 121.347 @@ -613,7 +648,7 @@ 121.348 NOT_PRODUCT( 121.349 if (PrintGCDetails && TraceReferenceGC) { 121.350 gclog_or_tty->print_cr(" Dropped %d dead Refs out of %d " 121.351 - "discovered Refs by policy list " INTPTR_FORMAT, 121.352 + "discovered Refs by policy, from list " INTPTR_FORMAT, 121.353 iter.removed(), iter.processed(), (address)refs_list.head()); 121.354 } 121.355 ) 121.356 @@ -725,22 +760,28 @@ 121.357 assert(iter.obj()->is_oop(UseConcMarkSweepGC), "Adding a bad reference"); 121.358 iter.next(); 121.359 } 121.360 - // Remember to keep sentinel pointer around 121.361 + // Remember to update the next pointer of the last ref. 121.362 iter.update_discovered(); 121.363 // Close the reachable set 121.364 complete_gc->do_void(); 121.365 } 121.366 121.367 void 121.368 +ReferenceProcessor::clear_discovered_references(DiscoveredList& refs_list) { 121.369 + oop obj = NULL; 121.370 + oop next = refs_list.head(); 121.371 + while (next != obj) { 121.372 + obj = next; 121.373 + next = java_lang_ref_Reference::discovered(obj); 121.374 + java_lang_ref_Reference::set_discovered_raw(obj, NULL); 121.375 + } 121.376 + refs_list.set_head(NULL); 121.377 + refs_list.set_length(0); 121.378 +} 121.379 + 121.380 +void 121.381 ReferenceProcessor::abandon_partial_discovered_list(DiscoveredList& refs_list) { 121.382 - oop obj = refs_list.head(); 121.383 - while (obj != sentinel_ref()) { 121.384 - oop discovered = java_lang_ref_Reference::discovered(obj); 121.385 - java_lang_ref_Reference::set_discovered_raw(obj, NULL); 121.386 - obj = discovered; 121.387 - } 121.388 - refs_list.set_head(sentinel_ref()); 121.389 - refs_list.set_length(0); 121.390 + clear_discovered_references(refs_list); 121.391 } 121.392 121.393 void ReferenceProcessor::abandon_partial_discovery() { 121.394 @@ -859,6 +900,9 @@ 121.395 refs_to_move = MIN2(ref_lists[from_idx].length() - avg_refs, 121.396 avg_refs - ref_lists[to_idx].length()); 121.397 } 121.398 + 121.399 + assert(refs_to_move > 0, "otherwise the code below will fail"); 121.400 + 121.401 oop move_head = ref_lists[from_idx].head(); 121.402 oop move_tail = move_head; 121.403 oop new_head = move_head; 121.404 @@ -867,10 +911,24 @@ 121.405 move_tail = new_head; 121.406 new_head = java_lang_ref_Reference::discovered(new_head); 121.407 } 121.408 - java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head()); 121.409 + 121.410 + // Add the chain to the to list. 121.411 + if (ref_lists[to_idx].head() == NULL) { 121.412 + // to list is empty. Make a loop at the end. 121.413 + java_lang_ref_Reference::set_discovered(move_tail, move_tail); 121.414 + } else { 121.415 + java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head()); 121.416 + } 121.417 ref_lists[to_idx].set_head(move_head); 121.418 ref_lists[to_idx].inc_length(refs_to_move); 121.419 - ref_lists[from_idx].set_head(new_head); 121.420 + 121.421 + // Remove the chain from the from list. 121.422 + if (move_tail == new_head) { 121.423 + // We found the end of the from list. 121.424 + ref_lists[from_idx].set_head(NULL); 121.425 + } else { 121.426 + ref_lists[from_idx].set_head(new_head); 121.427 + } 121.428 ref_lists[from_idx].dec_length(refs_to_move); 121.429 if (ref_lists[from_idx].length() == 0) { 121.430 break; 121.431 @@ -1082,42 +1140,40 @@ 121.432 // First we must make sure this object is only enqueued once. CAS in a non null 121.433 // discovered_addr. 121.434 oop current_head = refs_list.head(); 121.435 + // The last ref must have its discovered field pointing to itself. 121.436 + oop next_discovered = (current_head != NULL) ? current_head : obj; 121.437 121.438 // Note: In the case of G1, this specific pre-barrier is strictly 121.439 // not necessary because the only case we are interested in 121.440 // here is when *discovered_addr is NULL (see the CAS further below), 121.441 // so this will expand to nothing. As a result, we have manually 121.442 // elided this out for G1, but left in the test for some future 121.443 - // collector that might have need for a pre-barrier here. 121.444 - if (_discovered_list_needs_barrier && !UseG1GC) { 121.445 - if (UseCompressedOops) { 121.446 - _bs->write_ref_field_pre((narrowOop*)discovered_addr, current_head); 121.447 - } else { 121.448 - _bs->write_ref_field_pre((oop*)discovered_addr, current_head); 121.449 - } 121.450 - guarantee(false, "Need to check non-G1 collector"); 121.451 - } 121.452 - oop retest = oopDesc::atomic_compare_exchange_oop(current_head, discovered_addr, 121.453 + // collector that might have need for a pre-barrier here, e.g.:- 121.454 + // _bs->write_ref_field_pre((oop* or narrowOop*)discovered_addr, next_discovered); 121.455 + assert(!_discovered_list_needs_barrier || UseG1GC, 121.456 + "Need to check non-G1 collector: " 121.457 + "may need a pre-write-barrier for CAS from NULL below"); 121.458 + oop retest = oopDesc::atomic_compare_exchange_oop(next_discovered, discovered_addr, 121.459 NULL); 121.460 if (retest == NULL) { 121.461 // This thread just won the right to enqueue the object. 121.462 - // We have separate lists for enqueueing so no synchronization 121.463 + // We have separate lists for enqueueing, so no synchronization 121.464 // is necessary. 121.465 refs_list.set_head(obj); 121.466 refs_list.inc_length(1); 121.467 if (_discovered_list_needs_barrier) { 121.468 - _bs->write_ref_field((void*)discovered_addr, current_head); 121.469 + _bs->write_ref_field((void*)discovered_addr, next_discovered); 121.470 } 121.471 121.472 if (TraceReferenceGC) { 121.473 - gclog_or_tty->print_cr("Enqueued reference (mt) (" INTPTR_FORMAT ": %s)", 121.474 + gclog_or_tty->print_cr("Discovered reference (mt) (" INTPTR_FORMAT ": %s)", 121.475 obj, obj->blueprint()->internal_name()); 121.476 } 121.477 } else { 121.478 // If retest was non NULL, another thread beat us to it: 121.479 // The reference has already been discovered... 121.480 if (TraceReferenceGC) { 121.481 - gclog_or_tty->print_cr("Already enqueued reference (" INTPTR_FORMAT ": %s)", 121.482 + gclog_or_tty->print_cr("Already discovered reference (" INTPTR_FORMAT ": %s)", 121.483 obj, obj->blueprint()->internal_name()); 121.484 } 121.485 } 121.486 @@ -1142,7 +1198,7 @@ 121.487 // (or part of the heap being collected, indicated by our "span" 121.488 // we don't treat it specially (i.e. we scan it as we would 121.489 // a normal oop, treating its references as strong references). 121.490 -// This means that references can't be enqueued unless their 121.491 +// This means that references can't be discovered unless their 121.492 // referent is also in the same span. This is the simplest, 121.493 // most "local" and most conservative approach, albeit one 121.494 // that may cause weak references to be enqueued least promptly. 121.495 @@ -1164,14 +1220,13 @@ 121.496 // and complexity in processing these references. 121.497 // We call this choice the "RefeferentBasedDiscovery" policy. 121.498 bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { 121.499 - // We enqueue references only if we are discovering refs 121.500 - // (rather than processing discovered refs). 121.501 + // Make sure we are discovering refs (rather than processing discovered refs). 121.502 if (!_discovering_refs || !RegisterReferences) { 121.503 return false; 121.504 } 121.505 - // We only enqueue active references. 121.506 + // We only discover active references. 121.507 oop next = java_lang_ref_Reference::next(obj); 121.508 - if (next != NULL) { 121.509 + if (next != NULL) { // Ref is no longer active 121.510 return false; 121.511 } 121.512 121.513 @@ -1184,8 +1239,8 @@ 121.514 return false; 121.515 } 121.516 121.517 - // We only enqueue references whose referents are not (yet) strongly 121.518 - // reachable. 121.519 + // We only discover references whose referents are not (yet) 121.520 + // known to be strongly reachable. 121.521 if (is_alive_non_header() != NULL) { 121.522 verify_referent(obj); 121.523 if (is_alive_non_header()->do_object_b(java_lang_ref_Reference::referent(obj))) { 121.524 @@ -1211,7 +1266,7 @@ 121.525 if (discovered != NULL) { 121.526 // The reference has already been discovered... 121.527 if (TraceReferenceGC) { 121.528 - gclog_or_tty->print_cr("Already enqueued reference (" INTPTR_FORMAT ": %s)", 121.529 + gclog_or_tty->print_cr("Already discovered reference (" INTPTR_FORMAT ": %s)", 121.530 obj, obj->blueprint()->internal_name()); 121.531 } 121.532 if (RefDiscoveryPolicy == ReferentBasedDiscovery) { 121.533 @@ -1233,9 +1288,9 @@ 121.534 121.535 if (RefDiscoveryPolicy == ReferentBasedDiscovery) { 121.536 verify_referent(obj); 121.537 - // enqueue if and only if either: 121.538 - // reference is in our span or 121.539 - // we are an atomic collector and referent is in our span 121.540 + // Discover if and only if EITHER: 121.541 + // .. reference is in our span, OR 121.542 + // .. we are an atomic collector and referent is in our span 121.543 if (_span.contains(obj_addr) || 121.544 (discovery_is_atomic() && 121.545 _span.contains(java_lang_ref_Reference::referent(obj)))) { 121.546 @@ -1262,30 +1317,28 @@ 121.547 // here: the field will be visited later when processing the discovered 121.548 // references. 121.549 oop current_head = list->head(); 121.550 + // The last ref must have its discovered field pointing to itself. 121.551 + oop next_discovered = (current_head != NULL) ? current_head : obj; 121.552 + 121.553 // As in the case further above, since we are over-writing a NULL 121.554 // pre-value, we can safely elide the pre-barrier here for the case of G1. 121.555 + // e.g.:- _bs->write_ref_field_pre((oop* or narrowOop*)discovered_addr, next_discovered); 121.556 assert(discovered == NULL, "control point invariant"); 121.557 - if (_discovered_list_needs_barrier && !UseG1GC) { // safe to elide for G1 121.558 - if (UseCompressedOops) { 121.559 - _bs->write_ref_field_pre((narrowOop*)discovered_addr, current_head); 121.560 - } else { 121.561 - _bs->write_ref_field_pre((oop*)discovered_addr, current_head); 121.562 - } 121.563 - guarantee(false, "Need to check non-G1 collector"); 121.564 - } 121.565 - oop_store_raw(discovered_addr, current_head); 121.566 + assert(!_discovered_list_needs_barrier || UseG1GC, 121.567 + "For non-G1 collector, may need a pre-write-barrier for CAS from NULL below"); 121.568 + oop_store_raw(discovered_addr, next_discovered); 121.569 if (_discovered_list_needs_barrier) { 121.570 - _bs->write_ref_field((void*)discovered_addr, current_head); 121.571 + _bs->write_ref_field((void*)discovered_addr, next_discovered); 121.572 } 121.573 list->set_head(obj); 121.574 list->inc_length(1); 121.575 121.576 if (TraceReferenceGC) { 121.577 - gclog_or_tty->print_cr("Enqueued reference (" INTPTR_FORMAT ": %s)", 121.578 + gclog_or_tty->print_cr("Discovered reference (" INTPTR_FORMAT ": %s)", 121.579 obj, obj->blueprint()->internal_name()); 121.580 } 121.581 } 121.582 - assert(obj->is_oop(), "Enqueued a bad reference"); 121.583 + assert(obj->is_oop(), "Discovered a bad reference"); 121.584 verify_referent(obj); 121.585 return true; 121.586 } 121.587 @@ -1437,22 +1490,12 @@ 121.588 } 121.589 #endif 121.590 121.591 -void ReferenceProcessor::verify() { 121.592 - guarantee(sentinel_ref() != NULL && sentinel_ref()->is_oop(), "Lost _sentinelRef"); 121.593 -} 121.594 - 121.595 #ifndef PRODUCT 121.596 void ReferenceProcessor::clear_discovered_references() { 121.597 guarantee(!_discovering_refs, "Discovering refs?"); 121.598 for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { 121.599 - oop obj = _discoveredSoftRefs[i].head(); 121.600 - while (obj != sentinel_ref()) { 121.601 - oop next = java_lang_ref_Reference::discovered(obj); 121.602 - java_lang_ref_Reference::set_discovered(obj, (oop) NULL); 121.603 - obj = next; 121.604 - } 121.605 - _discoveredSoftRefs[i].set_head(sentinel_ref()); 121.606 - _discoveredSoftRefs[i].set_length(0); 121.607 + clear_discovered_references(_discoveredSoftRefs[i]); 121.608 } 121.609 } 121.610 + 121.611 #endif // PRODUCT
122.1 --- a/src/share/vm/memory/referenceProcessor.hpp Thu Sep 08 16:59:27 2011 -0700 122.2 +++ b/src/share/vm/memory/referenceProcessor.hpp Fri Sep 09 16:17:16 2011 -0700 122.3 @@ -52,8 +52,8 @@ 122.4 122.5 class ReferenceProcessor : public CHeapObj { 122.6 protected: 122.7 - // End of list marker 122.8 - static oop _sentinelRef; 122.9 + // Compatibility with pre-4965777 JDK's 122.10 + static bool _pending_list_uses_discovered_field; 122.11 MemRegion _span; // (right-open) interval of heap 122.12 // subject to wkref discovery 122.13 bool _discovering_refs; // true when discovery enabled 122.14 @@ -106,8 +106,6 @@ 122.15 int max_num_q() { return _max_num_q; } 122.16 void set_active_mt_degree(int v) { _num_q = v; } 122.17 DiscoveredList* discovered_soft_refs() { return _discoveredSoftRefs; } 122.18 - static oop sentinel_ref() { return _sentinelRef; } 122.19 - static oop* adr_sentinel_ref() { return &_sentinelRef; } 122.20 ReferencePolicy* setup_policy(bool always_clear) { 122.21 _current_soft_ref_policy = always_clear ? 122.22 _always_clear_soft_ref_policy : _default_soft_ref_policy; 122.23 @@ -115,7 +113,6 @@ 122.24 return _current_soft_ref_policy; 122.25 } 122.26 122.27 - public: 122.28 // Process references with a certain reachability level. 122.29 void process_discovered_reflist(DiscoveredList refs_lists[], 122.30 ReferencePolicy* policy, 122.31 @@ -230,6 +227,7 @@ 122.32 HeapWord* discovered_addr); 122.33 void verify_ok_to_handle_reflists() PRODUCT_RETURN; 122.34 122.35 + void clear_discovered_references(DiscoveredList& refs_list); 122.36 void abandon_partial_discovered_list(DiscoveredList& refs_list); 122.37 122.38 // Calculate the number of jni handles. 122.39 @@ -300,6 +298,13 @@ 122.40 bool discovery_is_atomic() const { return _discovery_is_atomic; } 122.41 void set_atomic_discovery(bool atomic) { _discovery_is_atomic = atomic; } 122.42 122.43 + // whether the JDK in which we are embedded is a pre-4965777 JDK, 122.44 + // and thus whether or not it uses the discovered field to chain 122.45 + // the entries in the pending list. 122.46 + static bool pending_list_uses_discovered_field() { 122.47 + return _pending_list_uses_discovered_field; 122.48 + } 122.49 + 122.50 // whether discovery is done by multiple threads same-old-timeously 122.51 bool discovery_is_mt() const { return _discovery_is_mt; } 122.52 void set_mt_discovery(bool mt) { _discovery_is_mt = mt; } 122.53 @@ -314,7 +319,6 @@ 122.54 122.55 // iterate over oops 122.56 void weak_oops_do(OopClosure* f); // weak roots 122.57 - static void oops_do(OopClosure* f); // strong root(s) 122.58 122.59 // Balance each of the discovered lists. 122.60 void balance_all_queues(); 122.61 @@ -340,7 +344,6 @@ 122.62 // debugging 122.63 void verify_no_references_recorded() PRODUCT_RETURN; 122.64 void verify_referent(oop obj) PRODUCT_RETURN; 122.65 - static void verify(); 122.66 122.67 // clear the discovered lists (unlinking each entry). 122.68 void clear_discovered_references() PRODUCT_RETURN; 122.69 @@ -524,12 +527,10 @@ 122.70 EnqueueTask(ReferenceProcessor& ref_processor, 122.71 DiscoveredList refs_lists[], 122.72 HeapWord* pending_list_addr, 122.73 - oop sentinel_ref, 122.74 int n_queues) 122.75 : _ref_processor(ref_processor), 122.76 _refs_lists(refs_lists), 122.77 _pending_list_addr(pending_list_addr), 122.78 - _sentinel_ref(sentinel_ref), 122.79 _n_queues(n_queues) 122.80 { } 122.81 122.82 @@ -540,7 +541,6 @@ 122.83 ReferenceProcessor& _ref_processor; 122.84 DiscoveredList* _refs_lists; 122.85 HeapWord* _pending_list_addr; 122.86 - oop _sentinel_ref; 122.87 int _n_queues; 122.88 }; 122.89
123.1 --- a/src/share/vm/memory/sharedHeap.cpp Thu Sep 08 16:59:27 2011 -0700 123.2 +++ b/src/share/vm/memory/sharedHeap.cpp Fri Sep 09 16:17:16 2011 -0700 123.3 @@ -146,7 +146,6 @@ 123.4 assert(_strong_roots_parity != 0, "must have called prologue code"); 123.5 if (!_process_strong_tasks->is_task_claimed(SH_PS_Universe_oops_do)) { 123.6 Universe::oops_do(roots); 123.7 - ReferenceProcessor::oops_do(roots); 123.8 // Consider perm-gen discovered lists to be strong. 123.9 perm_gen()->ref_processor()->weak_oops_do(roots); 123.10 }
124.1 --- a/src/share/vm/memory/universe.cpp Thu Sep 08 16:59:27 2011 -0700 124.2 +++ b/src/share/vm/memory/universe.cpp Fri Sep 09 16:17:16 2011 -0700 124.3 @@ -1203,12 +1203,12 @@ 124.4 // Compute the dependent nmethods that have a reference to a 124.5 // CallSite object. We use instanceKlass::mark_dependent_nmethod 124.6 // directly instead of CodeCache::mark_for_deoptimization because we 124.7 - // want dependents on the class CallSite only not all classes in the 124.8 - // ContextStream. 124.9 + // want dependents on the call site class only not all classes in 124.10 + // the ContextStream. 124.11 int marked = 0; 124.12 { 124.13 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 124.14 - instanceKlass* call_site_klass = instanceKlass::cast(SystemDictionary::CallSite_klass()); 124.15 + instanceKlass* call_site_klass = instanceKlass::cast(call_site->klass()); 124.16 marked = call_site_klass->mark_dependent_nmethods(changes); 124.17 } 124.18 if (marked > 0) {
125.1 --- a/src/share/vm/oops/constMethodKlass.cpp Thu Sep 08 16:59:27 2011 -0700 125.2 +++ b/src/share/vm/oops/constMethodKlass.cpp Fri Sep 09 16:17:16 2011 -0700 125.3 @@ -172,11 +172,6 @@ 125.4 int constMethodKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { 125.5 assert(obj->is_constMethod(), "should be constMethod"); 125.6 constMethodOop cm_oop = constMethodOop(obj); 125.7 -#if 0 125.8 - PSParallelCompact::adjust_pointer(cm_oop->adr_method()); 125.9 - PSParallelCompact::adjust_pointer(cm_oop->adr_exception_table()); 125.10 - PSParallelCompact::adjust_pointer(cm_oop->adr_stackmap_data()); 125.11 -#endif 125.12 oop* const beg_oop = cm_oop->oop_block_beg(); 125.13 oop* const end_oop = cm_oop->oop_block_end(); 125.14 for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) {
126.1 --- a/src/share/vm/oops/cpCacheKlass.cpp Thu Sep 08 16:59:27 2011 -0700 126.2 +++ b/src/share/vm/oops/cpCacheKlass.cpp Fri Sep 09 16:17:16 2011 -0700 126.3 @@ -63,8 +63,10 @@ 126.4 // CollectedHeap::permanent_obj_allocate(klass, size, CHECK_NULL); 126.5 126.6 oop obj = CollectedHeap::permanent_obj_allocate_no_klass_install(klass, size, CHECK_NULL); 126.7 - NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value((HeapWord*) obj, 126.8 - size)); 126.9 +#ifndef PRODUCT 126.10 + const size_t hs = oopDesc::header_size(); 126.11 + Universe::heap()->check_for_bad_heap_word_value(((HeapWord*) obj)+hs, size-hs); 126.12 +#endif 126.13 constantPoolCacheOop cache = (constantPoolCacheOop) obj; 126.14 assert(!UseConcMarkSweepGC || obj->klass_or_null() == NULL, 126.15 "klass should be NULL here when using CMS");
127.1 --- a/src/share/vm/oops/instanceRefKlass.cpp Thu Sep 08 16:59:27 2011 -0700 127.2 +++ b/src/share/vm/oops/instanceRefKlass.cpp Fri Sep 09 16:17:16 2011 -0700 127.3 @@ -56,9 +56,8 @@ 127.4 if (!oopDesc::is_null(heap_oop)) { 127.5 oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); 127.6 if (!referent->is_gc_marked() && 127.7 - MarkSweep::ref_processor()-> 127.8 - discover_reference(obj, ref->reference_type())) { 127.9 - // reference already enqueued, referent will be traversed later 127.10 + MarkSweep::ref_processor()->discover_reference(obj, ref->reference_type())) { 127.11 + // reference was discovered, referent will be traversed later 127.12 ref->instanceKlass::oop_follow_contents(obj); 127.13 debug_only( 127.14 if(TraceReferenceGC && PrintGCDetails) { 127.15 @@ -76,8 +75,34 @@ 127.16 MarkSweep::mark_and_push(referent_addr); 127.17 } 127.18 } 127.19 - // treat next as normal oop. next is a link in the pending list. 127.20 T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); 127.21 + if (ReferenceProcessor::pending_list_uses_discovered_field()) { 127.22 + // Treat discovered as normal oop, if ref is not "active", 127.23 + // i.e. if next is non-NULL. 127.24 + T next_oop = oopDesc::load_heap_oop(next_addr); 127.25 + if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active" 127.26 + T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); 127.27 + debug_only( 127.28 + if(TraceReferenceGC && PrintGCDetails) { 127.29 + gclog_or_tty->print_cr(" Process discovered as normal " 127.30 + INTPTR_FORMAT, discovered_addr); 127.31 + } 127.32 + ) 127.33 + MarkSweep::mark_and_push(discovered_addr); 127.34 + } 127.35 + } else { 127.36 +#ifdef ASSERT 127.37 + // In the case of older JDKs which do not use the discovered 127.38 + // field for the pending list, an inactive ref (next != NULL) 127.39 + // must always have a NULL discovered field. 127.40 + oop next = oopDesc::load_decode_heap_oop(next_addr); 127.41 + oop discovered = java_lang_ref_Reference::discovered(obj); 127.42 + assert(oopDesc::is_null(next) || oopDesc::is_null(discovered), 127.43 + err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field", 127.44 + obj)); 127.45 +#endif 127.46 + } 127.47 + // treat next as normal oop. next is a link in the reference queue. 127.48 debug_only( 127.49 if(TraceReferenceGC && PrintGCDetails) { 127.50 gclog_or_tty->print_cr(" Process next as normal " INTPTR_FORMAT, next_addr); 127.51 @@ -130,13 +155,33 @@ 127.52 PSParallelCompact::mark_and_push(cm, referent_addr); 127.53 } 127.54 } 127.55 - // treat next as normal oop. next is a link in the pending list. 127.56 T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); 127.57 - debug_only( 127.58 - if(TraceReferenceGC && PrintGCDetails) { 127.59 - gclog_or_tty->print_cr(" Process next as normal " INTPTR_FORMAT, next_addr); 127.60 + if (ReferenceProcessor::pending_list_uses_discovered_field()) { 127.61 + // Treat discovered as normal oop, if ref is not "active", 127.62 + // i.e. if next is non-NULL. 127.63 + T next_oop = oopDesc::load_heap_oop(next_addr); 127.64 + if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active" 127.65 + T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); 127.66 + debug_only( 127.67 + if(TraceReferenceGC && PrintGCDetails) { 127.68 + gclog_or_tty->print_cr(" Process discovered as normal " 127.69 + INTPTR_FORMAT, discovered_addr); 127.70 + } 127.71 + ) 127.72 + PSParallelCompact::mark_and_push(cm, discovered_addr); 127.73 } 127.74 - ) 127.75 + } else { 127.76 +#ifdef ASSERT 127.77 + // In the case of older JDKs which do not use the discovered 127.78 + // field for the pending list, an inactive ref (next != NULL) 127.79 + // must always have a NULL discovered field. 127.80 + T next = oopDesc::load_heap_oop(next_addr); 127.81 + oop discovered = java_lang_ref_Reference::discovered(obj); 127.82 + assert(oopDesc::is_null(next) || oopDesc::is_null(discovered), 127.83 + err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field", 127.84 + obj)); 127.85 +#endif 127.86 + } 127.87 PSParallelCompact::mark_and_push(cm, next_addr); 127.88 ref->instanceKlass::oop_follow_contents(cm, obj); 127.89 } 127.90 @@ -197,27 +242,53 @@ 127.91 } 127.92 127.93 #define InstanceRefKlass_SPECIALIZED_OOP_ITERATE(T, nv_suffix, contains) \ 127.94 + T* disc_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); \ 127.95 if (closure->apply_to_weak_ref_discovered_field()) { \ 127.96 - T* disc_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); \ 127.97 closure->do_oop##nv_suffix(disc_addr); \ 127.98 } \ 127.99 \ 127.100 T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); \ 127.101 T heap_oop = oopDesc::load_heap_oop(referent_addr); \ 127.102 - if (!oopDesc::is_null(heap_oop) && contains(referent_addr)) { \ 127.103 - ReferenceProcessor* rp = closure->_ref_processor; \ 127.104 + ReferenceProcessor* rp = closure->_ref_processor; \ 127.105 + if (!oopDesc::is_null(heap_oop)) { \ 127.106 oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); \ 127.107 if (!referent->is_gc_marked() && (rp != NULL) && \ 127.108 rp->discover_reference(obj, reference_type())) { \ 127.109 return size; \ 127.110 - } else { \ 127.111 + } else if (contains(referent_addr)) { \ 127.112 /* treat referent as normal oop */ \ 127.113 SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\ 127.114 closure->do_oop##nv_suffix(referent_addr); \ 127.115 } \ 127.116 } \ 127.117 + T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); \ 127.118 + if (ReferenceProcessor::pending_list_uses_discovered_field()) { \ 127.119 + T next_oop = oopDesc::load_heap_oop(next_addr); \ 127.120 + /* Treat discovered as normal oop, if ref is not "active" (next non-NULL) */\ 127.121 + if (!oopDesc::is_null(next_oop) && contains(disc_addr)) { \ 127.122 + /* i.e. ref is not "active" */ \ 127.123 + debug_only( \ 127.124 + if(TraceReferenceGC && PrintGCDetails) { \ 127.125 + gclog_or_tty->print_cr(" Process discovered as normal " \ 127.126 + INTPTR_FORMAT, disc_addr); \ 127.127 + } \ 127.128 + ) \ 127.129 + SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\ 127.130 + closure->do_oop##nv_suffix(disc_addr); \ 127.131 + } \ 127.132 + } else { \ 127.133 + /* In the case of older JDKs which do not use the discovered field for */ \ 127.134 + /* the pending list, an inactive ref (next != NULL) must always have a */ \ 127.135 + /* NULL discovered field. */ \ 127.136 + debug_only( \ 127.137 + T next_oop = oopDesc::load_heap_oop(next_addr); \ 127.138 + T disc_oop = oopDesc::load_heap_oop(disc_addr); \ 127.139 + assert(oopDesc::is_null(next_oop) || oopDesc::is_null(disc_oop), \ 127.140 + err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL" \ 127.141 + "discovered field", obj)); \ 127.142 + ) \ 127.143 + } \ 127.144 /* treat next as normal oop */ \ 127.145 - T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); \ 127.146 if (contains(next_addr)) { \ 127.147 SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk); \ 127.148 closure->do_oop##nv_suffix(next_addr); \ 127.149 @@ -306,8 +377,37 @@ 127.150 pm->claim_or_forward_depth(referent_addr); 127.151 } 127.152 } 127.153 - // treat next as normal oop 127.154 + // Treat discovered as normal oop, if ref is not "active", 127.155 + // i.e. if next is non-NULL. 127.156 T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); 127.157 + if (ReferenceProcessor::pending_list_uses_discovered_field()) { 127.158 + T next_oop = oopDesc::load_heap_oop(next_addr); 127.159 + if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active" 127.160 + T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); 127.161 + debug_only( 127.162 + if(TraceReferenceGC && PrintGCDetails) { 127.163 + gclog_or_tty->print_cr(" Process discovered as normal " 127.164 + INTPTR_FORMAT, discovered_addr); 127.165 + } 127.166 + ) 127.167 + if (PSScavenge::should_scavenge(discovered_addr)) { 127.168 + pm->claim_or_forward_depth(discovered_addr); 127.169 + } 127.170 + } 127.171 + } else { 127.172 +#ifdef ASSERT 127.173 + // In the case of older JDKs which do not use the discovered 127.174 + // field for the pending list, an inactive ref (next != NULL) 127.175 + // must always have a NULL discovered field. 127.176 + oop next = oopDesc::load_decode_heap_oop(next_addr); 127.177 + oop discovered = java_lang_ref_Reference::discovered(obj); 127.178 + assert(oopDesc::is_null(next) || oopDesc::is_null(discovered), 127.179 + err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field", 127.180 + obj)); 127.181 +#endif 127.182 + } 127.183 + 127.184 + // Treat next as normal oop; next is a link in the reference queue. 127.185 if (PSScavenge::should_scavenge(next_addr)) { 127.186 pm->claim_or_forward_depth(next_addr); 127.187 }
128.1 --- a/src/share/vm/oops/methodDataOop.hpp Thu Sep 08 16:59:27 2011 -0700 128.2 +++ b/src/share/vm/oops/methodDataOop.hpp Fri Sep 09 16:17:16 2011 -0700 128.3 @@ -600,6 +600,11 @@ 128.4 uint taken() { 128.5 return uint_at(taken_off_set); 128.6 } 128.7 + 128.8 + void set_taken(uint cnt) { 128.9 + set_uint_at(taken_off_set, cnt); 128.10 + } 128.11 + 128.12 // Saturating counter 128.13 uint inc_taken() { 128.14 uint cnt = taken() + 1; 128.15 @@ -926,6 +931,10 @@ 128.16 return uint_at(not_taken_off_set); 128.17 } 128.18 128.19 + void set_not_taken(uint cnt) { 128.20 + set_uint_at(not_taken_off_set, cnt); 128.21 + } 128.22 + 128.23 uint inc_not_taken() { 128.24 uint cnt = not_taken() + 1; 128.25 // Did we wrap? Will compiler screw us??
129.1 --- a/src/share/vm/oops/methodOop.cpp Thu Sep 08 16:59:27 2011 -0700 129.2 +++ b/src/share/vm/oops/methodOop.cpp Fri Sep 09 16:17:16 2011 -0700 129.3 @@ -914,6 +914,7 @@ 129.4 Symbol* name, 129.5 Symbol* signature, 129.6 Handle method_type, TRAPS) { 129.7 + ResourceMark rm; 129.8 methodHandle empty; 129.9 129.10 assert(holder() == SystemDictionary::MethodHandle_klass(),
130.1 --- a/src/share/vm/opto/bytecodeInfo.cpp Thu Sep 08 16:59:27 2011 -0700 130.2 +++ b/src/share/vm/opto/bytecodeInfo.cpp Fri Sep 09 16:17:16 2011 -0700 130.3 @@ -45,7 +45,7 @@ 130.4 _method(callee), 130.5 _site_invoke_ratio(site_invoke_ratio), 130.6 _max_inline_level(max_inline_level), 130.7 - _count_inline_bcs(method()->code_size()) 130.8 + _count_inline_bcs(method()->code_size_for_inlining()) 130.9 { 130.10 NOT_PRODUCT(_count_inlines = 0;) 130.11 if (_caller_jvms != NULL) { 130.12 @@ -107,7 +107,7 @@ 130.13 130.14 // positive filter: should send be inlined? returns NULL (--> yes) 130.15 // or rejection msg 130.16 - int size = callee_method->code_size(); 130.17 + int size = callee_method->code_size_for_inlining(); 130.18 130.19 // Check for too many throws (and not too huge) 130.20 if(callee_method->interpreter_throwout_count() > InlineThrowCount && 130.21 @@ -141,7 +141,21 @@ 130.22 assert(mha_profile, "must exist"); 130.23 CounterData* cd = mha_profile->as_CounterData(); 130.24 invoke_count = cd->count(); 130.25 - call_site_count = invoke_count; // use the same value 130.26 + if (invoke_count == 0) { 130.27 + return "method handle not reached"; 130.28 + } 130.29 + 130.30 + if (_caller_jvms != NULL && _caller_jvms->method() != NULL && 130.31 + _caller_jvms->method()->method_data() != NULL && 130.32 + !_caller_jvms->method()->method_data()->is_empty()) { 130.33 + ciMethodData* mdo = _caller_jvms->method()->method_data(); 130.34 + ciProfileData* mha_profile = mdo->bci_to_data(_caller_jvms->bci()); 130.35 + assert(mha_profile, "must exist"); 130.36 + CounterData* cd = mha_profile->as_CounterData(); 130.37 + call_site_count = cd->count(); 130.38 + } else { 130.39 + call_site_count = invoke_count; // use the same value 130.40 + } 130.41 } 130.42 130.43 assert(invoke_count != 0, "require invocation count greater than zero"); 130.44 @@ -244,7 +258,7 @@ 130.45 } 130.46 130.47 // use frequency-based objections only for non-trivial methods 130.48 - if (callee_method->code_size() <= MaxTrivialSize) return NULL; 130.49 + if (callee_method->code_size_for_inlining() <= MaxTrivialSize) return NULL; 130.50 130.51 // don't use counts with -Xcomp or CTW 130.52 if (UseInterpreter && !CompileTheWorld) { 130.53 @@ -305,7 +319,7 @@ 130.54 } 130.55 130.56 // suppress a few checks for accessors and trivial methods 130.57 - if (callee_method->code_size() > MaxTrivialSize) { 130.58 + if (callee_method->code_size_for_inlining() > MaxTrivialSize) { 130.59 130.60 // don't inline into giant methods 130.61 if (C->unique() > (uint)NodeCountInliningCutoff) { 130.62 @@ -349,7 +363,7 @@ 130.63 } 130.64 } 130.65 130.66 - int size = callee_method->code_size(); 130.67 + int size = callee_method->code_size_for_inlining(); 130.68 130.69 if (UseOldInlining && ClipInlining 130.70 && (int)count_inline_bcs() + size >= DesiredMethodLimit) { 130.71 @@ -394,6 +408,16 @@ 130.72 return true; 130.73 } 130.74 130.75 +//------------------------------check_can_parse-------------------------------- 130.76 +const char* InlineTree::check_can_parse(ciMethod* callee) { 130.77 + // Certain methods cannot be parsed at all: 130.78 + if ( callee->is_native()) return "native method"; 130.79 + if (!callee->can_be_compiled()) return "not compilable (disabled)"; 130.80 + if (!callee->has_balanced_monitors()) return "not compilable (unbalanced monitors)"; 130.81 + if ( callee->get_flow_analysis()->failing()) return "not compilable (flow analysis failed)"; 130.82 + return NULL; 130.83 +} 130.84 + 130.85 //------------------------------print_inlining--------------------------------- 130.86 // Really, the failure_msg can be a success message also. 130.87 void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const char* failure_msg) const { 130.88 @@ -423,14 +447,22 @@ 130.89 int caller_bci = jvms->bci(); 130.90 ciMethod *caller_method = jvms->method(); 130.91 130.92 - if( !pass_initial_checks(caller_method, caller_bci, callee_method)) { 130.93 - if( PrintInlining ) { 130.94 + // Do some initial checks. 130.95 + if (!pass_initial_checks(caller_method, caller_bci, callee_method)) { 130.96 + if (PrintInlining) { 130.97 failure_msg = "failed_initial_checks"; 130.98 - print_inlining( callee_method, caller_bci, failure_msg); 130.99 + print_inlining(callee_method, caller_bci, failure_msg); 130.100 } 130.101 return NULL; 130.102 } 130.103 130.104 + // Do some parse checks. 130.105 + failure_msg = check_can_parse(callee_method); 130.106 + if (failure_msg != NULL) { 130.107 + if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); 130.108 + return NULL; 130.109 + } 130.110 + 130.111 // Check if inlining policy says no. 130.112 WarmCallInfo wci = *(initial_wci); 130.113 failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci); 130.114 @@ -471,7 +503,7 @@ 130.115 if (failure_msg == NULL) failure_msg = "inline (hot)"; 130.116 130.117 // Inline! 130.118 - if( PrintInlining ) print_inlining( callee_method, caller_bci, failure_msg); 130.119 + if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); 130.120 if (UseOldInlining) 130.121 build_inline_tree_for_callee(callee_method, jvms, caller_bci); 130.122 if (InlineWarmCalls && !wci.is_hot()) 130.123 @@ -481,7 +513,7 @@ 130.124 130.125 // Do not inline 130.126 if (failure_msg == NULL) failure_msg = "too cold to inline"; 130.127 - if( PrintInlining ) print_inlining( callee_method, caller_bci, failure_msg); 130.128 + if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); 130.129 return NULL; 130.130 } 130.131
131.1 --- a/src/share/vm/opto/callGenerator.cpp Thu Sep 08 16:59:27 2011 -0700 131.2 +++ b/src/share/vm/opto/callGenerator.cpp Fri Sep 09 16:17:16 2011 -0700 131.3 @@ -61,12 +61,9 @@ 131.4 { 131.5 _is_osr = is_osr; 131.6 _expected_uses = expected_uses; 131.7 - assert(can_parse(method, is_osr), "parse must be possible"); 131.8 + assert(InlineTree::check_can_parse(method) == NULL, "parse must be possible"); 131.9 } 131.10 131.11 - // Can we build either an OSR or a regular parser for this method? 131.12 - static bool can_parse(ciMethod* method, int is_osr = false); 131.13 - 131.14 virtual bool is_parse() const { return true; } 131.15 virtual JVMState* generate(JVMState* jvms); 131.16 int is_osr() { return _is_osr; } 131.17 @@ -152,7 +149,6 @@ 131.18 call->set_optimized_virtual(true); 131.19 if (method()->is_method_handle_invoke()) { 131.20 call->set_method_handle_invoke(true); 131.21 - kit.C->set_has_method_handle_invokes(true); 131.22 } 131.23 } 131.24 kit.set_arguments_for_java_call(call); 131.25 @@ -210,7 +206,6 @@ 131.26 call->set_optimized_virtual(true); 131.27 // Take extra care (in the presence of argument motion) not to trash the SP: 131.28 call->set_method_handle_invoke(true); 131.29 - kit.C->set_has_method_handle_invokes(true); 131.30 131.31 // Pass the target MethodHandle as first argument and shift the 131.32 // other arguments. 131.33 @@ -303,20 +298,8 @@ 131.34 return kit.transfer_exceptions_into_jvms(); 131.35 } 131.36 131.37 -bool ParseGenerator::can_parse(ciMethod* m, int entry_bci) { 131.38 - // Certain methods cannot be parsed at all: 131.39 - if (!m->can_be_compiled()) return false; 131.40 - if (!m->has_balanced_monitors()) return false; 131.41 - if (m->get_flow_analysis()->failing()) return false; 131.42 - 131.43 - // (Methods may bail out for other reasons, after the parser is run. 131.44 - // We try to avoid this, but if forced, we must return (Node*)NULL. 131.45 - // The user of the CallGenerator must check for this condition.) 131.46 - return true; 131.47 -} 131.48 - 131.49 CallGenerator* CallGenerator::for_inline(ciMethod* m, float expected_uses) { 131.50 - if (!ParseGenerator::can_parse(m)) return NULL; 131.51 + if (InlineTree::check_can_parse(m) != NULL) return NULL; 131.52 return new ParseGenerator(m, expected_uses); 131.53 } 131.54 131.55 @@ -324,7 +307,7 @@ 131.56 // for the method execution already in progress, not just the JVMS 131.57 // of the caller. Thus, this CallGenerator cannot be mixed with others! 131.58 CallGenerator* CallGenerator::for_osr(ciMethod* m, int osr_bci) { 131.59 - if (!ParseGenerator::can_parse(m, true)) return NULL; 131.60 + if (InlineTree::check_can_parse(m) != NULL) return NULL; 131.61 float past_uses = m->interpreter_invocation_count(); 131.62 float expected_uses = past_uses; 131.63 return new ParseGenerator(m, expected_uses, true); 131.64 @@ -336,7 +319,7 @@ 131.65 } 131.66 131.67 CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) { 131.68 - assert(m->is_method_handle_invoke(), "for_dynamic_call mismatch"); 131.69 + assert(m->is_method_handle_invoke() || m->is_method_handle_adapter(), "for_dynamic_call mismatch"); 131.70 return new DynamicCallGenerator(m); 131.71 } 131.72 131.73 @@ -715,24 +698,36 @@ 131.74 // Get an adapter for the MethodHandle. 131.75 ciMethod* target_method = method_handle->get_method_handle_adapter(); 131.76 if (target_method != NULL) { 131.77 - CallGenerator* hit_cg = Compile::current()->call_generator(target_method, -1, false, jvms, true, 1); 131.78 - if (hit_cg != NULL && hit_cg->is_inline()) 131.79 - return hit_cg; 131.80 + CallGenerator* cg = Compile::current()->call_generator(target_method, -1, false, jvms, true, PROB_ALWAYS); 131.81 + if (cg != NULL && cg->is_inline()) 131.82 + return cg; 131.83 } 131.84 } else if (method_handle->Opcode() == Op_Phi && method_handle->req() == 3 && 131.85 method_handle->in(1)->Opcode() == Op_ConP && method_handle->in(2)->Opcode() == Op_ConP) { 131.86 + float prob = PROB_FAIR; 131.87 + Node* meth_region = method_handle->in(0); 131.88 + if (meth_region->is_Region() && 131.89 + meth_region->in(1)->is_Proj() && meth_region->in(2)->is_Proj() && 131.90 + meth_region->in(1)->in(0) == meth_region->in(2)->in(0) && 131.91 + meth_region->in(1)->in(0)->is_If()) { 131.92 + // If diamond, so grab the probability of the test to drive the inlining below 131.93 + prob = meth_region->in(1)->in(0)->as_If()->_prob; 131.94 + if (meth_region->in(1)->is_IfTrue()) { 131.95 + prob = 1 - prob; 131.96 + } 131.97 + } 131.98 + 131.99 // selectAlternative idiom merging two constant MethodHandles. 131.100 // Generate a guard so that each can be inlined. We might want to 131.101 // do more inputs at later point but this gets the most common 131.102 // case. 131.103 - const TypeOopPtr* oop_ptr = method_handle->in(1)->bottom_type()->is_oopptr(); 131.104 - ciObject* const_oop = oop_ptr->const_oop(); 131.105 - ciMethodHandle* mh = const_oop->as_method_handle(); 131.106 - 131.107 - CallGenerator* cg1 = for_method_handle_inline(method_handle->in(1), jvms, caller, callee, profile); 131.108 - CallGenerator* cg2 = for_method_handle_inline(method_handle->in(2), jvms, caller, callee, profile); 131.109 + CallGenerator* cg1 = for_method_handle_inline(method_handle->in(1), jvms, caller, callee, profile.rescale(1.0 - prob)); 131.110 + CallGenerator* cg2 = for_method_handle_inline(method_handle->in(2), jvms, caller, callee, profile.rescale(prob)); 131.111 if (cg1 != NULL && cg2 != NULL) { 131.112 - return new PredictedDynamicCallGenerator(mh, cg2, cg1, PROB_FAIR); 131.113 + const TypeOopPtr* oop_ptr = method_handle->in(1)->bottom_type()->is_oopptr(); 131.114 + ciObject* const_oop = oop_ptr->const_oop(); 131.115 + ciMethodHandle* mh = const_oop->as_method_handle(); 131.116 + return new PredictedDynamicCallGenerator(mh, cg2, cg1, prob); 131.117 } 131.118 } 131.119 return NULL; 131.120 @@ -741,7 +736,6 @@ 131.121 131.122 CallGenerator* CallGenerator::for_invokedynamic_inline(ciCallSite* call_site, JVMState* jvms, 131.123 ciMethod* caller, ciMethod* callee, ciCallProfile profile) { 131.124 - assert(call_site->is_constant_call_site() || call_site->is_mutable_call_site(), "must be"); 131.125 ciMethodHandle* method_handle = call_site->get_target(); 131.126 131.127 // Set the callee to have access to the class and signature in the 131.128 @@ -754,13 +748,13 @@ 131.129 ciMethod* target_method = method_handle->get_invokedynamic_adapter(); 131.130 if (target_method != NULL) { 131.131 Compile *C = Compile::current(); 131.132 - CallGenerator* hit_cg = C->call_generator(target_method, -1, false, jvms, true, PROB_ALWAYS); 131.133 - if (hit_cg != NULL && hit_cg->is_inline()) { 131.134 + CallGenerator* cg = C->call_generator(target_method, -1, false, jvms, true, PROB_ALWAYS); 131.135 + if (cg != NULL && cg->is_inline()) { 131.136 // Add a dependence for invalidation of the optimization. 131.137 - if (call_site->is_mutable_call_site()) { 131.138 - C->dependencies()->assert_call_site_target_value(C->env()->CallSite_klass(), call_site, method_handle); 131.139 + if (!call_site->is_constant_call_site()) { 131.140 + C->dependencies()->assert_call_site_target_value(call_site, method_handle); 131.141 } 131.142 - return hit_cg; 131.143 + return cg; 131.144 } 131.145 } 131.146 return NULL;
132.1 --- a/src/share/vm/opto/compile.cpp Thu Sep 08 16:59:27 2011 -0700 132.2 +++ b/src/share/vm/opto/compile.cpp Fri Sep 09 16:17:16 2011 -0700 132.3 @@ -817,7 +817,6 @@ 132.4 &_handler_table, &_inc_table, 132.5 compiler, 132.6 env()->comp_level(), 132.7 - true, /*has_debug_info*/ 132.8 has_unsafe_access() 132.9 ); 132.10 }
133.1 --- a/src/share/vm/opto/connode.hpp Thu Sep 08 16:59:27 2011 -0700 133.2 +++ b/src/share/vm/opto/connode.hpp Fri Sep 09 16:17:16 2011 -0700 133.3 @@ -496,14 +496,6 @@ 133.4 virtual bool depends_only_on_test() const { return false; } 133.5 }; 133.6 133.7 -//------------------------------MemMoveNode------------------------------------ 133.8 -// Memory to memory move. Inserted very late, after allocation. 133.9 -class MemMoveNode : public Node { 133.10 -public: 133.11 - MemMoveNode( Node *dst, Node *src ) : Node(0,dst,src) {} 133.12 - virtual int Opcode() const; 133.13 -}; 133.14 - 133.15 //------------------------------ThreadLocalNode-------------------------------- 133.16 // Ideal Node which returns the base of ThreadLocalStorage. 133.17 class ThreadLocalNode : public Node {
134.1 --- a/src/share/vm/opto/doCall.cpp Thu Sep 08 16:59:27 2011 -0700 134.2 +++ b/src/share/vm/opto/doCall.cpp Fri Sep 09 16:17:16 2011 -0700 134.3 @@ -136,15 +136,9 @@ 134.4 str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. 134.5 ciCallSite* call_site = str.get_call_site(); 134.6 134.7 - // Inline constant and mutable call sites. We don't inline 134.8 - // volatile call sites optimistically since they are specified 134.9 - // to change their value often and that would result in a lot of 134.10 - // deoptimizations and recompiles. 134.11 - if (call_site->is_constant_call_site() || call_site->is_mutable_call_site()) { 134.12 - CallGenerator* cg = CallGenerator::for_invokedynamic_inline(call_site, jvms, caller, call_method, profile); 134.13 - if (cg != NULL) { 134.14 - return cg; 134.15 - } 134.16 + CallGenerator* cg = CallGenerator::for_invokedynamic_inline(call_site, jvms, caller, call_method, profile); 134.17 + if (cg != NULL) { 134.18 + return cg; 134.19 } 134.20 // If something failed, generate a normal dynamic call. 134.21 return CallGenerator::for_dynamic_call(call_method);
135.1 --- a/src/share/vm/opto/idealGraphPrinter.cpp Thu Sep 08 16:59:27 2011 -0700 135.2 +++ b/src/share/vm/opto/idealGraphPrinter.cpp Fri Sep 09 16:17:16 2011 -0700 135.3 @@ -375,9 +375,9 @@ 135.4 return (intptr_t)(n); 135.5 } 135.6 135.7 -void IdealGraphPrinter::visit_node(Node *n, void *param) { 135.8 +void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { 135.9 135.10 - if(param) { 135.11 + if (edges) { 135.12 135.13 // Output edge 135.14 intptr_t dest_id = get_node_id(n); 135.15 @@ -599,16 +599,11 @@ 135.16 135.17 #ifdef ASSERT 135.18 if (node->debug_orig() != NULL) { 135.19 + temp_set->Clear(); 135.20 stringStream dorigStream; 135.21 Node* dorig = node->debug_orig(); 135.22 - if (dorig) { 135.23 + while (dorig && temp_set->test_set(dorig->_idx)) { 135.24 dorigStream.print("%d ", dorig->_idx); 135.25 - Node* first = dorig; 135.26 - dorig = first->debug_orig(); 135.27 - while (dorig && dorig != first) { 135.28 - dorigStream.print("%d ", dorig->_idx); 135.29 - dorig = dorig->debug_orig(); 135.30 - } 135.31 } 135.32 print_prop("debug_orig", dorigStream.as_string()); 135.33 } 135.34 @@ -629,7 +624,7 @@ 135.35 } 135.36 } 135.37 135.38 -void IdealGraphPrinter::walk_nodes(Node *start, void *param) { 135.39 +void IdealGraphPrinter::walk_nodes(Node *start, bool edges, VectorSet* temp_set) { 135.40 135.41 135.42 VectorSet visited(Thread::current()->resource_area()); 135.43 @@ -650,7 +645,7 @@ 135.44 while(nodeStack.length() > 0) { 135.45 135.46 Node *n = nodeStack.pop(); 135.47 - visit_node(n, param); 135.48 + visit_node(n, edges, temp_set); 135.49 135.50 if (_traverse_outs) { 135.51 for (DUIterator i = n->outs(); n->has_out(i); i++) { 135.52 @@ -689,12 +684,14 @@ 135.53 print_attr(GRAPH_NAME_PROPERTY, (const char *)name); 135.54 end_head(); 135.55 135.56 + VectorSet temp_set(Thread::current()->resource_area()); 135.57 + 135.58 head(NODES_ELEMENT); 135.59 - walk_nodes(node, NULL); 135.60 + walk_nodes(node, false, &temp_set); 135.61 tail(NODES_ELEMENT); 135.62 135.63 head(EDGES_ELEMENT); 135.64 - walk_nodes(node, (void *)1); 135.65 + walk_nodes(node, true, &temp_set); 135.66 tail(EDGES_ELEMENT); 135.67 if (C->cfg() != NULL) { 135.68 head(CONTROL_FLOW_ELEMENT);
136.1 --- a/src/share/vm/opto/idealGraphPrinter.hpp Thu Sep 08 16:59:27 2011 -0700 136.2 +++ b/src/share/vm/opto/idealGraphPrinter.hpp Fri Sep 09 16:17:16 2011 -0700 136.3 @@ -104,8 +104,8 @@ 136.4 void print_indent(); 136.5 void print_method(ciMethod *method, int bci, InlineTree *tree); 136.6 void print_inline_tree(InlineTree *tree); 136.7 - void visit_node(Node *n, void *param); 136.8 - void walk_nodes(Node *start, void *param); 136.9 + void visit_node(Node *n, bool edges, VectorSet* temp_set); 136.10 + void walk_nodes(Node *start, bool edges, VectorSet* temp_set); 136.11 void begin_elem(const char *s); 136.12 void end_elem(); 136.13 void begin_head(const char *s);
137.1 --- a/src/share/vm/opto/matcher.cpp Thu Sep 08 16:59:27 2011 -0700 137.2 +++ b/src/share/vm/opto/matcher.cpp Fri Sep 09 16:17:16 2011 -0700 137.3 @@ -501,6 +501,12 @@ 137.4 idealreg2spillmask[Op_RegP]->OR(*idealreg2regmask[Op_RegD]); 137.5 #else 137.6 idealreg2spillmask[Op_RegP]->OR(*idealreg2regmask[Op_RegF]); 137.7 +#ifdef ARM 137.8 + // ARM has support for moving 64bit values between a pair of 137.9 + // integer registers and a double register 137.10 + idealreg2spillmask[Op_RegL]->OR(*idealreg2regmask[Op_RegD]); 137.11 + idealreg2spillmask[Op_RegD]->OR(*idealreg2regmask[Op_RegL]); 137.12 +#endif 137.13 #endif 137.14 } 137.15 137.16 @@ -1106,6 +1112,9 @@ 137.17 mcall_java->_optimized_virtual = call_java->is_optimized_virtual(); 137.18 is_method_handle_invoke = call_java->is_method_handle_invoke(); 137.19 mcall_java->_method_handle_invoke = is_method_handle_invoke; 137.20 + if (is_method_handle_invoke) { 137.21 + C->set_has_method_handle_invokes(true); 137.22 + } 137.23 if( mcall_java->is_MachCallStaticJava() ) 137.24 mcall_java->as_MachCallStaticJava()->_name = 137.25 call_java->as_CallStaticJava()->_name;
138.1 --- a/src/share/vm/opto/memnode.cpp Thu Sep 08 16:59:27 2011 -0700 138.2 +++ b/src/share/vm/opto/memnode.cpp Fri Sep 09 16:17:16 2011 -0700 138.3 @@ -1493,6 +1493,7 @@ 138.4 if (tp == NULL || tp->empty()) return Type::TOP; 138.5 int off = tp->offset(); 138.6 assert(off != Type::OffsetTop, "case covered by TypePtr::empty"); 138.7 + Compile* C = phase->C; 138.8 138.9 // Try to guess loaded type from pointer type 138.10 if (tp->base() == Type::AryPtr) { 138.11 @@ -1536,7 +1537,7 @@ 138.12 Node* base = adr->in(AddPNode::Base); 138.13 if (base != NULL && 138.14 !phase->type(base)->higher_equal(TypePtr::NULL_PTR)) { 138.15 - Compile::AliasType* atp = phase->C->alias_type(base->adr_type()); 138.16 + Compile::AliasType* atp = C->alias_type(base->adr_type()); 138.17 if (is_autobox_cache(atp)) { 138.18 return jt->join(TypePtr::NOTNULL)->is_ptr(); 138.19 } 138.20 @@ -1546,22 +1547,23 @@ 138.21 } 138.22 } 138.23 } else if (tp->base() == Type::InstPtr) { 138.24 + ciEnv* env = C->env(); 138.25 const TypeInstPtr* tinst = tp->is_instptr(); 138.26 ciKlass* klass = tinst->klass(); 138.27 assert( off != Type::OffsetBot || 138.28 // arrays can be cast to Objects 138.29 tp->is_oopptr()->klass()->is_java_lang_Object() || 138.30 // unsafe field access may not have a constant offset 138.31 - phase->C->has_unsafe_access(), 138.32 + C->has_unsafe_access(), 138.33 "Field accesses must be precise" ); 138.34 // For oop loads, we expect the _type to be precise 138.35 - if (klass == phase->C->env()->String_klass() && 138.36 + if (klass == env->String_klass() && 138.37 adr->is_AddP() && off != Type::OffsetBot) { 138.38 // For constant Strings treat the final fields as compile time constants. 138.39 Node* base = adr->in(AddPNode::Base); 138.40 const TypeOopPtr* t = phase->type(base)->isa_oopptr(); 138.41 if (t != NULL && t->singleton()) { 138.42 - ciField* field = phase->C->env()->String_klass()->get_field_by_offset(off, false); 138.43 + ciField* field = env->String_klass()->get_field_by_offset(off, false); 138.44 if (field != NULL && field->is_final()) { 138.45 ciObject* string = t->const_oop(); 138.46 ciConstant constant = string->as_instance()->field_value(field); 138.47 @@ -1577,6 +1579,32 @@ 138.48 } 138.49 } 138.50 } 138.51 + // Optimizations for constant objects 138.52 + ciObject* const_oop = tinst->const_oop(); 138.53 + if (const_oop != NULL) { 138.54 + // For constant CallSites treat the target field as a compile time constant. 138.55 + if (const_oop->is_call_site()) { 138.56 + ciCallSite* call_site = const_oop->as_call_site(); 138.57 + ciField* field = call_site->klass()->as_instance_klass()->get_field_by_offset(off, /*is_static=*/ false); 138.58 + if (field != NULL && field->is_call_site_target()) { 138.59 + ciMethodHandle* target = call_site->get_target(); 138.60 + if (target != NULL) { // just in case 138.61 + ciConstant constant(T_OBJECT, target); 138.62 + const Type* t; 138.63 + if (adr->bottom_type()->is_ptr_to_narrowoop()) { 138.64 + t = TypeNarrowOop::make_from_constant(constant.as_object(), true); 138.65 + } else { 138.66 + t = TypeOopPtr::make_from_constant(constant.as_object(), true); 138.67 + } 138.68 + // Add a dependence for invalidation of the optimization. 138.69 + if (!call_site->is_constant_call_site()) { 138.70 + C->dependencies()->assert_call_site_target_value(call_site, target); 138.71 + } 138.72 + return t; 138.73 + } 138.74 + } 138.75 + } 138.76 + } 138.77 } else if (tp->base() == Type::KlassPtr) { 138.78 assert( off != Type::OffsetBot || 138.79 // arrays can be cast to Objects
139.1 --- a/src/share/vm/opto/parse.hpp Thu Sep 08 16:59:27 2011 -0700 139.2 +++ b/src/share/vm/opto/parse.hpp Fri Sep 09 16:17:16 2011 -0700 139.3 @@ -78,6 +78,8 @@ 139.4 int stack_depth() const { return _caller_jvms ? _caller_jvms->depth() : 0; } 139.5 139.6 public: 139.7 + static const char* check_can_parse(ciMethod* callee); 139.8 + 139.9 static InlineTree* build_inline_tree_root(); 139.10 static InlineTree* find_subtree_from_root(InlineTree* root, JVMState* jvms, ciMethod* callee, bool create_if_not_found = false); 139.11
140.1 --- a/src/share/vm/opto/parse2.cpp Thu Sep 08 16:59:27 2011 -0700 140.2 +++ b/src/share/vm/opto/parse2.cpp Fri Sep 09 16:17:16 2011 -0700 140.3 @@ -752,20 +752,12 @@ 140.4 // Handle ret bytecode 140.5 void Parse::do_ret() { 140.6 // Find to whom we return. 140.7 -#if 0 // %%%% MAKE THIS WORK 140.8 - Node* con = local(); 140.9 - const TypePtr* tp = con->bottom_type()->isa_ptr(); 140.10 - assert(tp && tp->singleton(), ""); 140.11 - int return_bci = (int) tp->get_con(); 140.12 - merge(return_bci); 140.13 -#else 140.14 assert(block()->num_successors() == 1, "a ret can only go one place now"); 140.15 Block* target = block()->successor_at(0); 140.16 assert(!target->is_ready(), "our arrival must be expected"); 140.17 profile_ret(target->flow()->start()); 140.18 int pnum = target->next_path_num(); 140.19 merge_common(target, pnum); 140.20 -#endif 140.21 } 140.22 140.23 //--------------------------dynamic_branch_prediction--------------------------
141.1 --- a/src/share/vm/opto/parse3.cpp Thu Sep 08 16:59:27 2011 -0700 141.2 +++ b/src/share/vm/opto/parse3.cpp Fri Sep 09 16:17:16 2011 -0700 141.3 @@ -100,11 +100,11 @@ 141.4 } 141.5 } 141.6 141.7 - // Deoptimize on putfield writes to CallSite.target 141.8 + // Deoptimize on putfield writes to call site target field. 141.9 if (!is_get && field->is_call_site_target()) { 141.10 uncommon_trap(Deoptimization::Reason_unhandled, 141.11 Deoptimization::Action_reinterpret, 141.12 - NULL, "put to CallSite.target field"); 141.13 + NULL, "put to call site target field"); 141.14 return; 141.15 } 141.16 141.17 @@ -147,19 +147,21 @@ 141.18 void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) { 141.19 // Does this field have a constant value? If so, just push the value. 141.20 if (field->is_constant()) { 141.21 + // final field 141.22 if (field->is_static()) { 141.23 // final static field 141.24 if (push_constant(field->constant_value())) 141.25 return; 141.26 } 141.27 else { 141.28 - // final non-static field of a trusted class (classes in 141.29 - // java.lang.invoke and sun.invoke packages and subpackages). 141.30 + // final non-static field 141.31 + // Treat final non-static fields of trusted classes (classes in 141.32 + // java.lang.invoke and sun.invoke packages and subpackages) as 141.33 + // compile time constants. 141.34 if (obj->is_Con()) { 141.35 const TypeOopPtr* oop_ptr = obj->bottom_type()->isa_oopptr(); 141.36 ciObject* constant_oop = oop_ptr->const_oop(); 141.37 ciConstant constant = field->constant_value_of(constant_oop); 141.38 - 141.39 if (push_constant(constant, true)) 141.40 return; 141.41 }
142.1 --- a/src/share/vm/opto/runtime.cpp Thu Sep 08 16:59:27 2011 -0700 142.2 +++ b/src/share/vm/opto/runtime.cpp Fri Sep 09 16:17:16 2011 -0700 142.3 @@ -978,7 +978,6 @@ 142.4 142.5 thread->set_exception_pc(pc); 142.6 thread->set_exception_handler_pc(handler_address); 142.7 - thread->set_exception_stack_size(0); 142.8 142.9 // Check if the exception PC is a MethodHandle call site. 142.10 thread->set_is_method_handle_return(nm->is_method_handle_return(pc));
143.1 --- a/src/share/vm/opto/split_if.cpp Thu Sep 08 16:59:27 2011 -0700 143.2 +++ b/src/share/vm/opto/split_if.cpp Fri Sep 09 16:17:16 2011 -0700 143.3 @@ -500,19 +500,14 @@ 143.4 region_cache.lru_insert( new_false, new_false ); 143.5 region_cache.lru_insert( new_true , new_true ); 143.6 // Now handle all uses of the splitting block 143.7 - for (DUIterator_Last kmin, k = region->last_outs(kmin); k >= kmin; --k) { 143.8 - Node* phi = region->last_out(k); 143.9 - if( !phi->in(0) ) { // Dead phi? Remove it 143.10 + for (DUIterator k = region->outs(); region->has_out(k); k++) { 143.11 + Node* phi = region->out(k); 143.12 + if (!phi->in(0)) { // Dead phi? Remove it 143.13 _igvn.remove_dead_node(phi); 143.14 - continue; 143.15 - } 143.16 - assert( phi->in(0) == region, "" ); 143.17 - if( phi == region ) { // Found the self-reference 143.18 - phi->set_req(0, NULL); 143.19 - continue; // Break the self-cycle 143.20 - } 143.21 - // Expected common case: Phi hanging off of Region 143.22 - if( phi->is_Phi() ) { 143.23 + } else if (phi == region) { // Found the self-reference 143.24 + continue; // No roll-back of DUIterator 143.25 + } else if (phi->is_Phi()) { // Expected common case: Phi hanging off of Region 143.26 + assert(phi->in(0) == region, "Inconsistent graph"); 143.27 // Need a per-def cache. Phi represents a def, so make a cache 143.28 small_cache phi_cache; 143.29 143.30 @@ -524,22 +519,24 @@ 143.31 // collection of PHI's merging values from different paths. The Phis 143.32 // inserted depend only on the location of the USE. We use a 143.33 // 2-element cache to handle multiple uses from the same block. 143.34 - handle_use( use, phi, &phi_cache, region_dom, new_false, new_true, old_false, old_true ); 143.35 + handle_use(use, phi, &phi_cache, region_dom, new_false, new_true, old_false, old_true); 143.36 } // End of while phi has uses 143.37 - 143.38 - // Because handle_use might relocate region->_out, 143.39 - // we must refresh the iterator. 143.40 - k = region->last_outs(kmin); 143.41 - 143.42 // Remove the dead Phi 143.43 _igvn.remove_dead_node( phi ); 143.44 + } else { 143.45 + assert(phi->in(0) == region, "Inconsistent graph"); 143.46 + // Random memory op guarded by Region. Compute new DEF for USE. 143.47 + handle_use(phi, region, ®ion_cache, region_dom, new_false, new_true, old_false, old_true); 143.48 + } 143.49 + // Every path above deletes a use of the region, except for the region 143.50 + // self-cycle (which is needed by handle_use calling find_use_block 143.51 + // calling get_ctrl calling get_ctrl_no_update looking for dead 143.52 + // regions). So roll back the DUIterator innards. 143.53 + --k; 143.54 + } // End of while merge point has phis 143.55 143.56 - } else { 143.57 - // Random memory op guarded by Region. Compute new DEF for USE. 143.58 - handle_use( phi, region, ®ion_cache, region_dom, new_false, new_true, old_false, old_true ); 143.59 - } 143.60 - 143.61 - } // End of while merge point has phis 143.62 + assert(region->outcnt() == 1, "Only self reference should remain"); // Just Self on the Region 143.63 + region->set_req(0, NULL); // Break the self-cycle 143.64 143.65 // Any leftover bits in the splitting block must not have depended on local 143.66 // Phi inputs (these have already been split-up). Hence it's safe to hoist
144.1 --- a/src/share/vm/precompiled.hpp Thu Sep 08 16:59:27 2011 -0700 144.2 +++ b/src/share/vm/precompiled.hpp Fri Sep 09 16:17:16 2011 -0700 144.3 @@ -206,7 +206,6 @@ 144.4 # include "runtime/perfMemory.hpp" 144.5 # include "runtime/prefetch.hpp" 144.6 # include "runtime/reflection.hpp" 144.7 -# include "runtime/reflectionCompat.hpp" 144.8 # include "runtime/reflectionUtils.hpp" 144.9 # include "runtime/registerMap.hpp" 144.10 # include "runtime/safepoint.hpp"
145.1 --- a/src/share/vm/prims/forte.cpp Thu Sep 08 16:59:27 2011 -0700 145.2 +++ b/src/share/vm/prims/forte.cpp Fri Sep 09 16:17:16 2011 -0700 145.3 @@ -522,25 +522,6 @@ 145.4 extern "C" { 145.5 JNIEXPORT 145.6 void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { 145.7 - 145.8 -// This is if'd out because we no longer use thread suspension. 145.9 -// However if someone wanted to backport this to a 5.0 jvm then this 145.10 -// code would be important. 145.11 -#if 0 145.12 - if (SafepointSynchronize::is_synchronizing()) { 145.13 - // The safepoint mechanism is trying to synchronize all the threads. 145.14 - // Since this can involve thread suspension, it is not safe for us 145.15 - // to be here. We can reduce the deadlock risk window by quickly 145.16 - // returning to the SIGPROF handler. However, it is still possible 145.17 - // for VMThread to catch us here or in the SIGPROF handler. If we 145.18 - // are suspended while holding a resource and another thread blocks 145.19 - // on that resource in the SIGPROF handler, then we will have a 145.20 - // three-thread deadlock (VMThread, this thread, the other thread). 145.21 - trace->num_frames = ticks_safepoint; // -10 145.22 - return; 145.23 - } 145.24 -#endif 145.25 - 145.26 JavaThread* thread; 145.27 145.28 if (trace->env_id == NULL ||
146.1 --- a/src/share/vm/prims/jvm.cpp Thu Sep 08 16:59:27 2011 -0700 146.2 +++ b/src/share/vm/prims/jvm.cpp Fri Sep 09 16:17:16 2011 -0700 146.3 @@ -4020,249 +4020,6 @@ 146.4 #endif 146.5 146.6 146.7 -//--------------------------------------------------------------------------- 146.8 -// 146.9 -// Support for old native code-based reflection (pre-JDK 1.4) 146.10 -// Disabled by default in the product build. 146.11 -// 146.12 -// See reflection.hpp for information on SUPPORT_OLD_REFLECTION 146.13 -// 146.14 -//--------------------------------------------------------------------------- 146.15 - 146.16 -#ifdef SUPPORT_OLD_REFLECTION 146.17 - 146.18 -JVM_ENTRY(jobjectArray, JVM_GetClassFields(JNIEnv *env, jclass cls, jint which)) 146.19 - JVMWrapper("JVM_GetClassFields"); 146.20 - JvmtiVMObjectAllocEventCollector oam; 146.21 - oop mirror = JNIHandles::resolve_non_null(cls); 146.22 - objArrayOop result = Reflection::reflect_fields(mirror, which, CHECK_NULL); 146.23 - return (jobjectArray) JNIHandles::make_local(env, result); 146.24 -JVM_END 146.25 - 146.26 - 146.27 -JVM_ENTRY(jobjectArray, JVM_GetClassMethods(JNIEnv *env, jclass cls, jint which)) 146.28 - JVMWrapper("JVM_GetClassMethods"); 146.29 - JvmtiVMObjectAllocEventCollector oam; 146.30 - oop mirror = JNIHandles::resolve_non_null(cls); 146.31 - objArrayOop result = Reflection::reflect_methods(mirror, which, CHECK_NULL); 146.32 - //%note jvm_r4 146.33 - return (jobjectArray) JNIHandles::make_local(env, result); 146.34 -JVM_END 146.35 - 146.36 - 146.37 -JVM_ENTRY(jobjectArray, JVM_GetClassConstructors(JNIEnv *env, jclass cls, jint which)) 146.38 - JVMWrapper("JVM_GetClassConstructors"); 146.39 - JvmtiVMObjectAllocEventCollector oam; 146.40 - oop mirror = JNIHandles::resolve_non_null(cls); 146.41 - objArrayOop result = Reflection::reflect_constructors(mirror, which, CHECK_NULL); 146.42 - //%note jvm_r4 146.43 - return (jobjectArray) JNIHandles::make_local(env, result); 146.44 -JVM_END 146.45 - 146.46 - 146.47 -JVM_ENTRY(jobject, JVM_GetClassField(JNIEnv *env, jclass cls, jstring name, jint which)) 146.48 - JVMWrapper("JVM_GetClassField"); 146.49 - JvmtiVMObjectAllocEventCollector oam; 146.50 - if (name == NULL) return NULL; 146.51 - Handle str (THREAD, JNIHandles::resolve_non_null(name)); 146.52 - 146.53 - const char* cstr = java_lang_String::as_utf8_string(str()); 146.54 - TempNewSymbol field_name = SymbolTable::probe(cstr, (int)strlen(cstr)); 146.55 - if (field_name == NULL) { 146.56 - THROW_0(vmSymbols::java_lang_NoSuchFieldException()); 146.57 - } 146.58 - 146.59 - oop mirror = JNIHandles::resolve_non_null(cls); 146.60 - oop result = Reflection::reflect_field(mirror, field_name, which, CHECK_NULL); 146.61 - if (result == NULL) { 146.62 - THROW_0(vmSymbols::java_lang_NoSuchFieldException()); 146.63 - } 146.64 - return JNIHandles::make_local(env, result); 146.65 -JVM_END 146.66 - 146.67 - 146.68 -JVM_ENTRY(jobject, JVM_GetClassMethod(JNIEnv *env, jclass cls, jstring name, jobjectArray types, jint which)) 146.69 - JVMWrapper("JVM_GetClassMethod"); 146.70 - JvmtiVMObjectAllocEventCollector oam; 146.71 - if (name == NULL) { 146.72 - THROW_0(vmSymbols::java_lang_NullPointerException()); 146.73 - } 146.74 - Handle str (THREAD, JNIHandles::resolve_non_null(name)); 146.75 - 146.76 - const char* cstr = java_lang_String::as_utf8_string(str()); 146.77 - TempNewSymbol method_name = SymbolTable::probe(cstr, (int)strlen(cstr)); 146.78 - if (method_name == NULL) { 146.79 - THROW_0(vmSymbols::java_lang_NoSuchMethodException()); 146.80 - } 146.81 - 146.82 - oop mirror = JNIHandles::resolve_non_null(cls); 146.83 - objArrayHandle tarray (THREAD, objArrayOop(JNIHandles::resolve(types))); 146.84 - oop result = Reflection::reflect_method(mirror, method_name, tarray, 146.85 - which, CHECK_NULL); 146.86 - if (result == NULL) { 146.87 - THROW_0(vmSymbols::java_lang_NoSuchMethodException()); 146.88 - } 146.89 - return JNIHandles::make_local(env, result); 146.90 -JVM_END 146.91 - 146.92 - 146.93 -JVM_ENTRY(jobject, JVM_GetClassConstructor(JNIEnv *env, jclass cls, jobjectArray types, jint which)) 146.94 - JVMWrapper("JVM_GetClassConstructor"); 146.95 - JvmtiVMObjectAllocEventCollector oam; 146.96 - oop mirror = JNIHandles::resolve_non_null(cls); 146.97 - objArrayHandle tarray (THREAD, objArrayOop(JNIHandles::resolve(types))); 146.98 - oop result = Reflection::reflect_constructor(mirror, tarray, which, CHECK_NULL); 146.99 - if (result == NULL) { 146.100 - THROW_0(vmSymbols::java_lang_NoSuchMethodException()); 146.101 - } 146.102 - return (jobject) JNIHandles::make_local(env, result); 146.103 -JVM_END 146.104 - 146.105 - 146.106 -// Instantiation /////////////////////////////////////////////////////////////////////////////// 146.107 - 146.108 -JVM_ENTRY(jobject, JVM_NewInstance(JNIEnv *env, jclass cls)) 146.109 - JVMWrapper("JVM_NewInstance"); 146.110 - Handle mirror(THREAD, JNIHandles::resolve_non_null(cls)); 146.111 - 146.112 - methodOop resolved_constructor = java_lang_Class::resolved_constructor(mirror()); 146.113 - if (resolved_constructor == NULL) { 146.114 - klassOop k = java_lang_Class::as_klassOop(mirror()); 146.115 - // The java.lang.Class object caches a resolved constructor if all the checks 146.116 - // below were done successfully and a constructor was found. 146.117 - 146.118 - // Do class based checks 146.119 - if (java_lang_Class::is_primitive(mirror())) { 146.120 - const char* msg = ""; 146.121 - if (mirror == Universe::bool_mirror()) msg = "java/lang/Boolean"; 146.122 - else if (mirror == Universe::char_mirror()) msg = "java/lang/Character"; 146.123 - else if (mirror == Universe::float_mirror()) msg = "java/lang/Float"; 146.124 - else if (mirror == Universe::double_mirror()) msg = "java/lang/Double"; 146.125 - else if (mirror == Universe::byte_mirror()) msg = "java/lang/Byte"; 146.126 - else if (mirror == Universe::short_mirror()) msg = "java/lang/Short"; 146.127 - else if (mirror == Universe::int_mirror()) msg = "java/lang/Integer"; 146.128 - else if (mirror == Universe::long_mirror()) msg = "java/lang/Long"; 146.129 - THROW_MSG_0(vmSymbols::java_lang_NullPointerException(), msg); 146.130 - } 146.131 - 146.132 - // Check whether we are allowed to instantiate this class 146.133 - Klass::cast(k)->check_valid_for_instantiation(false, CHECK_NULL); // Array classes get caught here 146.134 - instanceKlassHandle klass(THREAD, k); 146.135 - // Make sure class is initialized (also so all methods are rewritten) 146.136 - klass->initialize(CHECK_NULL); 146.137 - 146.138 - // Lookup default constructor 146.139 - resolved_constructor = klass->find_method(vmSymbols::object_initializer_name(), vmSymbols::void_method_signature()); 146.140 - if (resolved_constructor == NULL) { 146.141 - ResourceMark rm(THREAD); 146.142 - THROW_MSG_0(vmSymbols::java_lang_InstantiationException(), klass->external_name()); 146.143 - } 146.144 - 146.145 - // Cache result in java.lang.Class object. Does not have to be MT safe. 146.146 - java_lang_Class::set_resolved_constructor(mirror(), resolved_constructor); 146.147 - } 146.148 - 146.149 - assert(resolved_constructor != NULL, "sanity check"); 146.150 - methodHandle constructor = methodHandle(THREAD, resolved_constructor); 146.151 - 146.152 - // We have an initialized instanceKlass with a default constructor 146.153 - instanceKlassHandle klass(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls))); 146.154 - assert(klass->is_initialized() || klass->is_being_initialized(), "sanity check"); 146.155 - 146.156 - // Do security check 146.157 - klassOop caller_klass = NULL; 146.158 - if (UsePrivilegedStack) { 146.159 - caller_klass = thread->security_get_caller_class(2); 146.160 - 146.161 - if (!Reflection::verify_class_access(caller_klass, klass(), false) || 146.162 - !Reflection::verify_field_access(caller_klass, 146.163 - klass(), 146.164 - klass(), 146.165 - constructor->access_flags(), 146.166 - false, 146.167 - true)) { 146.168 - ResourceMark rm(THREAD); 146.169 - THROW_MSG_0(vmSymbols::java_lang_IllegalAccessException(), klass->external_name()); 146.170 - } 146.171 - } 146.172 - 146.173 - // Allocate object and call constructor 146.174 - Handle receiver = klass->allocate_instance_handle(CHECK_NULL); 146.175 - JavaCalls::call_default_constructor(thread, constructor, receiver, CHECK_NULL); 146.176 - 146.177 - jobject res = JNIHandles::make_local(env, receiver()); 146.178 - if (JvmtiExport::should_post_vm_object_alloc()) { 146.179 - JvmtiExport::post_vm_object_alloc(JavaThread::current(), receiver()); 146.180 - } 146.181 - return res; 146.182 -JVM_END 146.183 - 146.184 - 146.185 -// Field //////////////////////////////////////////////////////////////////////////////////////////// 146.186 - 146.187 -JVM_ENTRY(jobject, JVM_GetField(JNIEnv *env, jobject field, jobject obj)) 146.188 - JVMWrapper("JVM_GetField"); 146.189 - JvmtiVMObjectAllocEventCollector oam; 146.190 - Handle field_mirror(thread, JNIHandles::resolve(field)); 146.191 - Handle receiver (thread, JNIHandles::resolve(obj)); 146.192 - fieldDescriptor fd; 146.193 - Reflection::resolve_field(field_mirror, receiver, &fd, false, CHECK_NULL); 146.194 - jvalue value; 146.195 - BasicType type = Reflection::field_get(&value, &fd, receiver); 146.196 - oop box = Reflection::box(&value, type, CHECK_NULL); 146.197 - return JNIHandles::make_local(env, box); 146.198 -JVM_END 146.199 - 146.200 - 146.201 -JVM_ENTRY(jvalue, JVM_GetPrimitiveField(JNIEnv *env, jobject field, jobject obj, unsigned char wCode)) 146.202 - JVMWrapper("JVM_GetPrimitiveField"); 146.203 - Handle field_mirror(thread, JNIHandles::resolve(field)); 146.204 - Handle receiver (thread, JNIHandles::resolve(obj)); 146.205 - fieldDescriptor fd; 146.206 - jvalue value; 146.207 - value.j = 0; 146.208 - Reflection::resolve_field(field_mirror, receiver, &fd, false, CHECK_(value)); 146.209 - BasicType type = Reflection::field_get(&value, &fd, receiver); 146.210 - BasicType wide_type = (BasicType) wCode; 146.211 - if (type != wide_type) { 146.212 - Reflection::widen(&value, type, wide_type, CHECK_(value)); 146.213 - } 146.214 - return value; 146.215 -JVM_END // should really be JVM_END, but that doesn't work for union types! 146.216 - 146.217 - 146.218 -JVM_ENTRY(void, JVM_SetField(JNIEnv *env, jobject field, jobject obj, jobject val)) 146.219 - JVMWrapper("JVM_SetField"); 146.220 - Handle field_mirror(thread, JNIHandles::resolve(field)); 146.221 - Handle receiver (thread, JNIHandles::resolve(obj)); 146.222 - oop box = JNIHandles::resolve(val); 146.223 - fieldDescriptor fd; 146.224 - Reflection::resolve_field(field_mirror, receiver, &fd, true, CHECK); 146.225 - BasicType field_type = fd.field_type(); 146.226 - jvalue value; 146.227 - BasicType value_type; 146.228 - if (field_type == T_OBJECT || field_type == T_ARRAY) { 146.229 - // Make sure we do no unbox e.g. java/lang/Integer instances when storing into an object array 146.230 - value_type = Reflection::unbox_for_regular_object(box, &value); 146.231 - Reflection::field_set(&value, &fd, receiver, field_type, CHECK); 146.232 - } else { 146.233 - value_type = Reflection::unbox_for_primitive(box, &value, CHECK); 146.234 - Reflection::field_set(&value, &fd, receiver, value_type, CHECK); 146.235 - } 146.236 -JVM_END 146.237 - 146.238 - 146.239 -JVM_ENTRY(void, JVM_SetPrimitiveField(JNIEnv *env, jobject field, jobject obj, jvalue v, unsigned char vCode)) 146.240 - JVMWrapper("JVM_SetPrimitiveField"); 146.241 - Handle field_mirror(thread, JNIHandles::resolve(field)); 146.242 - Handle receiver (thread, JNIHandles::resolve(obj)); 146.243 - fieldDescriptor fd; 146.244 - Reflection::resolve_field(field_mirror, receiver, &fd, true, CHECK); 146.245 - BasicType value_type = (BasicType) vCode; 146.246 - Reflection::field_set(&v, &fd, receiver, value_type, CHECK); 146.247 -JVM_END 146.248 - 146.249 - 146.250 // Method /////////////////////////////////////////////////////////////////////////////////////////// 146.251 146.252 JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0)) 146.253 @@ -4302,8 +4059,6 @@ 146.254 return res; 146.255 JVM_END 146.256 146.257 -#endif /* SUPPORT_OLD_REFLECTION */ 146.258 - 146.259 // Atomic /////////////////////////////////////////////////////////////////////////////////////////// 146.260 146.261 JVM_LEAF(jboolean, JVM_SupportsCX8())
147.1 --- a/src/share/vm/prims/jvm.h Thu Sep 08 16:59:27 2011 -0700 147.2 +++ b/src/share/vm/prims/jvm.h Fri Sep 09 16:17:16 2011 -0700 147.3 @@ -26,7 +26,6 @@ 147.4 #define SHARE_VM_PRIMS_JVM_H 147.5 147.6 #include "prims/jni.h" 147.7 -#include "runtime/reflectionCompat.hpp" 147.8 #ifdef TARGET_OS_FAMILY_linux 147.9 # include "jvm_linux.h" 147.10 #endif 147.11 @@ -43,8 +42,7 @@ 147.12 // HotSpot integration note: 147.13 // 147.14 // This file and jvm.h used with the JDK are identical, 147.15 -// except for the three includes removed below and the 147.16 -// SUPPORT_OLD_REFLECTION sections cut out of the JDK's jvm.h. 147.17 +// except for the three includes removed below 147.18 147.19 // #include <sys/stat.h> 147.20 // #include "jni.h" 147.21 @@ -443,14 +441,6 @@ 147.22 jsize len, jobject pd, const char *source, 147.23 jboolean verify); 147.24 147.25 -/* Define a class with a source (MLVM) */ 147.26 -JNIEXPORT jclass JNICALL 147.27 -JVM_DefineClassWithCP(JNIEnv *env, const char *name, jobject loader, 147.28 - const jbyte *buf, jsize len, jobject pd, 147.29 - const char *source, 147.30 - // same args as JVM_DefineClassWithSource to this point 147.31 - jobjectArray constants); 147.32 - 147.33 /* 147.34 * Reflection support functions 147.35 */ 147.36 @@ -1442,65 +1432,6 @@ 147.37 JNIEXPORT void JNICALL 147.38 JVM_RawMonitorExit(void *mon); 147.39 147.40 - 147.41 -#ifdef SUPPORT_OLD_REFLECTION 147.42 - 147.43 -/* 147.44 - * Support for old native code-based (pre-JDK 1.4) reflection implementation. 147.45 - * Disabled by default in the product build. 147.46 - * 147.47 - * See reflection.hpp for information on SUPPORT_OLD_REFLECTION 147.48 - */ 147.49 - 147.50 -/* 147.51 - * reflecting fields and methods. 147.52 - * which: 0 --- MEMBER_PUBLIC 147.53 - * 1 --- MEMBER_DECLARED 147.54 - * NOTE: absent in product build by default 147.55 - */ 147.56 - 147.57 -JNIEXPORT jobjectArray JNICALL 147.58 -JVM_GetClassFields(JNIEnv *env, jclass cls, jint which); 147.59 - 147.60 -JNIEXPORT jobjectArray JNICALL 147.61 -JVM_GetClassMethods(JNIEnv *env, jclass cls, jint which); 147.62 - 147.63 -JNIEXPORT jobjectArray JNICALL 147.64 -JVM_GetClassConstructors(JNIEnv *env, jclass cls, jint which); 147.65 - 147.66 -JNIEXPORT jobject JNICALL 147.67 -JVM_GetClassField(JNIEnv *env, jclass cls, jstring name, jint which); 147.68 - 147.69 -JNIEXPORT jobject JNICALL 147.70 -JVM_GetClassMethod(JNIEnv *env, jclass cls, jstring name, jobjectArray types, 147.71 - jint which); 147.72 -JNIEXPORT jobject JNICALL 147.73 -JVM_GetClassConstructor(JNIEnv *env, jclass cls, jobjectArray types, 147.74 - jint which); 147.75 - 147.76 -/* 147.77 - * Implements Class.newInstance 147.78 - */ 147.79 -JNIEXPORT jobject JNICALL 147.80 -JVM_NewInstance(JNIEnv *env, jclass cls); 147.81 - 147.82 -/* 147.83 - * java.lang.reflect.Field 147.84 - */ 147.85 -JNIEXPORT jobject JNICALL 147.86 -JVM_GetField(JNIEnv *env, jobject field, jobject obj); 147.87 - 147.88 -JNIEXPORT jvalue JNICALL 147.89 -JVM_GetPrimitiveField(JNIEnv *env, jobject field, jobject obj, 147.90 - unsigned char wCode); 147.91 - 147.92 -JNIEXPORT void JNICALL 147.93 -JVM_SetField(JNIEnv *env, jobject field, jobject obj, jobject val); 147.94 - 147.95 -JNIEXPORT void JNICALL 147.96 -JVM_SetPrimitiveField(JNIEnv *env, jobject field, jobject obj, jvalue v, 147.97 - unsigned char vCode); 147.98 - 147.99 /* 147.100 * java.lang.reflect.Method 147.101 */ 147.102 @@ -1513,8 +1444,6 @@ 147.103 JNIEXPORT jobject JNICALL 147.104 JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0); 147.105 147.106 -#endif /* SUPPORT_OLD_REFLECTION */ 147.107 - 147.108 /* 147.109 * java.lang.management support 147.110 */ 147.111 @@ -1650,7 +1579,8 @@ 147.112 */ 147.113 unsigned int thread_park_blocker : 1; 147.114 unsigned int post_vm_init_hook_enabled : 1; 147.115 - unsigned int : 30; 147.116 + unsigned int pending_list_uses_discovered_field : 1; 147.117 + unsigned int : 29; 147.118 unsigned int : 32; 147.119 unsigned int : 32; 147.120 } jdk_version_info;
148.1 --- a/src/share/vm/prims/methodHandleWalk.cpp Thu Sep 08 16:59:27 2011 -0700 148.2 +++ b/src/share/vm/prims/methodHandleWalk.cpp Fri Sep 09 16:17:16 2011 -0700 148.3 @@ -182,10 +182,6 @@ 148.4 HandleMark hm; 148.5 ResourceMark rm; 148.6 Handle mh(m); 148.7 - print(mh); 148.8 -} 148.9 - 148.10 -void MethodHandleChain::print(Handle mh) { 148.11 EXCEPTION_MARK; 148.12 MethodHandleChain mhc(mh, THREAD); 148.13 if (HAS_PENDING_EXCEPTION) { 148.14 @@ -222,16 +218,33 @@ 148.15 if (o != NULL) { 148.16 if (o->is_instance()) { 148.17 tty->print(" instance %s", o->klass()->klass_part()->internal_name()); 148.18 + if (java_lang_invoke_CountingMethodHandle::is_instance(o)) { 148.19 + tty->print(" vmcount: %d", java_lang_invoke_CountingMethodHandle::vmcount(o)); 148.20 + } 148.21 } else { 148.22 o->print(); 148.23 } 148.24 } 148.25 + oop vmt = chain.vmtarget_oop(); 148.26 + if (vmt != NULL) { 148.27 + if (vmt->is_method()) { 148.28 + tty->print(" "); 148.29 + methodOop(vmt)->print_short_name(tty); 148.30 + } else if (java_lang_invoke_MethodHandle::is_instance(vmt)) { 148.31 + tty->print(" method handle " INTPTR_FORMAT, vmt); 148.32 + } else { 148.33 + ShouldNotReachHere(); 148.34 + } 148.35 + } 148.36 } else if (chain.is_adapter()) { 148.37 tty->print("adapter: arg_slot %d conversion op %s", 148.38 chain.adapter_arg_slot(), 148.39 adapter_op_to_string(chain.adapter_conversion_op())); 148.40 switch (chain.adapter_conversion_op()) { 148.41 case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY: 148.42 + if (java_lang_invoke_CountingMethodHandle::is_instance(chain.method_handle_oop())) { 148.43 + tty->print(" vmcount: %d", java_lang_invoke_CountingMethodHandle::vmcount(chain.method_handle_oop())); 148.44 + } 148.45 case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW: 148.46 case java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST: 148.47 case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM: 148.48 @@ -907,7 +920,10 @@ 148.49 _non_bcp_klasses(THREAD, 5), 148.50 _cur_stack(0), 148.51 _max_stack(0), 148.52 - _rtype(T_ILLEGAL) 148.53 + _rtype(T_ILLEGAL), 148.54 + _selectAlternative_bci(-1), 148.55 + _taken_count(0), 148.56 + _not_taken_count(0) 148.57 { 148.58 148.59 // Element zero is always the null constant. 148.60 @@ -1115,11 +1131,50 @@ 148.61 _bytecode.push(0); 148.62 break; 148.63 148.64 + case Bytecodes::_ifeq: 148.65 + assert((unsigned short) index == index, "index does not fit in 16-bit"); 148.66 + _bytecode.push(op); 148.67 + _bytecode.push(index >> 8); 148.68 + _bytecode.push(index); 148.69 + break; 148.70 + 148.71 default: 148.72 ShouldNotReachHere(); 148.73 } 148.74 } 148.75 148.76 +void MethodHandleCompiler::update_branch_dest(int src, int dst) { 148.77 + switch (_bytecode.at(src)) { 148.78 + case Bytecodes::_ifeq: 148.79 + dst -= src; // compute the offset 148.80 + assert((unsigned short) dst == dst, "index does not fit in 16-bit"); 148.81 + _bytecode.at_put(src + 1, dst >> 8); 148.82 + _bytecode.at_put(src + 2, dst); 148.83 + break; 148.84 + default: 148.85 + ShouldNotReachHere(); 148.86 + } 148.87 +} 148.88 + 148.89 +void MethodHandleCompiler::emit_load(ArgToken arg) { 148.90 + TokenType tt = arg.token_type(); 148.91 + BasicType bt = arg.basic_type(); 148.92 + 148.93 + switch (tt) { 148.94 + case tt_parameter: 148.95 + case tt_temporary: 148.96 + emit_load(bt, arg.index()); 148.97 + break; 148.98 + case tt_constant: 148.99 + emit_load_constant(arg); 148.100 + break; 148.101 + case tt_illegal: 148.102 + case tt_void: 148.103 + default: 148.104 + ShouldNotReachHere(); 148.105 + } 148.106 +} 148.107 + 148.108 148.109 void MethodHandleCompiler::emit_load(BasicType bt, int index) { 148.110 if (index <= 3) { 148.111 @@ -1318,6 +1373,29 @@ 148.112 jvalue MethodHandleCompiler::zero_jvalue = { 0 }; 148.113 jvalue MethodHandleCompiler::one_jvalue = { 1 }; 148.114 148.115 +// Fetch any values from CountingMethodHandles and capture them for profiles 148.116 +bool MethodHandleCompiler::fetch_counts(ArgToken arg1, ArgToken arg2) { 148.117 + int count1 = -1, count2 = -1; 148.118 + if (arg1.token_type() == tt_constant && arg1.basic_type() == T_OBJECT && 148.119 + java_lang_invoke_CountingMethodHandle::is_instance(arg1.object()())) { 148.120 + count1 = java_lang_invoke_CountingMethodHandle::vmcount(arg1.object()()); 148.121 + } 148.122 + if (arg2.token_type() == tt_constant && arg2.basic_type() == T_OBJECT && 148.123 + java_lang_invoke_CountingMethodHandle::is_instance(arg2.object()())) { 148.124 + count2 = java_lang_invoke_CountingMethodHandle::vmcount(arg2.object()()); 148.125 + } 148.126 + int total = count1 + count2; 148.127 + if (count1 != -1 && count2 != -1 && total != 0) { 148.128 + // Normalize the collect counts to the invoke_count 148.129 + tty->print("counts %d %d scaled by %d = ", count2, count1, _invoke_count); 148.130 + if (count1 != 0) _not_taken_count = (int)(_invoke_count * count1 / (double)total); 148.131 + if (count2 != 0) _taken_count = (int)(_invoke_count * count2 / (double)total); 148.132 + tty->print_cr("%d %d", _taken_count, _not_taken_count); 148.133 + return true; 148.134 + } 148.135 + return false; 148.136 +} 148.137 + 148.138 // Emit bytecodes for the given invoke instruction. 148.139 MethodHandleWalker::ArgToken 148.140 MethodHandleCompiler::make_invoke(methodHandle m, vmIntrinsics::ID iid, 148.141 @@ -1367,6 +1445,29 @@ 148.142 } 148.143 } 148.144 148.145 + if (m->intrinsic_id() == vmIntrinsics::_selectAlternative && 148.146 + fetch_counts(argv[1], argv[2])) { 148.147 + assert(argc == 3, "three arguments"); 148.148 + assert(tailcall, "only"); 148.149 + 148.150 + // do inline bytecodes so we can drop profile data into it, 148.151 + // 0: iload_0 148.152 + emit_load(argv[0]); 148.153 + // 1: ifeq 8 148.154 + _selectAlternative_bci = _bytecode.length(); 148.155 + emit_bc(Bytecodes::_ifeq, 0); // emit placeholder offset 148.156 + // 4: aload_1 148.157 + emit_load(argv[1]); 148.158 + // 5: areturn; 148.159 + emit_bc(Bytecodes::_areturn); 148.160 + // 8: aload_2 148.161 + update_branch_dest(_selectAlternative_bci, cur_bci()); 148.162 + emit_load(argv[2]); 148.163 + // 9: areturn 148.164 + emit_bc(Bytecodes::_areturn); 148.165 + return ArgToken(); // Dummy return value. 148.166 + } 148.167 + 148.168 check_non_bcp_klass(klass, CHECK_(zero)); 148.169 if (m->is_method_handle_invoke()) { 148.170 check_non_bcp_klasses(m->method_handle_type(), CHECK_(zero)); 148.171 @@ -1377,10 +1478,6 @@ 148.172 assert(argc == asc.size() + ((op == Bytecodes::_invokestatic || op == Bytecodes::_invokedynamic) ? 0 : 1), 148.173 "argc mismatch"); 148.174 148.175 - // Inline the method. 148.176 - InvocationCounter* ic = m->invocation_counter(); 148.177 - ic->set_carry_flag(); 148.178 - 148.179 for (int i = 0; i < argc; i++) { 148.180 ArgToken arg = argv[i]; 148.181 TokenType tt = arg.token_type(); 148.182 @@ -1686,7 +1783,7 @@ 148.183 } 148.184 148.185 148.186 -methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const { 148.187 +methodHandle MethodHandleCompiler::get_method_oop(TRAPS) { 148.188 methodHandle empty; 148.189 // Create a method that holds the generated bytecode. invokedynamic 148.190 // has no receiver, normal MH calls do. 148.191 @@ -1765,6 +1862,7 @@ 148.192 assert(m->method_data() == NULL, "there should not be an MDO yet"); 148.193 m->set_method_data(mdo); 148.194 148.195 + bool found_selectAlternative = false; 148.196 // Iterate over all profile data and set the count of the counter 148.197 // data entries to the original call site counter. 148.198 for (ProfileData* profile_data = mdo->first_data(); 148.199 @@ -1774,7 +1872,15 @@ 148.200 CounterData* counter_data = profile_data->as_CounterData(); 148.201 counter_data->set_count(_invoke_count); 148.202 } 148.203 + if (profile_data->is_BranchData() && 148.204 + profile_data->bci() == _selectAlternative_bci) { 148.205 + BranchData* bd = profile_data->as_BranchData(); 148.206 + bd->set_taken(_taken_count); 148.207 + bd->set_not_taken(_not_taken_count); 148.208 + found_selectAlternative = true; 148.209 + } 148.210 } 148.211 + assert(_selectAlternative_bci == -1 || found_selectAlternative, "must have found profile entry"); 148.212 } 148.213 148.214 #ifndef PRODUCT
149.1 --- a/src/share/vm/prims/methodHandleWalk.hpp Thu Sep 08 16:59:27 2011 -0700 149.2 +++ b/src/share/vm/prims/methodHandleWalk.hpp Fri Sep 09 16:17:16 2011 -0700 149.3 @@ -74,6 +74,7 @@ 149.4 set_method_handle(MethodHandle_vmtarget_oop(), THREAD); 149.5 } 149.6 149.7 + Handle root() { return _root; } 149.8 Handle method_handle() { return _method_handle; } 149.9 oop method_handle_oop() { return _method_handle(); } 149.10 oop method_type_oop() { return MethodHandle_type_oop(); } 149.11 @@ -110,7 +111,6 @@ 149.12 // the signature for each method. The signatures are printed in 149.13 // slot order to make it easier to understand. 149.14 void print(); 149.15 - static void print(Handle mh); 149.16 static void print(oopDesc* mh); 149.17 #endif 149.18 }; 149.19 @@ -277,6 +277,10 @@ 149.20 KlassHandle _target_klass; 149.21 Thread* _thread; 149.22 149.23 + int _selectAlternative_bci; // These are used for capturing profiles from GWTs 149.24 + int _taken_count; 149.25 + int _not_taken_count; 149.26 + 149.27 // Values used by the compiler. 149.28 static jvalue zero_jvalue; 149.29 static jvalue one_jvalue; 149.30 @@ -372,6 +376,7 @@ 149.31 149.32 unsigned char* bytecode() const { return _bytecode.adr_at(0); } 149.33 int bytecode_length() const { return _bytecode.length(); } 149.34 + int cur_bci() const { return _bytecode.length(); } 149.35 149.36 // Fake constant pool. 149.37 int cpool_oop_put(int tag, Handle con) { 149.38 @@ -436,6 +441,8 @@ 149.39 } 149.40 149.41 void emit_bc(Bytecodes::Code op, int index = 0, int args_size = -1); 149.42 + void update_branch_dest(int src, int dst); 149.43 + void emit_load(ArgToken arg); 149.44 void emit_load(BasicType bt, int index); 149.45 void emit_store(BasicType bt, int index); 149.46 void emit_load_constant(ArgToken arg); 149.47 @@ -455,11 +462,14 @@ 149.48 virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS); 149.49 virtual ArgToken make_invoke(methodHandle m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS); 149.50 149.51 + // Check for profiling information on a GWT and return true if it's found 149.52 + bool fetch_counts(ArgToken a1, ArgToken a2); 149.53 + 149.54 // Get a real constant pool. 149.55 constantPoolHandle get_constant_pool(TRAPS) const; 149.56 149.57 // Get a real methodOop. 149.58 - methodHandle get_method_oop(TRAPS) const; 149.59 + methodHandle get_method_oop(TRAPS); 149.60 149.61 public: 149.62 MethodHandleCompiler(Handle root, Symbol* name, Symbol* signature, int invoke_count, bool for_invokedynamic, TRAPS);
150.1 --- a/src/share/vm/prims/methodHandles.cpp Thu Sep 08 16:59:27 2011 -0700 150.2 +++ b/src/share/vm/prims/methodHandles.cpp Fri Sep 09 16:17:16 2011 -0700 150.3 @@ -158,6 +158,8 @@ 150.4 "adapter_fold/4/ref", 150.5 "adapter_fold/5/ref", 150.6 150.7 + "adapter_opt_profiling", 150.8 + 150.9 NULL 150.10 }; 150.11 150.12 @@ -2653,6 +2655,11 @@ 150.13 // Finalize the conversion field. (Note that it is final to Java code.) 150.14 java_lang_invoke_AdapterMethodHandle::set_conversion(mh(), new_conversion); 150.15 150.16 + if (java_lang_invoke_CountingMethodHandle::is_instance(mh())) { 150.17 + assert(ek_orig == _adapter_retype_only, "only one handled"); 150.18 + ek_opt = _adapter_opt_profiling; 150.19 + } 150.20 + 150.21 // Done! 150.22 java_lang_invoke_MethodHandle::set_vmentry(mh(), entry(ek_opt)); 150.23 150.24 @@ -2905,8 +2912,12 @@ 150.25 return MethodHandles::stack_move_unit(); 150.26 case MethodHandles::GC_CONV_OP_IMPLEMENTED_MASK: 150.27 return MethodHandles::adapter_conversion_ops_supported_mask(); 150.28 - case MethodHandles::GC_OP_ROT_ARGS_DOWN_LIMIT_BIAS: 150.29 - return MethodHandles::OP_ROT_ARGS_DOWN_LIMIT_BIAS; 150.30 + case MethodHandles::GC_COUNT_GWT: 150.31 +#ifdef COMPILER2 150.32 + return true; 150.33 +#else 150.34 + return false; 150.35 +#endif 150.36 } 150.37 return 0; 150.38 }
151.1 --- a/src/share/vm/prims/methodHandles.hpp Thu Sep 08 16:59:27 2011 -0700 151.2 +++ b/src/share/vm/prims/methodHandles.hpp Fri Sep 09 16:17:16 2011 -0700 151.3 @@ -187,6 +187,8 @@ 151.4 _adapter_opt_fold_FIRST = _adapter_opt_fold_ref, 151.5 _adapter_opt_fold_LAST = _adapter_opt_fold_5_ref, 151.6 151.7 + _adapter_opt_profiling, 151.8 + 151.9 _EK_LIMIT, 151.10 _EK_FIRST = 0 151.11 }; 151.12 @@ -266,6 +268,8 @@ 151.13 return _adapter_fold_args; 151.14 if (ek >= _adapter_opt_return_FIRST && ek <= _adapter_opt_return_LAST) 151.15 return _adapter_opt_return_any; 151.16 + if (ek == _adapter_opt_profiling) 151.17 + return _adapter_retype_only; 151.18 assert(false, "oob"); 151.19 return _EK_LIMIT; 151.20 } 151.21 @@ -582,6 +586,7 @@ 151.22 GC_JVM_STACK_MOVE_UNIT = 1, 151.23 GC_CONV_OP_IMPLEMENTED_MASK = 2, 151.24 GC_OP_ROT_ARGS_DOWN_LIMIT_BIAS = 3, 151.25 + GC_COUNT_GWT = 4, 151.26 151.27 // format of result from getTarget / encode_target: 151.28 ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
152.1 --- a/src/share/vm/prims/unsafe.cpp Thu Sep 08 16:59:27 2011 -0700 152.2 +++ b/src/share/vm/prims/unsafe.cpp Fri Sep 09 16:17:16 2011 -0700 152.3 @@ -33,7 +33,6 @@ 152.4 #include "runtime/globals.hpp" 152.5 #include "runtime/interfaceSupport.hpp" 152.6 #include "runtime/reflection.hpp" 152.7 -#include "runtime/reflectionCompat.hpp" 152.8 #include "runtime/synchronizer.hpp" 152.9 #include "services/threadService.hpp" 152.10 #include "utilities/copy.hpp" 152.11 @@ -303,6 +302,19 @@ 152.12 UnsafeWrapper("Unsafe_SetObjectVolatile"); 152.13 oop x = JNIHandles::resolve(x_h); 152.14 oop p = JNIHandles::resolve(obj); 152.15 + // Catch VolatileCallSite.target stores (via 152.16 + // CallSite.setTargetVolatile) and check call site dependencies. 152.17 + if ((offset == java_lang_invoke_CallSite::target_offset_in_bytes()) && p->is_a(SystemDictionary::CallSite_klass())) { 152.18 + oop call_site = p; 152.19 + oop method_handle = x; 152.20 + assert(call_site ->is_a(SystemDictionary::CallSite_klass()), "must be"); 152.21 + assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "must be"); 152.22 + { 152.23 + // Walk all nmethods depending on this call site. 152.24 + MutexLocker mu(Compile_lock, thread); 152.25 + Universe::flush_dependents_on(call_site, method_handle); 152.26 + } 152.27 + } 152.28 void* addr = index_oop_from_field_offset_long(p, offset); 152.29 OrderAccess::release(); 152.30 if (UseCompressedOops) {
153.1 --- a/src/share/vm/runtime/arguments.cpp Thu Sep 08 16:59:27 2011 -0700 153.2 +++ b/src/share/vm/runtime/arguments.cpp Fri Sep 09 16:17:16 2011 -0700 153.3 @@ -1423,6 +1423,9 @@ 153.4 if (FLAG_IS_DEFAULT(MinHeapDeltaBytes)) { 153.5 FLAG_SET_DEFAULT(MinHeapDeltaBytes, 64*M); 153.6 } 153.7 + // For those collectors or operating systems (eg, Windows) that do 153.8 + // not support full UseNUMA, we will map to UseNUMAInterleaving for now 153.9 + UseNUMAInterleaving = true; 153.10 } 153.11 } 153.12
154.1 --- a/src/share/vm/runtime/globals.hpp Thu Sep 08 16:59:27 2011 -0700 154.2 +++ b/src/share/vm/runtime/globals.hpp Fri Sep 09 16:17:16 2011 -0700 154.3 @@ -475,6 +475,12 @@ 154.4 product(bool, UseNUMA, false, \ 154.5 "Use NUMA if available") \ 154.6 \ 154.7 + product(bool, UseNUMAInterleaving, false, \ 154.8 + "Interleave memory across NUMA nodes if available") \ 154.9 + \ 154.10 + product(uintx, NUMAInterleaveGranularity, 2*M, \ 154.11 + "Granularity to use for NUMA interleaving on Windows OS") \ 154.12 + \ 154.13 product(bool, ForceNUMA, false, \ 154.14 "Force NUMA optimizations on single-node/UMA systems") \ 154.15 \ 154.16 @@ -1979,6 +1985,18 @@ 154.17 product(bool, TLABStats, true, \ 154.18 "Print various TLAB related information") \ 154.19 \ 154.20 + product(bool, UseBlockZeroing, false, \ 154.21 + "Use special cpu instructions for block zeroing") \ 154.22 + \ 154.23 + product(intx, BlockZeroingLowLimit, 2048, \ 154.24 + "Minimum size in bytes when block zeroing will be used") \ 154.25 + \ 154.26 + product(bool, UseBlockCopy, false, \ 154.27 + "Use special cpu instructions for block copy") \ 154.28 + \ 154.29 + product(intx, BlockCopyLowLimit, 2048, \ 154.30 + "Minimum size in bytes when block copy will be used") \ 154.31 + \ 154.32 product(bool, PrintRevisitStats, false, \ 154.33 "Print revisit (klass and MDO) stack related information") \ 154.34 \ 154.35 @@ -2912,6 +2930,12 @@ 154.36 product(intx, ReadPrefetchInstr, 0, \ 154.37 "Prefetch instruction to prefetch ahead") \ 154.38 \ 154.39 + product(uintx, ArraycopySrcPrefetchDistance, 0, \ 154.40 + "Distance to prefetch source array in arracopy") \ 154.41 + \ 154.42 + product(uintx, ArraycopyDstPrefetchDistance, 0, \ 154.43 + "Distance to prefetch destination array in arracopy") \ 154.44 + \ 154.45 /* deoptimization */ \ 154.46 develop(bool, TraceDeoptimization, false, \ 154.47 "Trace deoptimization") \
155.1 --- a/src/share/vm/runtime/java.cpp Thu Sep 08 16:59:27 2011 -0700 155.2 +++ b/src/share/vm/runtime/java.cpp Fri Sep 09 16:17:16 2011 -0700 155.3 @@ -672,7 +672,8 @@ 155.4 _current = JDK_Version(major, minor, micro, info.update_version, 155.5 info.special_update_version, build, 155.6 info.thread_park_blocker == 1, 155.7 - info.post_vm_init_hook_enabled == 1); 155.8 + info.post_vm_init_hook_enabled == 1, 155.9 + info.pending_list_uses_discovered_field == 1); 155.10 } 155.11 } 155.12
156.1 --- a/src/share/vm/runtime/java.hpp Thu Sep 08 16:59:27 2011 -0700 156.2 +++ b/src/share/vm/runtime/java.hpp Fri Sep 09 16:17:16 2011 -0700 156.3 @@ -92,6 +92,7 @@ 156.4 bool _partially_initialized; 156.5 156.6 bool _thread_park_blocker; 156.7 + bool _pending_list_uses_discovered_field; 156.8 bool _post_vm_init_hook_enabled; 156.9 156.10 bool is_valid() const { 156.11 @@ -114,15 +115,18 @@ 156.12 156.13 JDK_Version() : _major(0), _minor(0), _micro(0), _update(0), 156.14 _special(0), _build(0), _partially_initialized(false), 156.15 - _thread_park_blocker(false), _post_vm_init_hook_enabled(false) {} 156.16 + _thread_park_blocker(false), _post_vm_init_hook_enabled(false), 156.17 + _pending_list_uses_discovered_field(false) {} 156.18 156.19 JDK_Version(uint8_t major, uint8_t minor = 0, uint8_t micro = 0, 156.20 uint8_t update = 0, uint8_t special = 0, uint8_t build = 0, 156.21 - bool thread_park_blocker = false, bool post_vm_init_hook_enabled = false) : 156.22 + bool thread_park_blocker = false, bool post_vm_init_hook_enabled = false, 156.23 + bool pending_list_uses_discovered_field = false) : 156.24 _major(major), _minor(minor), _micro(micro), _update(update), 156.25 _special(special), _build(build), _partially_initialized(false), 156.26 _thread_park_blocker(thread_park_blocker), 156.27 - _post_vm_init_hook_enabled(post_vm_init_hook_enabled) {} 156.28 + _post_vm_init_hook_enabled(post_vm_init_hook_enabled), 156.29 + _pending_list_uses_discovered_field(pending_list_uses_discovered_field) {} 156.30 156.31 // Returns the current running JDK version 156.32 static JDK_Version current() { return _current; } 156.33 @@ -149,6 +153,10 @@ 156.34 bool post_vm_init_hook_enabled() const { 156.35 return _post_vm_init_hook_enabled; 156.36 } 156.37 + // For compatibility wrt pre-4965777 JDK's 156.38 + bool pending_list_uses_discovered_field() const { 156.39 + return _pending_list_uses_discovered_field; 156.40 + } 156.41 156.42 // Performs a full ordering comparison using all fields (update, build, etc.) 156.43 int compare(const JDK_Version& other) const;
157.1 --- a/src/share/vm/runtime/reflection.cpp Thu Sep 08 16:59:27 2011 -0700 157.2 +++ b/src/share/vm/runtime/reflection.cpp Fri Sep 09 16:17:16 2011 -0700 157.3 @@ -844,16 +844,6 @@ 157.4 } 157.5 157.6 157.7 -//--------------------------------------------------------------------------- 157.8 -// 157.9 -// Supporting routines for old native code-based reflection (pre-JDK 1.4). 157.10 -// 157.11 -// See reflection.hpp for details. 157.12 -// 157.13 -//--------------------------------------------------------------------------- 157.14 - 157.15 -#ifdef SUPPORT_OLD_REFLECTION 157.16 - 157.17 methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, methodHandle method, 157.18 KlassHandle recv_klass, Handle receiver, TRAPS) { 157.19 assert(!method.is_null() , "method should not be null"); 157.20 @@ -1081,519 +1071,6 @@ 157.21 return java_lang_Class::primitive_type(basic_type_mirror); 157.22 } 157.23 157.24 - 157.25 -bool Reflection::match_parameter_types(methodHandle method, objArrayHandle types, int parameter_count, TRAPS) { 157.26 - int types_len = types.is_null() ? 0 : types->length(); 157.27 - if (types_len != parameter_count) return false; 157.28 - if (parameter_count > 0) { 157.29 - objArrayHandle method_types = get_parameter_types(method, parameter_count, NULL, CHECK_false); 157.30 - for (int index = 0; index < parameter_count; index++) { 157.31 - if (types->obj_at(index) != method_types->obj_at(index)) { 157.32 - return false; 157.33 - } 157.34 - } 157.35 - } 157.36 - return true; 157.37 -} 157.38 - 157.39 - 157.40 -oop Reflection::new_field(FieldStream* st, TRAPS) { 157.41 - Symbol* field_name = st->name(); 157.42 - Handle name = java_lang_String::create_from_symbol(field_name, CHECK_NULL); 157.43 - Symbol* signature = st->signature(); 157.44 - Handle type = new_type(signature, st->klass(), CHECK_NULL); 157.45 - Handle rh = java_lang_reflect_Field::create(CHECK_NULL); 157.46 - oop result = rh(); 157.47 - 157.48 - java_lang_reflect_Field::set_clazz(result, st->klass()->java_mirror()); 157.49 - java_lang_reflect_Field::set_slot(result, st->index()); 157.50 - java_lang_reflect_Field::set_name(result, name()); 157.51 - java_lang_reflect_Field::set_type(result, type()); 157.52 - // Note the ACC_ANNOTATION bit, which is a per-class access flag, is never set here. 157.53 - java_lang_reflect_Field::set_modifiers(result, st->access_flags().as_int() & JVM_RECOGNIZED_FIELD_MODIFIERS); 157.54 - java_lang_reflect_Field::set_override(result, false); 157.55 - return result; 157.56 -} 157.57 - 157.58 - 157.59 -bool Reflection::resolve_field(Handle field_mirror, Handle& receiver, fieldDescriptor* fd, bool check_final, TRAPS) { 157.60 - if (field_mirror.is_null()) { 157.61 - THROW_(vmSymbols::java_lang_NullPointerException(), false); 157.62 - } 157.63 - 157.64 - instanceKlassHandle klass (THREAD, java_lang_Class::as_klassOop(java_lang_reflect_Field::clazz(field_mirror()))); 157.65 - int slot = java_lang_reflect_Field::slot(field_mirror()); 157.66 - 157.67 - // Ensure klass is initialized 157.68 - klass->initialize(CHECK_false); 157.69 - fd->initialize(klass(), slot); 157.70 - 157.71 - bool is_static = fd->is_static(); 157.72 - KlassHandle receiver_klass; 157.73 - 157.74 - if (is_static) { 157.75 - receiver = KlassHandle(THREAD, klass()); 157.76 - receiver_klass = klass; 157.77 - } else { 157.78 - // Check object is a non-null instance of declaring class 157.79 - if (receiver.is_null()) { 157.80 - THROW_(vmSymbols::java_lang_NullPointerException(), false); 157.81 - } 157.82 - if (!receiver->is_a(klass())) { 157.83 - THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "object is not an instance of declaring class", false); 157.84 - } 157.85 - receiver_klass = KlassHandle(THREAD, receiver->klass()); 157.86 - } 157.87 - 157.88 - // Access checking (unless overridden by Field) 157.89 - if (!java_lang_reflect_Field::override(field_mirror())) { 157.90 - if (!(klass->is_public() && fd->is_public())) { 157.91 - bool access_check = reflect_check_access(klass(), fd->access_flags(), receiver_klass(), false, CHECK_false); 157.92 - if (!access_check) { 157.93 - return false; // exception 157.94 - } 157.95 - } 157.96 - } 157.97 - 157.98 - if (check_final && fd->is_final()) { 157.99 - // In 1.3 we always throw an error when attempting to set a final field. 157.100 - // In 1.2.x, this was allowed in the override bit was set by calling Field.setAccessible(true). 157.101 - // We currently maintain backwards compatibility. See bug 4250960. 157.102 - bool strict_final_check = !JDK_Version::is_jdk12x_version(); 157.103 - if (strict_final_check || !java_lang_reflect_Field::override(field_mirror())) { 157.104 - THROW_MSG_(vmSymbols::java_lang_IllegalAccessException(), "field is final", false); 157.105 - } 157.106 - } 157.107 - return true; 157.108 -} 157.109 - 157.110 - 157.111 -BasicType Reflection::field_get(jvalue* value, fieldDescriptor* fd, Handle receiver) { 157.112 - BasicType field_type = fd->field_type(); 157.113 - int offset = fd->offset(); 157.114 - switch (field_type) { 157.115 - case T_BOOLEAN: 157.116 - value->z = receiver->bool_field(offset); 157.117 - break; 157.118 - case T_CHAR: 157.119 - value->c = receiver->char_field(offset); 157.120 - break; 157.121 - case T_FLOAT: 157.122 - value->f = receiver->float_field(offset); 157.123 - break; 157.124 - case T_DOUBLE: 157.125 - value->d = receiver->double_field(offset); 157.126 - break; 157.127 - case T_BYTE: 157.128 - value->b = receiver->byte_field(offset); 157.129 - break; 157.130 - case T_SHORT: 157.131 - value->s = receiver->short_field(offset); 157.132 - break; 157.133 - case T_INT: 157.134 - value->i = receiver->int_field(offset); 157.135 - break; 157.136 - case T_LONG: 157.137 - value->j = receiver->long_field(offset); 157.138 - break; 157.139 - case T_OBJECT: 157.140 - case T_ARRAY: 157.141 - value->l = (jobject) receiver->obj_field(offset); 157.142 - break; 157.143 - default: 157.144 - return T_ILLEGAL; 157.145 - } 157.146 - return field_type; 157.147 -} 157.148 - 157.149 - 157.150 -void Reflection::field_set(jvalue* value, fieldDescriptor* fd, Handle receiver, BasicType value_type, TRAPS) { 157.151 - BasicType field_type = fd->field_type(); 157.152 - if (field_type != value_type) { 157.153 - widen(value, value_type, field_type, CHECK); 157.154 - } 157.155 - 157.156 - int offset = fd->offset(); 157.157 - switch (field_type) { 157.158 - case T_BOOLEAN: 157.159 - receiver->bool_field_put(offset, value->z); 157.160 - break; 157.161 - case T_CHAR: 157.162 - receiver->char_field_put(offset, value->c); 157.163 - break; 157.164 - case T_FLOAT: 157.165 - receiver->float_field_put(offset, value->f); 157.166 - break; 157.167 - case T_DOUBLE: 157.168 - receiver->double_field_put(offset, value->d); 157.169 - break; 157.170 - case T_BYTE: 157.171 - receiver->byte_field_put(offset, value->b); 157.172 - break; 157.173 - case T_SHORT: 157.174 - receiver->short_field_put(offset, value->s); 157.175 - break; 157.176 - case T_INT: 157.177 - receiver->int_field_put(offset, value->i); 157.178 - break; 157.179 - case T_LONG: 157.180 - receiver->long_field_put(offset, value->j); 157.181 - break; 157.182 - case T_OBJECT: 157.183 - case T_ARRAY: { 157.184 - Handle obj(THREAD, (oop) value->l); 157.185 - if (obj.not_null()) { 157.186 - Symbol* signature = fd->signature(); 157.187 - Handle loader (THREAD, fd->loader()); 157.188 - Handle protect (THREAD, Klass::cast(fd->field_holder())->protection_domain()); 157.189 - klassOop k = SystemDictionary::resolve_or_fail(signature, loader, protect, true, CHECK); // may block 157.190 - if (!obj->is_a(k)) { 157.191 - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "field type mismatch"); 157.192 - } 157.193 - } 157.194 - receiver->obj_field_put(offset, obj()); 157.195 - break; 157.196 - } 157.197 - default: 157.198 - THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "field type mismatch"); 157.199 - } 157.200 -} 157.201 - 157.202 - 157.203 -oop Reflection::reflect_field(oop mirror, Symbol* field_name, jint which, TRAPS) { 157.204 - // Exclude primitive types and array types 157.205 - if (java_lang_Class::is_primitive(mirror)) return NULL; 157.206 - if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) return NULL; 157.207 - 157.208 - instanceKlassHandle k(THREAD, java_lang_Class::as_klassOop(mirror)); 157.209 - bool local_fields_only = (which == DECLARED); 157.210 - 157.211 - // Ensure class is linked 157.212 - k->link_class(CHECK_NULL); 157.213 - 157.214 - // Search class and interface fields 157.215 - for (FieldStream st(k, local_fields_only, false); !st.eos(); st.next()) { 157.216 - if (st.name() == field_name) { 157.217 - if (local_fields_only || st.access_flags().is_public()) { 157.218 - return new_field(&st, THREAD); 157.219 - } 157.220 - } 157.221 - } 157.222 - 157.223 - return NULL; 157.224 -} 157.225 - 157.226 - 157.227 -objArrayOop Reflection::reflect_fields(oop mirror, jint which, TRAPS) { 157.228 - // Exclude primitive types and array types 157.229 - if (java_lang_Class::is_primitive(mirror) 157.230 - || Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) { 157.231 - Symbol* name = vmSymbols::java_lang_reflect_Field(); 157.232 - klassOop klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL); 157.233 - return oopFactory::new_objArray(klass, 0, CHECK_NULL); // Return empty array 157.234 - } 157.235 - 157.236 - instanceKlassHandle k(THREAD, java_lang_Class::as_klassOop(mirror)); 157.237 - 157.238 - // Ensure class is linked 157.239 - k->link_class(CHECK_NULL); 157.240 - 157.241 - bool local_fields_only = (which == DECLARED); 157.242 - int count = 0; 157.243 - { // Compute fields count for class and interface fields 157.244 - for (FieldStream st(k, local_fields_only, false); !st.eos(); st.next()) { 157.245 - if (local_fields_only || st.access_flags().is_public()) { 157.246 - count++; 157.247 - } 157.248 - } 157.249 - } 157.250 - 157.251 - // Allocate result 157.252 - Symbol* name = vmSymbols::java_lang_reflect_Field(); 157.253 - klassOop klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL); 157.254 - objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); 157.255 - objArrayHandle result (THREAD, r); 157.256 - 157.257 - // Fill in results backwards 157.258 - { 157.259 - for (FieldStream st(k, local_fields_only, false); !st.eos(); st.next()) { 157.260 - if (local_fields_only || st.access_flags().is_public()) { 157.261 - oop field = new_field(&st, CHECK_NULL); 157.262 - result->obj_at_put(--count, field); 157.263 - } 157.264 - } 157.265 - assert(count == 0, "just checking"); 157.266 - } 157.267 - return result(); 157.268 -} 157.269 - 157.270 - 157.271 -oop Reflection::reflect_method(oop mirror, Symbol* method_name, objArrayHandle types, jint which, TRAPS) { 157.272 - if (java_lang_Class::is_primitive(mirror)) return NULL; 157.273 - klassOop klass = java_lang_Class::as_klassOop(mirror); 157.274 - if (Klass::cast(klass)->oop_is_array() && which == MEMBER_DECLARED) return NULL; 157.275 - 157.276 - if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) { 157.277 - klass = SystemDictionary::Object_klass(); 157.278 - } 157.279 - instanceKlassHandle h_k(THREAD, klass); 157.280 - 157.281 - // Ensure klass is linked (need not be initialized) 157.282 - h_k->link_class(CHECK_NULL); 157.283 - 157.284 - // For interfaces include static initializers under jdk1.2.x (since classic does that) 157.285 - bool include_clinit = JDK_Version::is_jdk12x_version() && h_k->is_interface(); 157.286 - 157.287 - switch (which) { 157.288 - case MEMBER_PUBLIC: 157.289 - // First the public non-static methods (works if method holder is an interface) 157.290 - // Note that we can ignore checks for overridden methods, since we go up the hierarchy. 157.291 - { 157.292 - for (MethodStream st(h_k, false, false); !st.eos(); st.next()) { 157.293 - methodHandle m(THREAD, st.method()); 157.294 - // For interfaces include static initializers since classic does that! 157.295 - if (method_name == m->name() && (include_clinit || (m->is_public() && !m->is_static() && !m->is_initializer()))) { 157.296 - Symbol* signature = m->signature(); 157.297 - bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL); 157.298 - if (parameter_match) { 157.299 - return new_method(m, false, false, THREAD); 157.300 - } 157.301 - } 157.302 - } 157.303 - } 157.304 - // Then the public static methods (works if method holder is an interface) 157.305 - { 157.306 - for (MethodStream st(h_k, false, false); !st.eos(); st.next()) { 157.307 - methodHandle m(THREAD, st.method()); 157.308 - if (method_name == m->name() && m->is_public() && m->is_static() && !m->is_initializer()) { 157.309 - Symbol* signature = m->signature(); 157.310 - bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL); 157.311 - if (parameter_match) { 157.312 - return new_method(m, false, false, THREAD); 157.313 - } 157.314 - } 157.315 - } 157.316 - } 157.317 - break; 157.318 - case MEMBER_DECLARED: 157.319 - // All local methods 157.320 - { 157.321 - for (MethodStream st(h_k, true, true); !st.eos(); st.next()) { 157.322 - methodHandle m(THREAD, st.method()); 157.323 - if (method_name == m->name() && !m->is_initializer()) { 157.324 - Symbol* signature = m->signature(); 157.325 - bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL); 157.326 - if (parameter_match) { 157.327 - return new_method(m, false, false, THREAD); 157.328 - } 157.329 - } 157.330 - } 157.331 - } 157.332 - break; 157.333 - default: 157.334 - break; 157.335 - } 157.336 - return NULL; 157.337 -} 157.338 - 157.339 - 157.340 -objArrayOop Reflection::reflect_methods(oop mirror, jint which, TRAPS) { 157.341 - // Exclude primitive types 157.342 - if (java_lang_Class::is_primitive(mirror) || 157.343 - (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array() && (which == MEMBER_DECLARED))) { 157.344 - klassOop klass = SystemDictionary::reflect_Method_klass(); 157.345 - return oopFactory::new_objArray(klass, 0, CHECK_NULL); // Return empty array 157.346 - } 157.347 - 157.348 - klassOop klass = java_lang_Class::as_klassOop(mirror); 157.349 - if (Klass::cast(java_lang_Class::as_klassOop(mirror))->oop_is_array()) { 157.350 - klass = SystemDictionary::Object_klass(); 157.351 - } 157.352 - instanceKlassHandle h_k(THREAD, klass); 157.353 - 157.354 - // Ensure klass is linked (need not be initialized) 157.355 - h_k->link_class(CHECK_NULL); 157.356 - 157.357 - // We search the (super)interfaces only if h_k is an interface itself 157.358 - bool is_interface = h_k->is_interface(); 157.359 - 157.360 - // For interfaces include static initializers under jdk1.2.x (since classic does that) 157.361 - bool include_clinit = JDK_Version::is_jdk12x_version() && is_interface; 157.362 - 157.363 - switch (which) { 157.364 - case MEMBER_PUBLIC: 157.365 - { 157.366 - 157.367 - // Count public methods (non-static and static) 157.368 - int count = 0; 157.369 - { 157.370 - for (MethodStream st(h_k, false, false); !st.eos(); st.next()) { 157.371 - methodOop m = st.method(); 157.372 - // For interfaces include static initializers since classic does that! 157.373 - if (include_clinit || (!m->is_initializer() && m->is_public() && !m->is_overridden_in(h_k()))) { 157.374 - count++; 157.375 - } 157.376 - } 157.377 - } 157.378 - 157.379 - // Allocate result 157.380 - klassOop klass = SystemDictionary::reflect_Method_klass(); 157.381 - objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); 157.382 - objArrayHandle h_result (THREAD, r); 157.383 - 157.384 - // Fill in results backwards 157.385 - { 157.386 - // First the non-static public methods 157.387 - for (MethodStream st(h_k, false, false); !st.eos(); st.next()) { 157.388 - methodHandle m (THREAD, st.method()); 157.389 - if (!m->is_static() && !m->is_initializer() && m->is_public() && !m->is_overridden_in(h_k())) { 157.390 - oop method = new_method(m, false, false, CHECK_NULL); 157.391 - if (method == NULL) { 157.392 - return NULL; 157.393 - } else { 157.394 - h_result->obj_at_put(--count, method); 157.395 - } 157.396 - } 157.397 - } 157.398 - } 157.399 - { 157.400 - // Then the static public methods 157.401 - for (MethodStream st(h_k, false, !is_interface); !st.eos(); st.next()) { 157.402 - methodHandle m (THREAD, st.method()); 157.403 - if (m->is_static() && (include_clinit || (!m->is_initializer()) && m->is_public() && !m->is_overridden_in(h_k()))) { 157.404 - oop method = new_method(m, false, false, CHECK_NULL); 157.405 - if (method == NULL) { 157.406 - return NULL; 157.407 - } else { 157.408 - h_result->obj_at_put(--count, method); 157.409 - } 157.410 - } 157.411 - } 157.412 - } 157.413 - 157.414 - assert(count == 0, "just checking"); 157.415 - return h_result(); 157.416 - } 157.417 - 157.418 - case MEMBER_DECLARED: 157.419 - { 157.420 - // Count all methods 157.421 - int count = 0; 157.422 - { 157.423 - for (MethodStream st(h_k, true, !is_interface); !st.eos(); st.next()) { 157.424 - methodOop m = st.method(); 157.425 - if (!m->is_initializer()) { 157.426 - count++; 157.427 - } 157.428 - } 157.429 - } 157.430 - // Allocate result 157.431 - klassOop klass = SystemDictionary::reflect_Method_klass(); 157.432 - objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); 157.433 - objArrayHandle h_result (THREAD, r); 157.434 - 157.435 - // Fill in results backwards 157.436 - { 157.437 - for (MethodStream st(h_k, true, true); !st.eos(); st.next()) { 157.438 - methodHandle m (THREAD, st.method()); 157.439 - if (!m->is_initializer()) { 157.440 - oop method = new_method(m, false, false, CHECK_NULL); 157.441 - if (method == NULL) { 157.442 - return NULL; 157.443 - } else { 157.444 - h_result->obj_at_put(--count, method); 157.445 - } 157.446 - } 157.447 - } 157.448 - } 157.449 - assert(count == 0, "just checking"); 157.450 - return h_result(); 157.451 - } 157.452 - } 157.453 - ShouldNotReachHere(); 157.454 - return NULL; 157.455 -} 157.456 - 157.457 - 157.458 -oop Reflection::reflect_constructor(oop mirror, objArrayHandle types, jint which, TRAPS) { 157.459 - 157.460 - // Exclude primitive, interface and array types 157.461 - bool prim = java_lang_Class::is_primitive(mirror); 157.462 - Klass* klass = prim ? NULL : Klass::cast(java_lang_Class::as_klassOop(mirror)); 157.463 - if (prim || klass->is_interface() || klass->oop_is_array()) return NULL; 157.464 - 157.465 - // Must be instance klass 157.466 - instanceKlassHandle h_k(THREAD, java_lang_Class::as_klassOop(mirror)); 157.467 - 157.468 - // Ensure klass is linked (need not be initialized) 157.469 - h_k->link_class(CHECK_NULL); 157.470 - 157.471 - bool local_only = (which == MEMBER_DECLARED); 157.472 - for (MethodStream st(h_k, true, true); !st.eos(); st.next()) { 157.473 - methodHandle m(THREAD, st.method()); 157.474 - if (m->name() == vmSymbols::object_initializer_name() && (local_only || m->is_public())) { 157.475 - Symbol* signature = m->signature(); 157.476 - bool parameter_match = match_parameter_types(m, types, ArgumentCount(signature).size(), CHECK_NULL); 157.477 - if (parameter_match) { 157.478 - return new_constructor(m, THREAD); 157.479 - } 157.480 - } 157.481 - } 157.482 - 157.483 - return NULL; 157.484 -} 157.485 - 157.486 - 157.487 -objArrayOop Reflection::reflect_constructors(oop mirror, jint which, TRAPS) { 157.488 - // Exclude primitive, interface and array types 157.489 - bool prim = java_lang_Class::is_primitive(mirror); 157.490 - Klass* k = prim ? NULL : Klass::cast(java_lang_Class::as_klassOop(mirror)); 157.491 - if (prim || k->is_interface() || k->oop_is_array()) { 157.492 - return oopFactory::new_objArray(SystemDictionary::reflect_Constructor_klass(), 0, CHECK_NULL); // Return empty array 157.493 - } 157.494 - 157.495 - // Must be instanceKlass at this point 157.496 - instanceKlassHandle h_k(THREAD, java_lang_Class::as_klassOop(mirror)); 157.497 - 157.498 - // Ensure klass is linked (need not be initialized) 157.499 - h_k->link_class(CHECK_NULL); 157.500 - 157.501 - bool local_only = (which == MEMBER_DECLARED); 157.502 - int count = 0; 157.503 - { 157.504 - for (MethodStream st(h_k, true, true); !st.eos(); st.next()) { 157.505 - methodOop m = st.method(); 157.506 - if (m->name() == vmSymbols::object_initializer_name() && (local_only || m->is_public())) { 157.507 - count++; 157.508 - } 157.509 - } 157.510 - } 157.511 - 157.512 - // Allocate result 157.513 - Symbol* name = vmSymbols::java_lang_reflect_Constructor(); 157.514 - klassOop klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL); 157.515 - objArrayOop r = oopFactory::new_objArray(klass, count, CHECK_NULL); 157.516 - objArrayHandle h_result (THREAD, r); 157.517 - 157.518 - // Fill in results backwards 157.519 - { 157.520 - for (MethodStream st(h_k, true, true); !st.eos(); st.next()) { 157.521 - methodHandle m (THREAD, st.method()); 157.522 - if (m->name() == vmSymbols::object_initializer_name() && (local_only || m->is_public())) { 157.523 - oop constr = new_constructor(m, CHECK_NULL); 157.524 - if (constr == NULL) { 157.525 - return NULL; 157.526 - } else { 157.527 - h_result->obj_at_put(--count, constr); 157.528 - } 157.529 - } 157.530 - } 157.531 - assert(count == 0, "just checking"); 157.532 - } 157.533 - return h_result(); 157.534 -} 157.535 - 157.536 - 157.537 // This would be nicer if, say, java.lang.reflect.Method was a subclass 157.538 // of java.lang.reflect.Constructor 157.539 157.540 @@ -1647,6 +1124,3 @@ 157.541 invoke(klass, method, receiver, override, ptypes, T_VOID, args, false, CHECK_NULL); 157.542 return receiver(); 157.543 } 157.544 - 157.545 - 157.546 -#endif /* SUPPORT_OLD_REFLECTION */
158.1 --- a/src/share/vm/runtime/reflection.hpp Thu Sep 08 16:59:27 2011 -0700 158.2 +++ b/src/share/vm/runtime/reflection.hpp Fri Sep 09 16:17:16 2011 -0700 158.3 @@ -27,7 +27,6 @@ 158.4 158.5 #include "oops/oop.hpp" 158.6 #include "runtime/fieldDescriptor.hpp" 158.7 -#include "runtime/reflectionCompat.hpp" 158.8 #include "utilities/accessFlags.hpp" 158.9 #include "utilities/growableArray.hpp" 158.10 158.11 @@ -120,16 +119,6 @@ 158.12 // Create a java.lang.reflect.Field object based on a field descriptor 158.13 static oop new_field(fieldDescriptor* fd, bool intern_name, TRAPS); 158.14 158.15 - //--------------------------------------------------------------------------- 158.16 - // 158.17 - // Support for old native code-based reflection (pre-JDK 1.4) 158.18 - // 158.19 - // NOTE: the method and constructor invocation code is still used 158.20 - // for startup time reasons; see reflectionCompat.hpp. 158.21 - // 158.22 - //--------------------------------------------------------------------------- 158.23 - 158.24 -#ifdef SUPPORT_OLD_REFLECTION 158.25 private: 158.26 // method resolution for invoke 158.27 static methodHandle resolve_interface_call(instanceKlassHandle klass, methodHandle method, KlassHandle recv_klass, Handle receiver, TRAPS); 158.28 @@ -144,35 +133,11 @@ 158.29 // Conversion 158.30 static BasicType basic_type_mirror_to_basic_type(oop basic_type_mirror, TRAPS); 158.31 158.32 - static bool match_parameter_types(methodHandle method, objArrayHandle types, int parameter_count, TRAPS); 158.33 - // Creating new java.lang.reflect.xxx wrappers 158.34 - static oop new_field(FieldStream* st, TRAPS); 158.35 - 158.36 public: 158.37 - // Field lookup and verification. 158.38 - static bool resolve_field(Handle field_mirror, Handle& receiver, fieldDescriptor* fd, bool check_final, TRAPS); 158.39 - 158.40 - // Reflective field access. Returns type code. Throws IllegalArgumentException. 158.41 - static BasicType field_get(jvalue* value, fieldDescriptor* fd, Handle receiver); 158.42 - static void field_set(jvalue* value, fieldDescriptor* fd, Handle receiver, BasicType value_type, TRAPS); 158.43 - 158.44 - // Reflective lookup of fields. Returns java.lang.reflect.Field instances. 158.45 - static oop reflect_field(oop mirror, Symbol* field_name, jint which, TRAPS); 158.46 - static objArrayOop reflect_fields(oop mirror, jint which, TRAPS); 158.47 - 158.48 - // Reflective lookup of methods. Returns java.lang.reflect.Method instances. 158.49 - static oop reflect_method(oop mirror, Symbol* method_name, objArrayHandle types, jint which, TRAPS); 158.50 - static objArrayOop reflect_methods(oop mirror, jint which, TRAPS); 158.51 - 158.52 - // Reflective lookup of constructors. Returns java.lang.reflect.Constructor instances. 158.53 - static oop reflect_constructor(oop mirror, objArrayHandle types, jint which, TRAPS); 158.54 - static objArrayOop reflect_constructors(oop mirror, jint which, TRAPS); 158.55 - 158.56 // Method invokation through java.lang.reflect.Method 158.57 static oop invoke_method(oop method_mirror, Handle receiver, objArrayHandle args, TRAPS); 158.58 // Method invokation through java.lang.reflect.Constructor 158.59 static oop invoke_constructor(oop method_mirror, objArrayHandle args, TRAPS); 158.60 -#endif /* SUPPORT_OLD_REFLECTION */ 158.61 158.62 }; 158.63
159.1 --- a/src/share/vm/runtime/reflectionCompat.hpp Thu Sep 08 16:59:27 2011 -0700 159.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 159.3 @@ -1,47 +0,0 @@ 159.4 -/* 159.5 - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 159.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 159.7 - * 159.8 - * This code is free software; you can redistribute it and/or modify it 159.9 - * under the terms of the GNU General Public License version 2 only, as 159.10 - * published by the Free Software Foundation. 159.11 - * 159.12 - * This code is distributed in the hope that it will be useful, but WITHOUT 159.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 159.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 159.15 - * version 2 for more details (a copy is included in the LICENSE file that 159.16 - * accompanied this code). 159.17 - * 159.18 - * You should have received a copy of the GNU General Public License version 159.19 - * 2 along with this work; if not, write to the Free Software Foundation, 159.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 159.21 - * 159.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 159.23 - * or visit www.oracle.com if you need additional information or have any 159.24 - * questions. 159.25 - * 159.26 - */ 159.27 - 159.28 -#ifndef SHARE_VM_RUNTIME_REFLECTIONCOMPAT_HPP 159.29 -#define SHARE_VM_RUNTIME_REFLECTIONCOMPAT_HPP 159.30 - 159.31 -// During the development of the JDK 1.4 reflection implementation 159.32 -// based on dynamic bytecode generation, it was hoped that the bulk of 159.33 -// the native code for reflection could be removed. Unfortunately 159.34 -// there is currently a significant cost associated with loading the 159.35 -// stub classes which impacts startup time. Until this cost can be 159.36 -// reduced, the JVM entry points JVM_InvokeMethod and 159.37 -// JVM_NewInstanceFromConstructor are still needed; these and their 159.38 -// dependents currently constitute the bulk of the native code for 159.39 -// reflection. If this cost is reduced in the future, the 159.40 -// NativeMethodAccessorImpl and NativeConstructorAccessorImpl classes 159.41 -// can be removed from sun.reflect and all of the code guarded by this 159.42 -// flag removed from the product build. (Non-product builds, 159.43 -// specifically the "optimized" target, would retain the code so they 159.44 -// could be dropped into earlier JDKs for comparative benchmarking.) 159.45 - 159.46 -//#ifndef PRODUCT 159.47 -# define SUPPORT_OLD_REFLECTION 159.48 -//#endif 159.49 - 159.50 -#endif // SHARE_VM_RUNTIME_REFLECTIONCOMPAT_HPP
160.1 --- a/src/share/vm/runtime/sharedRuntime.hpp Thu Sep 08 16:59:27 2011 -0700 160.2 +++ b/src/share/vm/runtime/sharedRuntime.hpp Fri Sep 09 16:17:16 2011 -0700 160.3 @@ -45,6 +45,8 @@ 160.4 // information, etc. 160.5 160.6 class SharedRuntime: AllStatic { 160.7 + friend class VMStructs; 160.8 + 160.9 private: 160.10 static methodHandle resolve_sub_helper(JavaThread *thread, 160.11 bool is_virtual,
161.1 --- a/src/share/vm/runtime/stubRoutines.cpp Thu Sep 08 16:59:27 2011 -0700 161.2 +++ b/src/share/vm/runtime/stubRoutines.cpp Fri Sep 09 16:17:16 2011 -0700 161.3 @@ -108,6 +108,7 @@ 161.4 address StubRoutines::_arrayof_oop_disjoint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy); 161.5 address StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy_uninit); 161.6 161.7 +address StubRoutines::_zero_aligned_words = CAST_FROM_FN_PTR(address, Copy::zero_to_words); 161.8 161.9 address StubRoutines::_checkcast_arraycopy = NULL; 161.10 address StubRoutines::_checkcast_arraycopy_uninit = NULL;
162.1 --- a/src/share/vm/runtime/stubRoutines.hpp Thu Sep 08 16:59:27 2011 -0700 162.2 +++ b/src/share/vm/runtime/stubRoutines.hpp Fri Sep 09 16:17:16 2011 -0700 162.3 @@ -199,6 +199,9 @@ 162.4 static address _arrayof_jshort_fill; 162.5 static address _arrayof_jint_fill; 162.6 162.7 + // zero heap space aligned to jlong (8 bytes) 162.8 + static address _zero_aligned_words; 162.9 + 162.10 // These are versions of the java.lang.Math methods which perform 162.11 // the same operations as the intrinsic version. They are used for 162.12 // constant folding in the compiler to ensure equivalence. If the 162.13 @@ -332,6 +335,7 @@ 162.14 162.15 static address select_fill_function(BasicType t, bool aligned, const char* &name); 162.16 162.17 + static address zero_aligned_words() { return _zero_aligned_words; } 162.18 162.19 static double intrinsic_log(double d) { 162.20 assert(_intrinsic_log != NULL, "must be defined");
163.1 --- a/src/share/vm/runtime/thread.cpp Thu Sep 08 16:59:27 2011 -0700 163.2 +++ b/src/share/vm/runtime/thread.cpp Fri Sep 09 16:17:16 2011 -0700 163.3 @@ -1272,7 +1272,6 @@ 163.4 _exception_oop = NULL; 163.5 _exception_pc = 0; 163.6 _exception_handler_pc = 0; 163.7 - _exception_stack_size = 0; 163.8 _is_method_handle_return = 0; 163.9 _jvmti_thread_state= NULL; 163.10 _should_post_on_exceptions_flag = JNI_FALSE; 163.11 @@ -2860,6 +2859,44 @@ 163.12 } 163.13 } 163.14 163.15 +class PrintAndVerifyOopClosure: public OopClosure { 163.16 + protected: 163.17 + template <class T> inline void do_oop_work(T* p) { 163.18 + oop obj = oopDesc::load_decode_heap_oop(p); 163.19 + if (obj == NULL) return; 163.20 + tty->print(INTPTR_FORMAT ": ", p); 163.21 + if (obj->is_oop_or_null()) { 163.22 + if (obj->is_objArray()) { 163.23 + tty->print_cr("valid objArray: " INTPTR_FORMAT, (oopDesc*) obj); 163.24 + } else { 163.25 + obj->print(); 163.26 + } 163.27 + } else { 163.28 + tty->print_cr("invalid oop: " INTPTR_FORMAT, (oopDesc*) obj); 163.29 + } 163.30 + tty->cr(); 163.31 + } 163.32 + public: 163.33 + virtual void do_oop(oop* p) { do_oop_work(p); } 163.34 + virtual void do_oop(narrowOop* p) { do_oop_work(p); } 163.35 +}; 163.36 + 163.37 + 163.38 +static void oops_print(frame* f, const RegisterMap *map) { 163.39 + PrintAndVerifyOopClosure print; 163.40 + f->print_value(); 163.41 + f->oops_do(&print, NULL, (RegisterMap*)map); 163.42 +} 163.43 + 163.44 +// Print our all the locations that contain oops and whether they are 163.45 +// valid or not. This useful when trying to find the oldest frame 163.46 +// where an oop has gone bad since the frame walk is from youngest to 163.47 +// oldest. 163.48 +void JavaThread::trace_oops() { 163.49 + tty->print_cr("[Trace oops]"); 163.50 + frames_do(oops_print); 163.51 +} 163.52 + 163.53 163.54 #ifdef ASSERT 163.55 // Print or validate the layout of stack frames
164.1 --- a/src/share/vm/runtime/thread.hpp Thu Sep 08 16:59:27 2011 -0700 164.2 +++ b/src/share/vm/runtime/thread.hpp Fri Sep 09 16:17:16 2011 -0700 164.3 @@ -841,7 +841,6 @@ 164.4 volatile oop _exception_oop; // Exception thrown in compiled code 164.5 volatile address _exception_pc; // PC where exception happened 164.6 volatile address _exception_handler_pc; // PC for handler of exception 164.7 - volatile int _exception_stack_size; // Size of frame where exception happened 164.8 volatile int _is_method_handle_return; // true (== 1) if the current exception PC is a MethodHandle call site. 164.9 164.10 // support for compilation 164.11 @@ -1182,7 +1181,6 @@ 164.12 164.13 // Exception handling for compiled methods 164.14 oop exception_oop() const { return _exception_oop; } 164.15 - int exception_stack_size() const { return _exception_stack_size; } 164.16 address exception_pc() const { return _exception_pc; } 164.17 address exception_handler_pc() const { return _exception_handler_pc; } 164.18 bool is_method_handle_return() const { return _is_method_handle_return == 1; } 164.19 @@ -1190,7 +1188,6 @@ 164.20 void set_exception_oop(oop o) { _exception_oop = o; } 164.21 void set_exception_pc(address a) { _exception_pc = a; } 164.22 void set_exception_handler_pc(address a) { _exception_handler_pc = a; } 164.23 - void set_exception_stack_size(int size) { _exception_stack_size = size; } 164.24 void set_is_method_handle_return(bool value) { _is_method_handle_return = value ? 1 : 0; } 164.25 164.26 // Stack overflow support 164.27 @@ -1264,7 +1261,6 @@ 164.28 static ByteSize exception_oop_offset() { return byte_offset_of(JavaThread, _exception_oop ); } 164.29 static ByteSize exception_pc_offset() { return byte_offset_of(JavaThread, _exception_pc ); } 164.30 static ByteSize exception_handler_pc_offset() { return byte_offset_of(JavaThread, _exception_handler_pc); } 164.31 - static ByteSize exception_stack_size_offset() { return byte_offset_of(JavaThread, _exception_stack_size); } 164.32 static ByteSize is_method_handle_return_offset() { return byte_offset_of(JavaThread, _is_method_handle_return); } 164.33 static ByteSize stack_guard_state_offset() { return byte_offset_of(JavaThread, _stack_guard_state ); } 164.34 static ByteSize suspend_flags_offset() { return byte_offset_of(JavaThread, _suspend_flags ); } 164.35 @@ -1379,6 +1375,7 @@ 164.36 void trace_stack() PRODUCT_RETURN; 164.37 void trace_stack_from(vframe* start_vf) PRODUCT_RETURN; 164.38 void trace_frames() PRODUCT_RETURN; 164.39 + void trace_oops() PRODUCT_RETURN; 164.40 164.41 // Print an annotated view of the stack frames 164.42 void print_frame_layout(int depth = 0, bool validate_only = false) NOT_DEBUG_RETURN;
165.1 --- a/src/share/vm/runtime/vmStructs.cpp Thu Sep 08 16:59:27 2011 -0700 165.2 +++ b/src/share/vm/runtime/vmStructs.cpp Fri Sep 09 16:17:16 2011 -0700 165.3 @@ -652,6 +652,7 @@ 165.4 static_field(SystemDictionary, WK_KLASS(ThreadGroup_klass), klassOop) \ 165.5 static_field(SystemDictionary, WK_KLASS(Properties_klass), klassOop) \ 165.6 static_field(SystemDictionary, WK_KLASS(StringBuffer_klass), klassOop) \ 165.7 + static_field(SystemDictionary, WK_KLASS(MethodHandle_klass), klassOop) \ 165.8 static_field(SystemDictionary, _box_klasses[0], klassOop) \ 165.9 static_field(SystemDictionary, _java_system_loader, oop) \ 165.10 \ 165.11 @@ -757,12 +758,19 @@ 165.12 nonstatic_field(PcDesc, _pc_offset, int) \ 165.13 nonstatic_field(PcDesc, _scope_decode_offset, int) \ 165.14 nonstatic_field(PcDesc, _obj_decode_offset, int) \ 165.15 - nonstatic_field(PcDesc, _flags, PcDesc::PcDescFlags) \ 165.16 + nonstatic_field(PcDesc, _flags, int) \ 165.17 \ 165.18 /***************************************************/ \ 165.19 /* CodeBlobs (NOTE: incomplete, but only a little) */ \ 165.20 /***************************************************/ \ 165.21 \ 165.22 + X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _sender_pc, address)) \ 165.23 + X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _exact_sender_sp, intptr_t*)) \ 165.24 + X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _sender_link, intptr_t*)) \ 165.25 + X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _saved_args_base, intptr_t*)) \ 165.26 + \ 165.27 + static_field(SharedRuntime, _ricochet_blob, RicochetBlob*) \ 165.28 + \ 165.29 nonstatic_field(CodeBlob, _name, const char*) \ 165.30 nonstatic_field(CodeBlob, _size, int) \ 165.31 nonstatic_field(CodeBlob, _header_size, int) \ 165.32 @@ -774,6 +782,8 @@ 165.33 nonstatic_field(CodeBlob, _frame_size, int) \ 165.34 nonstatic_field(CodeBlob, _oop_maps, OopMapSet*) \ 165.35 \ 165.36 + nonstatic_field(RuntimeStub, _caller_must_gc_arguments, bool) \ 165.37 + \ 165.38 /**************************************************/ \ 165.39 /* NMethods (NOTE: incomplete, but only a little) */ \ 165.40 /**************************************************/ \ 165.41 @@ -786,6 +796,7 @@ 165.42 nonstatic_field(nmethod, _state, unsigned char) \ 165.43 nonstatic_field(nmethod, _exception_offset, int) \ 165.44 nonstatic_field(nmethod, _deoptimize_offset, int) \ 165.45 + nonstatic_field(nmethod, _deoptimize_mh_offset, int) \ 165.46 nonstatic_field(nmethod, _orig_pc_offset, int) \ 165.47 nonstatic_field(nmethod, _stub_offset, int) \ 165.48 nonstatic_field(nmethod, _consts_offset, int) \ 165.49 @@ -804,6 +815,9 @@ 165.50 nonstatic_field(nmethod, _compile_id, int) \ 165.51 nonstatic_field(nmethod, _marked_for_deoptimization, bool) \ 165.52 \ 165.53 + nonstatic_field(RicochetBlob, _bounce_offset, int) \ 165.54 + nonstatic_field(RicochetBlob, _exception_offset, int) \ 165.55 + \ 165.56 /********************************/ \ 165.57 /* JavaCalls (NOTE: incomplete) */ \ 165.58 /********************************/ \ 165.59 @@ -1310,24 +1324,27 @@ 165.60 /* CodeBlob hierarchy (needed for run-time type information) */ \ 165.61 /*************************************************************/ \ 165.62 \ 165.63 + declare_toplevel_type(SharedRuntime) \ 165.64 + X86_ONLY(declare_toplevel_type(MethodHandles::RicochetFrame)) \ 165.65 + \ 165.66 declare_toplevel_type(CodeBlob) \ 165.67 - declare_type(BufferBlob, CodeBlob) \ 165.68 - declare_type(AdapterBlob, BufferBlob) \ 165.69 - declare_type(nmethod, CodeBlob) \ 165.70 - declare_type(RuntimeStub, CodeBlob) \ 165.71 - declare_type(SingletonBlob, CodeBlob) \ 165.72 - declare_type(SafepointBlob, SingletonBlob) \ 165.73 - declare_type(DeoptimizationBlob, SingletonBlob) \ 165.74 - declare_type(RicochetBlob, SingletonBlob) \ 165.75 - declare_c2_type(ExceptionBlob, SingletonBlob) \ 165.76 - declare_c2_type(UncommonTrapBlob, CodeBlob) \ 165.77 + declare_type(BufferBlob, CodeBlob) \ 165.78 + declare_type(AdapterBlob, BufferBlob) \ 165.79 + declare_type(MethodHandlesAdapterBlob, BufferBlob) \ 165.80 + declare_type(nmethod, CodeBlob) \ 165.81 + declare_type(RuntimeStub, CodeBlob) \ 165.82 + declare_type(SingletonBlob, CodeBlob) \ 165.83 + declare_type(SafepointBlob, SingletonBlob) \ 165.84 + declare_type(DeoptimizationBlob, SingletonBlob) \ 165.85 + declare_type(RicochetBlob, SingletonBlob) \ 165.86 + declare_c2_type(ExceptionBlob, SingletonBlob) \ 165.87 + declare_c2_type(UncommonTrapBlob, CodeBlob) \ 165.88 \ 165.89 /***************************************/ \ 165.90 /* PcDesc and other compiled code info */ \ 165.91 /***************************************/ \ 165.92 \ 165.93 declare_toplevel_type(PcDesc) \ 165.94 - declare_integer_type(PcDesc::PcDescFlags) \ 165.95 \ 165.96 /************************/ \ 165.97 /* OopMap and OopMapSet */ \ 165.98 @@ -1796,6 +1813,21 @@ 165.99 \ 165.100 declare_constant(ObjectSynchronizer::_BLOCKSIZE) \ 165.101 \ 165.102 + /**********************/ \ 165.103 + /* PcDesc */ \ 165.104 + /**********************/ \ 165.105 + \ 165.106 + declare_constant(PcDesc::PCDESC_reexecute) \ 165.107 + declare_constant(PcDesc::PCDESC_is_method_handle_invoke) \ 165.108 + declare_constant(PcDesc::PCDESC_return_oop) \ 165.109 + \ 165.110 + /**********************/ \ 165.111 + /* frame */ \ 165.112 + /**********************/ \ 165.113 + \ 165.114 + X86_ONLY(declare_constant(frame::entry_frame_call_wrapper_offset)) \ 165.115 + declare_constant(frame::pc_return_offset) \ 165.116 + \ 165.117 /********************************/ \ 165.118 /* Calling convention constants */ \ 165.119 /********************************/ \
166.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 166.2 +++ b/test/compiler/7082949/Test7082949.java Fri Sep 09 16:17:16 2011 -0700 166.3 @@ -0,0 +1,54 @@ 166.4 +/* 166.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 166.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 166.7 + * 166.8 + * This code is free software; you can redistribute it and/or modify it 166.9 + * under the terms of the GNU General Public License version 2 only, as 166.10 + * published by the Free Software Foundation. 166.11 + * 166.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 166.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 166.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 166.15 + * version 2 for more details (a copy is included in the LICENSE file that 166.16 + * accompanied this code). 166.17 + * 166.18 + * You should have received a copy of the GNU General Public License version 166.19 + * 2 along with this work; if not, write to the Free Software Foundation, 166.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 166.21 + * 166.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 166.23 + * or visit www.oracle.com if you need additional information or have any 166.24 + * questions. 166.25 + * 166.26 + */ 166.27 + 166.28 +/** 166.29 + * @test 166.30 + * @bug 7082949 166.31 + * @summary JSR 292: missing ResourceMark in methodOopDesc::make_invoke_method 166.32 + * 166.33 + * @run main Test7082949 166.34 + */ 166.35 + 166.36 +import java.lang.invoke.*; 166.37 +import static java.lang.invoke.MethodHandles.*; 166.38 +import static java.lang.invoke.MethodType.*; 166.39 + 166.40 +public class Test7082949 implements Runnable { 166.41 + public static void main(String... args) throws Throwable { 166.42 + new Thread(new Test7082949()).start(); 166.43 + } 166.44 + 166.45 + public static Test7082949 test() { 166.46 + return null; 166.47 + } 166.48 + 166.49 + public void run() { 166.50 + try { 166.51 + MethodHandle m1 = MethodHandles.lookup().findStatic(Test7082949.class, "test", methodType(Test7082949.class)); 166.52 + Test7082949 v = (Test7082949)m1.invokeExact(); 166.53 + } catch (Throwable t) { 166.54 + t.printStackTrace(); 166.55 + } 166.56 + } 166.57 +}