# HG changeset patch # User amurillo # Date 1353087400 28800 # Node ID cfc5309f03b7bd6c1567618b63cf1fc74c0f2a8f # Parent 4e3e685dbc9dd07bc45f58acd9419f99c9618eea# Parent 80e866b1d053531bfc644983b055296c2655a3e8 Merge diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/doc/c2replay.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/doc/c2replay.html Fri Nov 16 09:36:40 2012 -0800 @@ -0,0 +1,41 @@ + + + +C2 Replay + + + + +

C2 compiler replay

+

+The C2 compiler replay is a function to repeat the compiling process from a crashed java process in compiled method
+This function only exists in debug version of VM +

+

Usage

+
 
+First, use SA to attach to the core file, if suceeded, do
+       clhsdb>dumpreplaydata 
| -a | [> replay.txt] + create file replay.txt, address is address of Method, or nmethod(CodeBlob) + clhsdb>buildreplayjars [all | boot | app] + create files: + all: + app.jar, boot.jar + boot: + boot.jar + app: + app.jar + exit SA now. +Second, use the obtained replay text file, replay.txt and jar files, app.jar and boot.jar, using debug version of java + java -Xbootclasspath/p:boot.jar -cp app.jar -XX:ReplayDataFile= -XX:+ReplayCompiles .... + This will replay the compiling process. + + With ReplayCompiles, the replay will recompile all the methods in app.jar, and in boot.jar to emulate the process in java app. + +notes: + 1) Most time, we don't need the boot.jar which is the classes loaded from JDK. It will be only modified when an agent(JVMDI) is running and modifies the classes. + 2) If encounter error as "" not found, that means the SA is using a VMStructs which is different from the one with corefile. In this case, SA has a utility tool vmstructsdump which is located at agent/src/os//proc/ + + Use this tool to dump VM type library: + vmstructsdump libjvm.so > .db + + set env SA_TYPEDB=.db (refer different shell for set envs) diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/doc/clhsdb.html --- a/agent/doc/clhsdb.html Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/doc/clhsdb.html Fri Nov 16 09:36:40 2012 -0800 @@ -37,12 +37,19 @@ Available commands: assert true | false turn on/off asserts in SA code attach pid | exec core attach SA to a process or core + buildreplayjars [all | boot | app] build jars for replay, boot.jar for bootclasses, app.jar for application classes class name find a Java class from debuggee and print oop classes print all loaded Java classes with Klass* detach detach SA from current target dis address [ length ] disassemble (sparc/x86) specified number of instructions from given address + dissemble address disassemble nmethod + dumpcfg -a | id Dump the PhaseCFG for every compiler thread that has one live dumpclass { address | name } [ directory ] dump .class file for given Klass* or class name + dumpcodecache dump codecache contents dumpheap [ file ] dump heap in hprof binary format + dumpideal -a | id dump ideal graph like debug flag -XX:+PrintIdeal + dumpilt -a | id dump inline tree for C2 compilation + dumpreplaydata
| -a | [>replay.txt] dump replay data into a file echo [ true | false ] turn on/off command echo mode examine [ address/count ] | [ address,address] show contents of memory from given address field [ type [ name fieldtype isStatic offset address ] ] print info about a field of HotSpot type @@ -51,29 +58,35 @@ help [ command ] print help message for all commands or just given command history show command history. usual !command-number syntax works. inspect expression inspect a given oop + intConstant [ name [ value ] ] print out hotspot integer constant(s) jdis address show bytecode disassembly of a given Method* jhisto show Java heap histogram jseval script evaluate a given string as JavaScript code jsload file load and evaluate a JavaScript file jstack [-v] show Java stack trace of all Java threads. -v is verbose mode livenmethods show all live nmethods + longConstant [ name [ value ] ] print out hotspot long constant(s)s mem address [ length ] show contents of memory -- also shows closest ELF/COFF symbol if found pmap show Solaris pmap-like output print expression print given Klass*, Method* or arbitrary address printas type expression print given address as given HotSpot type. eg. print JavaThread <address> + printmdo -a | expression print method data oop printstatics [ type ] print static fields of given HotSpot type (or all types if none specified) pstack [-v] show mixed mode stack trace for all Java, non-Java threads. -v is verbose mode quit quit CLHSDB tool reattach detach and re-attach SA to current target + revptrs find liveness of oops scanoops start end [ type ] scan a Oop from given start to end address search [ heap | codecache | threads ] value search a value in heap or codecache or threads source filename load and execute CLHSDB commands from given file symbol name show address of a given ELF/COFF symbol sysprops show all Java System properties + thread id show thread of id threads show all Java threads tokenize ... type [ type [ name super isOop isInteger isUnsigned size ] ] show info. on HotSpot type universe print gc universe + vmstructsdump dump hotspot type library in text verbose true | false turn on/off verbose mode versioncheck [ true | false ] turn on/off debuggee VM version check whatis address print info about any arbitrary address @@ -114,5 +127,11 @@
+

C2 Compilation Replay

+

+When a java process crashes in compiled method, usually a core file is saved. +The C2 replay function can reproduce the compiling process in the core. +c2replay.html + diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/doc/index.html --- a/agent/doc/index.html Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/doc/index.html Fri Nov 16 09:36:40 2012 -0800 @@ -220,6 +220,12 @@ +

C2 Compilation Replay

+

+When a java process crashes in compiled method, usually a core file is saved. +The C2 replay function can reproduce the compiling process in the core. +c2replay.html +

Debugging transported core dumps

When a core dump is moved from the machine where it was produced to a diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/make/Makefile --- a/agent/make/Makefile Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/make/Makefile Fri Nov 16 09:36:40 2012 -0800 @@ -58,10 +58,8 @@ sun.jvm.hotspot.debugger.cdbg.basic.amd64 \ sun.jvm.hotspot.debugger.cdbg.basic.x86 \ sun.jvm.hotspot.debugger.dummy \ -sun.jvm.hotspot.debugger.ia64 \ sun.jvm.hotspot.debugger.linux \ sun.jvm.hotspot.debugger.linux.amd64 \ -sun.jvm.hotspot.debugger.linux.ia64 \ sun.jvm.hotspot.debugger.linux.x86 \ sun.jvm.hotspot.debugger.posix \ sun.jvm.hotspot.debugger.posix.elf \ @@ -77,7 +75,6 @@ sun.jvm.hotspot.debugger.win32.coff \ sun.jvm.hotspot.debugger.windbg \ sun.jvm.hotspot.debugger.windbg.amd64 \ -sun.jvm.hotspot.debugger.windbg.ia64 \ sun.jvm.hotspot.debugger.windbg.x86 \ sun.jvm.hotspot.debugger.x86 \ sun.jvm.hotspot.gc_implementation \ @@ -97,10 +94,8 @@ sun.jvm.hotspot.runtime.bsd \ sun.jvm.hotspot.runtime.bsd_amd64 \ sun.jvm.hotspot.runtime.bsd_x86 \ -sun.jvm.hotspot.runtime.ia64 \ sun.jvm.hotspot.runtime.linux \ sun.jvm.hotspot.runtime.linux_amd64 \ -sun.jvm.hotspot.runtime.linux_ia64 \ sun.jvm.hotspot.runtime.linux_sparc \ sun.jvm.hotspot.runtime.linux_x86 \ sun.jvm.hotspot.runtime.posix \ @@ -109,7 +104,6 @@ sun.jvm.hotspot.runtime.solaris_x86 \ sun.jvm.hotspot.runtime.sparc \ sun.jvm.hotspot.runtime.win32_amd64 \ -sun.jvm.hotspot.runtime.win32_ia64 \ sun.jvm.hotspot.runtime.win32_x86 \ sun.jvm.hotspot.runtime.x86 \ sun.jvm.hotspot.tools \ @@ -152,7 +146,6 @@ sun/jvm/hotspot/debugger/cdbg/basic/amd64/*.java \ sun/jvm/hotspot/debugger/cdbg/basic/x86/*.java \ sun/jvm/hotspot/debugger/dummy/*.java \ -sun/jvm/hotspot/debugger/ia64/*.java \ sun/jvm/hotspot/debugger/linux/*.java \ sun/jvm/hotspot/debugger/linux/x86/*.java \ sun/jvm/hotspot/debugger/posix/*.java \ @@ -168,7 +161,6 @@ sun/jvm/hotspot/debugger/sparc/*.java \ sun/jvm/hotspot/debugger/win32/coff/*.java \ sun/jvm/hotspot/debugger/windbg/*.java \ -sun/jvm/hotspot/debugger/windbg/ia64/*.java \ sun/jvm/hotspot/debugger/windbg/x86/*.java \ sun/jvm/hotspot/debugger/x86/*.java \ sun/jvm/hotspot/gc_implementation/g1/*.java \ @@ -186,10 +178,8 @@ sun/jvm/hotspot/runtime/bsd/*.java \ sun/jvm/hotspot/runtime/bsd_amd64/*.java \ sun/jvm/hotspot/runtime/bsd_x86/*.java \ -sun/jvm/hotspot/runtime/ia64/*.java \ sun/jvm/hotspot/runtime/linux/*.java \ sun/jvm/hotspot/runtime/linux_amd64/*.java \ -sun/jvm/hotspot/runtime/linux_ia64/*.java \ sun/jvm/hotspot/runtime/linux_sparc/*.java \ sun/jvm/hotspot/runtime/linux_x86/*.java \ sun/jvm/hotspot/runtime/posix/*.java \ @@ -198,7 +188,6 @@ sun/jvm/hotspot/runtime/solaris_x86/*.java \ sun/jvm/hotspot/runtime/sparc/*.java \ sun/jvm/hotspot/runtime/win32_amd64/*.java \ -sun/jvm/hotspot/runtime/win32_ia64/*.java \ sun/jvm/hotspot/runtime/win32_x86/*.java \ sun/jvm/hotspot/runtime/x86/*.java \ sun/jvm/hotspot/tools/*.java \ @@ -258,6 +247,7 @@ SA_PROPERTIES = $(OUTPUT_DIR)/sa.properties JAVAC = $(JDK_HOME)/bin/javac +JAVA = $(JDK_HOME)/bin/java JAVADOC = $(JDK_HOME)/bin/javadoc RMIC = $(JDK_HOME)/bin/rmic @@ -298,7 +288,7 @@ .PHONY: natives natives: - cd ../src/os/`java -classpath $(OUTPUT_DIR) sun.jvm.hotspot.utilities.PlatformInfo`; $(MAKE) all + cd ../src/os/`$(JAVA) -classpath $(OUTPUT_DIR) sun.jvm.hotspot.utilities.PlatformInfo`; $(MAKE) all .PHONY: sa-jdi.jar sa-jdi.jar: @@ -323,5 +313,5 @@ clean:: rm -rf filelist - cd ../src/os/`java -classpath $(OUTPUT_DIR) sun.jvm.hotspot.utilities.PlatformInfo`; $(MAKE) clean + cd ../src/os/`$(JAVA) -classpath $(OUTPUT_DIR) sun.jvm.hotspot.utilities.PlatformInfo`; $(MAKE) clean rm -rf $(BUILD_DIR)/* diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java --- a/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java Fri Nov 16 09:36:40 2012 -0800 @@ -33,6 +33,7 @@ import sun.jvm.hotspot.types.Field; import sun.jvm.hotspot.HotSpotTypeDataBase; import sun.jvm.hotspot.types.basic.BasicType; +import sun.jvm.hotspot.types.basic.BasicTypeDataBase; import sun.jvm.hotspot.types.CIntegerType; import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.compiler.*; @@ -448,6 +449,112 @@ } } }, + new Command("dumpreplaydata", "dumpreplaydata {

| -a | }", false) { + // This is used to dump replay data from ciInstanceKlass, ciMethodData etc + // default file name is replay.txt, also if java crashes in compiler + // thread, this file will be dumped in error processing. + public void doit(Tokens t) { + if (t.countTokens() != 1) { + usage(); + return; + } + String name = t.nextToken(); + Address a = null; + try { + a = VM.getVM().getDebugger().parseAddress(name); + } catch (NumberFormatException e) { } + if (a != null) { + // only nmethod, Method, MethodData and InstanceKlass needed to + // dump replay data + + CodeBlob cb = VM.getVM().getCodeCache().findBlob(a); + if (cb != null && (cb instanceof NMethod)) { + ((NMethod)cb).dumpReplayData(out); + return; + } + // assume it is Metadata + Metadata meta = Metadata.instantiateWrapperFor(a); + if (meta != null) { + meta.dumpReplayData(out); + } else { + usage(); + return; + } + } + // Not an address + boolean all = name.equals("-a"); + Threads threads = VM.getVM().getThreads(); + for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + thread.printThreadIDOn(new PrintStream(bos)); + if (all || bos.toString().equals(name)) { + if (thread instanceof CompilerThread) { + CompilerThread ct = (CompilerThread)thread; + ciEnv env = ct.env(); + if (env != null) { + env.dumpReplayData(out); + } + } + } + } + } + }, + new Command("buildreplayjars", "buildreplayjars [ all | app | boot ] | [ prefix ]", false) { + // This is used to dump jar files of all the classes + // loaded in the core. Everything on the bootclasspath + // will go in boot.jar and everything else will go in + // app.jar. Then the classes can be loaded by the replay + // jvm using -Xbootclasspath/p:boot.jar -cp app.jar. boot.jar usually + // not needed, unless changed by jvmti. + public void doit(Tokens t) { + int tcount = t.countTokens(); + if (tcount > 2) { + usage(); + return; + } + try { + String prefix = ""; + String option = "all"; // default + switch(tcount) { + case 0: + break; + case 1: + option = t.nextToken(); + if (!option.equalsIgnoreCase("all") && !option.equalsIgnoreCase("app") && + !option.equalsIgnoreCase("root")) { + prefix = option; + option = "all"; + } + break; + case 2: + option = t.nextToken(); + prefix = t.nextToken(); + break; + default: + usage(); + return; + } + if (!option.equalsIgnoreCase("all") && !option.equalsIgnoreCase("app") && + !option.equalsIgnoreCase("boot")) { + usage(); + return; + } + ClassDump cd = new ClassDump(); + if (option.equalsIgnoreCase("all") || option.equalsIgnoreCase("boot")) { + cd.setClassFilter(new BootFilter()); + cd.setJarOutput(prefix + "boot.jar"); + cd.run(); + } + if (option.equalsIgnoreCase("all") || option.equalsIgnoreCase("app")) { + cd.setClassFilter(new NonBootFilter()); + cd.setJarOutput(prefix + "app.jar"); + cd.run(); + } + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + }, new Command("findpc", "findpc address", false) { public void doit(Tokens t) { if (t.countTokens() != 1) { diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/src/share/classes/sun/jvm/hotspot/ci/ciBaseObject.java --- a/agent/src/share/classes/sun/jvm/hotspot/ci/ciBaseObject.java Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/ci/ciBaseObject.java Fri Nov 16 09:36:40 2012 -0800 @@ -16,9 +16,9 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. * */ @@ -50,4 +50,8 @@ public ciBaseObject(Address addr) { super(addr); } + + public void dumpReplayData(PrintStream out) { + out.println("# Unknown ci type " + getAddress().getAddressAt(0)); + } } diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/src/share/classes/sun/jvm/hotspot/ci/ciConstant.java --- a/agent/src/share/classes/sun/jvm/hotspot/ci/ciConstant.java Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/ci/ciConstant.java Fri Nov 16 09:36:40 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -16,9 +16,9 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. * */ @@ -60,4 +60,8 @@ public ciConstant(Address addr) { super(addr); } + + public void dumpReplayData(PrintStream out) { + // Nothing to be done + } } diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/src/share/classes/sun/jvm/hotspot/ci/ciEnv.java --- a/agent/src/share/classes/sun/jvm/hotspot/ci/ciEnv.java Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/ci/ciEnv.java Fri Nov 16 09:36:40 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -16,9 +16,9 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. * */ @@ -74,4 +74,29 @@ public CompileTask task() { return new CompileTask(taskField.getValue(this.getAddress())); } + + public void dumpReplayData(PrintStream out) { + out.println("JvmtiExport can_access_local_variables " + + (JvmtiExport.canAccessLocalVariables() ? '1' : '0')); + out.println("JvmtiExport can_hotswap_or_post_breakpoint " + + (JvmtiExport.canHotswapOrPostBreakpoint() ? '1' : '0')); + out.println("JvmtiExport can_post_on_exceptions " + + (JvmtiExport.canPostOnExceptions() ? '1' : '0')); + + GrowableArray objects = factory().objects(); + out.println("# " + objects.length() + " ciObject found"); + for (int i = 0; i < objects.length(); i++) { + ciMetadata o = objects.at(i); + out.println("# ciMetadata" + i + " @ " + o); + o.dumpReplayData(out); + } + CompileTask task = task(); + Method method = task.method(); + int entryBci = task.osrBci(); + Klass holder = method.getMethodHolder(); + out.println("compile " + holder.getName().asString() + " " + + OopUtilities.escapeString(method.getName().asString()) + " " + + method.getSignature().asString() + " " + + entryBci); + } } diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/src/share/classes/sun/jvm/hotspot/ci/ciInstanceKlass.java --- a/agent/src/share/classes/sun/jvm/hotspot/ci/ciInstanceKlass.java Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/ci/ciInstanceKlass.java Fri Nov 16 09:36:40 2012 -0800 @@ -16,9 +16,9 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. * */ @@ -80,4 +80,84 @@ public boolean isInitialized() { return initState() == CLASS_STATE_FULLY_INITIALIZED; } + + public void dumpReplayData(PrintStream out) { + InstanceKlass ik = (InstanceKlass)getMetadata(); + ConstantPool cp = ik.getConstants(); + + // Try to record related loaded classes + Klass sub = ik.getSubklassKlass(); + while (sub != null) { + if (sub instanceof InstanceKlass) { + out.println("instanceKlass " + sub.getName().asString()); + } + sub = sub.getNextSiblingKlass(); + } + + final int length = (int) cp.getLength(); + out.print("ciInstanceKlass " + name() + " " + (isLinked() ? 1 : 0) + " " + (isInitialized() ? 1 : 0) + " " + length); + for (int index = 1; index < length; index++) { + out.print(" " + cp.getTags().at(index)); + } + out.println(); + if (isInitialized()) { + Field[] staticFields = ik.getStaticFields(); + for (int i = 0; i < staticFields.length; i++) { + Field f = staticFields[i]; + Oop mirror = ik.getJavaMirror(); + if (f.isFinal() && !f.hasInitialValue()) { + out.print("staticfield " + name() + " " + + OopUtilities.escapeString(f.getID().getName()) + " " + + f.getFieldType().getSignature().asString() + " "); + if (f instanceof ByteField) { + ByteField bf = (ByteField)f; + out.println(bf.getValue(mirror)); + } else if (f instanceof BooleanField) { + BooleanField bf = (BooleanField)f; + out.println(bf.getValue(mirror) ? 1 : 0); + } else if (f instanceof ShortField) { + ShortField bf = (ShortField)f; + out.println(bf.getValue(mirror)); + } else if (f instanceof CharField) { + CharField bf = (CharField)f; + out.println(bf.getValue(mirror) & 0xffff); + } else if (f instanceof IntField) { + IntField bf = (IntField)f; + out.println(bf.getValue(mirror)); + } else if (f instanceof LongField) { + LongField bf = (LongField)f; + out.println(bf.getValue(mirror)); + } else if (f instanceof FloatField) { + FloatField bf = (FloatField)f; + out.println(Float.floatToRawIntBits(bf.getValue(mirror))); + } else if (f instanceof DoubleField) { + DoubleField bf = (DoubleField)f; + out.println(Double.doubleToRawLongBits(bf.getValue(mirror))); + } else if (f instanceof OopField) { + OopField bf = (OopField)f; + Oop value = bf.getValue(mirror); + if (value == null) { + out.println("null"); + } else if (value.isInstance()) { + Instance inst = (Instance)value; + if (inst.isA(SystemDictionary.getStringKlass())) { + out.println("\"" + OopUtilities.stringOopToEscapedString(inst) + "\""); + } else { + out.println(inst.getKlass().getName().asString()); + } + } else if (value.isObjArray()) { + ObjArray oa = (ObjArray)value; + Klass ek = (ObjArrayKlass)oa.getKlass(); + out.println(oa.getLength() + " " + ek.getName().asString()); + } else if (value.isTypeArray()) { + TypeArray ta = (TypeArray)value; + out.println(ta.getLength()); + } else { + out.println(value); + } + } + } + } + } + } } diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/src/share/classes/sun/jvm/hotspot/ci/ciMethod.java --- a/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethod.java Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethod.java Fri Nov 16 09:36:40 2012 -0800 @@ -16,9 +16,9 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. * */ @@ -88,4 +88,19 @@ st.printf(" %s::%s", method.getMethodHolder().getName().asString().replace('/', '.'), method.getName().asString()); } + + public void dumpReplayData(PrintStream out) { + Method method = (Method)getMetadata(); + NMethod nm = method.getNativeMethod(); + Klass holder = method.getMethodHolder(); + out.println("ciMethod " + + holder.getName().asString() + " " + + OopUtilities.escapeString(method.getName().asString()) + " " + + method.getSignature().asString() + " " + + method.getInvocationCounter() + " " + + method.getBackedgeCounter() + " " + + interpreterInvocationCount() + " " + + interpreterThrowoutCount() + " " + + instructionsSize()); + } } diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/src/share/classes/sun/jvm/hotspot/ci/ciMethodData.java --- a/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethodData.java Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/ci/ciMethodData.java Fri Nov 16 09:36:40 2012 -0800 @@ -16,9 +16,9 @@ * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. * */ @@ -174,4 +174,52 @@ } } + public void dumpReplayData(PrintStream out) { + MethodData mdo = (MethodData)getMetadata(); + Method method = mdo.getMethod(); + Klass holder = method.getMethodHolder(); + out.print("ciMethodData " + + holder.getName().asString() + " " + + OopUtilities.escapeString(method.getName().asString()) + " " + + method.getSignature().asString() + " " + + state() + " " + currentMileage()); + byte[] orig = orig(); + out.print(" orig " + orig.length); + for (int i = 0; i < orig.length; i++) { + out.print(" " + (orig[i] & 0xff)); + } + + long[] data = data(); + out.print(" data " + data.length); + for (int i = 0; i < data.length; i++) { + out.print(" 0x" + Long.toHexString(data[i])); + } + int count = 0; + for (int round = 0; round < 2; round++) { + if (round == 1) out.print(" oops " + count); + ProfileData pdata = firstData(); + for ( ; isValid(pdata); pdata = nextData(pdata)) { + if (pdata instanceof ciReceiverTypeData) { + ciReceiverTypeData vdata = (ciReceiverTypeData)pdata; + for (int i = 0; i < vdata.rowLimit(); i++) { + ciKlass k = vdata.receiverAt(i); + if (k != null) { + if (round == 0) count++; + else out.print(" " + ((vdata.dp() + vdata.cellOffset(vdata.receiverCellIndex(i))) / MethodData.cellSize) + " " + k.name()); + } + } + } else if (pdata instanceof ciVirtualCallData) { + ciVirtualCallData vdata = (ciVirtualCallData)pdata; + for (int i = 0; i < vdata.rowLimit(); i++) { + ciKlass k = vdata.receiverAt(i); + if (k != null) { + if (round == 0) count++; + else out.print(" " + ((vdata.dp() + vdata.cellOffset(vdata.receiverCellIndex(i))) / MethodData.cellSize + " " + k.name())); + } + } + } + } + } + out.println(); + } } diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java --- a/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Fri Nov 16 09:36:40 2012 -0800 @@ -498,6 +498,42 @@ method.getSignature().asString(); } + public void dumpReplayData(PrintStream out) { + HashMap h = new HashMap(); + for (int i = 1; i < getMetadataLength(); i++) { + Metadata meta = Metadata.instantiateWrapperFor(getMetadataAt(i)); + System.err.println(meta); + if (h.get(meta) != null) continue; + h.put(meta, meta); + if (meta instanceof InstanceKlass) { + ((InstanceKlass)meta).dumpReplayData(out); + } else if (meta instanceof Method) { + ((Method)meta).dumpReplayData(out); + MethodData mdo = ((Method)meta).getMethodData(); + if (mdo != null) { + mdo.dumpReplayData(out); + } + } + } + Method method = getMethod(); + if (h.get(method) == null) { + method.dumpReplayData(out); + MethodData mdo = method.getMethodData(); + if (mdo != null) { + mdo.dumpReplayData(out); + } + } + if (h.get(method.getMethodHolder()) == null) { + ((InstanceKlass)method.getMethodHolder()).dumpReplayData(out); + } + Klass holder = method.getMethodHolder(); + out.println("compile " + holder.getName().asString() + " " + + OopUtilities.escapeString(method.getName().asString()) + " " + + method.getSignature().asString() + " " + + getEntryBCI()); + + } + //-------------------------------------------------------------------------------- // Internals only below this point // diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/src/share/classes/sun/jvm/hotspot/compiler/CompileTask.java --- a/agent/src/share/classes/sun/jvm/hotspot/compiler/CompileTask.java Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/compiler/CompileTask.java Fri Nov 16 09:36:40 2012 -0800 @@ -56,7 +56,7 @@ } public Method method() { - Address oh = methodField.getValue(getAddress()).getAddressAt(0); + Address oh = methodField.getValue(getAddress()); return (Method)Metadata.instantiateWrapperFor(oh); } diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java Fri Nov 16 09:36:40 2012 -0800 @@ -86,7 +86,7 @@ public void printValueOn(PrintStream tty) { - tty.print("ConstantPoolCache for " + getConstants().getPoolHolder().getName().asString()); + tty.print("ConstantPoolCache for " + getConstants().getPoolHolder().getName().asString() + " address = " + getAddress() + " offset = " + baseOffset); } public int getLength() { diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/src/share/classes/sun/jvm/hotspot/oops/Field.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/Field.java Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/Field.java Fri Nov 16 09:36:40 2012 -0800 @@ -110,6 +110,8 @@ public Symbol getSignature() { return signature; } public Symbol getGenericSignature() { return genericSignature; } + public boolean hasInitialValue() { return holder.getFieldInitialValueIndex(fieldIndex) != 0; } + // // Following acccessors are for named, non-VM fields only // diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Fri Nov 16 09:36:40 2012 -0800 @@ -278,7 +278,7 @@ } public short getFieldGenericSignatureIndex(int index) { - int len = getFields().length(); + // int len = getFields().length(); int allFieldsCount = getAllFieldsCount(); int generic_signature_slot = allFieldsCount * FIELD_SLOTS; for (int i = 0; i < allFieldsCount; i++) { @@ -325,7 +325,7 @@ public KlassArray getTransitiveInterfaces() { return new KlassArray(transitiveInterfaces.getValue(getAddress())); } public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); } public int getAllFieldsCount() { - int len = getFields().length(); + int len = getFields().length(); int allFieldsCount = 0; for (; allFieldsCount*FIELD_SLOTS < len; allFieldsCount++) { short flags = getFieldAccessFlags(allFieldsCount); @@ -581,6 +581,19 @@ } } + public Field[] getStaticFields() { + U2Array fields = getFields(); + int length = getJavaFieldsCount(); + ArrayList result = new ArrayList(); + for (int index = 0; index < length; index++) { + Field f = newField(index); + if (f.isStatic()) { + result.add(f); + } + } + return (Field[])result.toArray(new Field[result.size()]); + } + public void iterateNonStaticFields(OopVisitor visitor, Oop obj) { if (getSuper() != null) { ((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj); @@ -979,4 +992,84 @@ } return -1; } + + public void dumpReplayData(PrintStream out) { + ConstantPool cp = getConstants(); + + // Try to record related loaded classes + Klass sub = getSubklassKlass(); + while (sub != null) { + if (sub instanceof InstanceKlass) { + out.println("instanceKlass " + sub.getName().asString()); + } + sub = sub.getNextSiblingKlass(); + } + + final int length = (int) cp.getLength(); + out.print("ciInstanceKlass " + getName().asString() + " " + (isLinked() ? 1 : 0) + " " + (isInitialized() ? 1 : 0) + " " + length); + for (int index = 1; index < length; index++) { + out.print(" " + cp.getTags().at(index)); + } + out.println(); + if (isInitialized()) { + Field[] staticFields = getStaticFields(); + for (int i = 0; i < staticFields.length; i++) { + Field f = staticFields[i]; + Oop mirror = getJavaMirror(); + if (f.isFinal() && !f.hasInitialValue()) { + out.print("staticfield " + getName().asString() + " " + + OopUtilities.escapeString(f.getID().getName()) + " " + + f.getFieldType().getSignature().asString() + " "); + if (f instanceof ByteField) { + ByteField bf = (ByteField)f; + out.println(bf.getValue(mirror)); + } else if (f instanceof BooleanField) { + BooleanField bf = (BooleanField)f; + out.println(bf.getValue(mirror) ? 1 : 0); + } else if (f instanceof ShortField) { + ShortField bf = (ShortField)f; + out.println(bf.getValue(mirror)); + } else if (f instanceof CharField) { + CharField bf = (CharField)f; + out.println(bf.getValue(mirror) & 0xffff); + } else if (f instanceof IntField) { + IntField bf = (IntField)f; + out.println(bf.getValue(mirror)); + } else if (f instanceof LongField) { + LongField bf = (LongField)f; + out.println(bf.getValue(mirror)); + } else if (f instanceof FloatField) { + FloatField bf = (FloatField)f; + out.println(Float.floatToRawIntBits(bf.getValue(mirror))); + } else if (f instanceof DoubleField) { + DoubleField bf = (DoubleField)f; + out.println(Double.doubleToRawLongBits(bf.getValue(mirror))); + } else if (f instanceof OopField) { + OopField bf = (OopField)f; + + Oop value = bf.getValue(mirror); + if (value == null) { + out.println("null"); + } else if (value.isInstance()) { + Instance inst = (Instance)value; + if (inst.isA(SystemDictionary.getStringKlass())) { + out.println("\"" + OopUtilities.stringOopToEscapedString(inst) + "\""); + } else { + out.println(inst.getKlass().getName().asString()); + } + } else if (value.isObjArray()) { + ObjArray oa = (ObjArray)value; + Klass ek = (ObjArrayKlass)oa.getKlass(); + out.println(oa.getLength() + " " + ek.getName().asString()); + } else if (value.isTypeArray()) { + TypeArray ta = (TypeArray)value; + out.println(ta.getLength()); + } else { + out.println(value); + } + } + } + } + } + } } diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/src/share/classes/sun/jvm/hotspot/oops/Metadata.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/Metadata.java Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/Metadata.java Fri Nov 16 09:36:40 2012 -0800 @@ -79,4 +79,7 @@ } abstract public void printValueOn(PrintStream tty); + public void dumpReplayData(PrintStream out) { + out.println("# Unknown Metadata"); + } } diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/src/share/classes/sun/jvm/hotspot/oops/Method.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Fri Nov 16 09:36:40 2012 -0800 @@ -358,6 +358,25 @@ buf.append(")"); return buf.toString().replace('/', '.'); } + + public void dumpReplayData(PrintStream out) { + NMethod nm = getNativeMethod(); + int code_size = 0; + if (nm != null) { + code_size = (int)nm.codeEnd().minus(nm.getVerifiedEntryPoint()); + } + Klass holder = getMethodHolder(); + out.println("ciMethod " + + holder.getName().asString() + " " + + OopUtilities.escapeString(getName().asString()) + " " + + getSignature().asString() + " " + + getInvocationCounter() + " " + + getBackedgeCounter() + " " + + interpreterInvocationCount() + " " + + interpreterThrowoutCount() + " " + + code_size); + } + public int interpreterThrowoutCount() { return (int) interpreterThrowoutCountField.getValue(this); } diff -r 4e3e685dbc9d -r cfc5309f03b7 agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java Thu Nov 15 15:39:02 2012 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java Fri Nov 16 09:36:40 2012 -0800 @@ -332,4 +332,59 @@ public int currentMileage() { return 20000; } + + public void dumpReplayData(PrintStream out) { + Method method = getMethod(); + Klass holder = method.getMethodHolder(); + out.print("ciMethodData " + + holder.getName().asString() + " " + + OopUtilities.escapeString(method.getName().asString()) + " " + + method.getSignature().asString() + " " + + "2" + " " + + currentMileage()); + byte[] orig = orig(); + out.print(" orig " + orig.length); + for (int i = 0; i < orig.length; i++) { + out.print(" " + (orig[i] & 0xff)); + } + + long[] data = data(); + out.print(" data " + data.length); + for (int i = 0; i < data.length; i++) { + out.print(" 0x" + Long.toHexString(data[i])); + } + int count = 0; + for (int round = 0; round < 2; round++) { + if (round == 1) out.print(" oops " + count); + ProfileData pdata = firstData(); + for ( ; isValid(pdata); pdata = nextData(pdata)) { + if (pdata instanceof ReceiverTypeData) { + ReceiverTypeData vdata = (ReceiverTypeData)pdata; + for (int i = 0; i < vdata.rowLimit(); i++) { + Klass k = vdata.receiver(i); + if (k != null) { + if (round == 0) count++; + else out.print(" " + + (dpToDi(vdata.dp() + + vdata.cellOffset(vdata.receiverCellIndex(i))) / cellSize) + " " + + k.getName().asString()); + } + } + } else if (pdata instanceof VirtualCallData) { + VirtualCallData vdata = (VirtualCallData)pdata; + for (int i = 0; i < vdata.rowLimit(); i++) { + Klass k = vdata.receiver(i); + if (k != null) { + if (round == 0) count++; + else out.print(" " + + (dpToDi(vdata.dp() + + vdata.cellOffset(vdata.receiverCellIndex(i))) / cellSize) + " " + + k.getName().asString()); + } + } + } + } + } + out.println(); + } } diff -r 4e3e685dbc9d -r cfc5309f03b7 make/hotspot_version --- a/make/hotspot_version Thu Nov 15 15:39:02 2012 -0800 +++ b/make/hotspot_version Fri Nov 16 09:36:40 2012 -0800 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=09 +HS_BUILD_NUMBER=10 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r 4e3e685dbc9d -r cfc5309f03b7 src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/os/bsd/vm/os_bsd.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -1198,19 +1198,20 @@ return os::stat(filename, &statbuf) == 0; } -void os::dll_build_name(char* buffer, size_t buflen, +bool os::dll_build_name(char* buffer, size_t buflen, const char* pname, const char* fname) { + bool retval = false; // Copied from libhpi const size_t pnamelen = pname ? strlen(pname) : 0; - // Quietly truncate on buffer overflow. Should be an error. + // Return error on buffer overflow. if (pnamelen + strlen(fname) + strlen(JNI_LIB_PREFIX) + strlen(JNI_LIB_SUFFIX) + 2 > buflen) { - *buffer = '\0'; - return; + return retval; } if (pnamelen == 0) { snprintf(buffer, buflen, JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, fname); + retval = true; } else if (strchr(pname, *os::path_separator()) != NULL) { int n; char** pelements = split_path(pname, &n); @@ -1222,6 +1223,7 @@ snprintf(buffer, buflen, "%s/" JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, pelements[i], fname); if (file_exists(buffer)) { + retval = true; break; } } @@ -1236,7 +1238,9 @@ } } else { snprintf(buffer, buflen, "%s/" JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, pname, fname); + retval = true; } + return retval; } const char* os::get_current_directory(char *buf, int buflen) { diff -r 4e3e685dbc9d -r cfc5309f03b7 src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/os/linux/vm/os_linux.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -1650,19 +1650,20 @@ return os::stat(filename, &statbuf) == 0; } -void os::dll_build_name(char* buffer, size_t buflen, +bool os::dll_build_name(char* buffer, size_t buflen, const char* pname, const char* fname) { + bool retval = false; // Copied from libhpi const size_t pnamelen = pname ? strlen(pname) : 0; - // Quietly truncate on buffer overflow. Should be an error. + // Return error on buffer overflow. if (pnamelen + strlen(fname) + 10 > (size_t) buflen) { - *buffer = '\0'; - return; + return retval; } if (pnamelen == 0) { snprintf(buffer, buflen, "lib%s.so", fname); + retval = true; } else if (strchr(pname, *os::path_separator()) != NULL) { int n; char** pelements = split_path(pname, &n); @@ -1673,6 +1674,7 @@ } snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname); if (file_exists(buffer)) { + retval = true; break; } } @@ -1687,7 +1689,9 @@ } } else { snprintf(buffer, buflen, "%s/lib%s.so", pname, fname); - } + retval = true; + } + return retval; } const char* os::get_current_directory(char *buf, int buflen) { diff -r 4e3e685dbc9d -r cfc5309f03b7 src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/os/solaris/vm/os_solaris.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -1894,18 +1894,19 @@ return os::stat(filename, &statbuf) == 0; } -void os::dll_build_name(char* buffer, size_t buflen, +bool os::dll_build_name(char* buffer, size_t buflen, const char* pname, const char* fname) { + bool retval = false; const size_t pnamelen = pname ? strlen(pname) : 0; - // Quietly truncate on buffer overflow. Should be an error. + // Return error on buffer overflow. if (pnamelen + strlen(fname) + 10 > (size_t) buflen) { - *buffer = '\0'; - return; + return retval; } if (pnamelen == 0) { snprintf(buffer, buflen, "lib%s.so", fname); + retval = true; } else if (strchr(pname, *os::path_separator()) != NULL) { int n; char** pelements = split_path(pname, &n); @@ -1916,6 +1917,7 @@ } snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname); if (file_exists(buffer)) { + retval = true; break; } } @@ -1930,7 +1932,9 @@ } } else { snprintf(buffer, buflen, "%s/lib%s.so", pname, fname); - } + retval = true; + } + return retval; } const char* os::get_current_directory(char *buf, int buflen) { diff -r 4e3e685dbc9d -r cfc5309f03b7 src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/os/windows/vm/os_windows.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -1132,21 +1132,23 @@ return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES; } -void os::dll_build_name(char *buffer, size_t buflen, +bool os::dll_build_name(char *buffer, size_t buflen, const char* pname, const char* fname) { + bool retval = false; const size_t pnamelen = pname ? strlen(pname) : 0; const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0; - // Quietly truncates on buffer overflow. Should be an error. + // Return error on buffer overflow. if (pnamelen + strlen(fname) + 10 > buflen) { - *buffer = '\0'; - return; + return retval; } if (pnamelen == 0) { jio_snprintf(buffer, buflen, "%s.dll", fname); + retval = true; } else if (c == ':' || c == '\\') { jio_snprintf(buffer, buflen, "%s%s.dll", pname, fname); + retval = true; } else if (strchr(pname, *os::path_separator()) != NULL) { int n; char** pelements = split_path(pname, &n); @@ -1164,6 +1166,7 @@ jio_snprintf(buffer, buflen, "%s\\%s.dll", path, fname); } if (file_exists(buffer)) { + retval = true; break; } } @@ -1178,7 +1181,9 @@ } } else { jio_snprintf(buffer, buflen, "%s\\%s.dll", pname, fname); - } + retval = true; + } + return retval; } // Needs to be in os specific directory because windows requires another diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/c1/c1_GraphBuilder.cpp --- a/src/share/vm/c1/c1_GraphBuilder.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -1836,7 +1836,7 @@ // check if we could do inlining if (!PatchALot && Inline && klass->is_loaded() && (klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized()) - && target->will_link(klass, callee_holder, code)) { + && target->is_loaded()) { // callee is known => check if we have static binding assert(target->is_loaded(), "callee must be known"); if (code == Bytecodes::_invokestatic || diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/c1/c1_Runtime1.cpp --- a/src/share/vm/c1/c1_Runtime1.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/c1/c1_Runtime1.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -374,7 +374,7 @@ JRT_ENTRY(void, Runtime1::throw_array_store_exception(JavaThread* thread, oopDesc* obj)) ResourceMark rm(thread); - const char* klass_name = Klass::cast(obj->klass())->external_name(); + const char* klass_name = obj->klass()->external_name(); SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_ArrayStoreException(), klass_name); JRT_END @@ -631,7 +631,7 @@ NOT_PRODUCT(_throw_class_cast_exception_count++;) ResourceMark rm(thread); char* message = SharedRuntime::generate_class_cast_message( - thread, Klass::cast(object->klass())->external_name()); + thread, object->klass()->external_name()); SharedRuntime::throw_and_post_jvmti_exception( thread, vmSymbols::java_lang_ClassCastException(), message); JRT_END @@ -876,7 +876,7 @@ case Bytecodes::_anewarray: { Bytecode_anewarray anew(caller_method(), caller_method->bcp_from(bci)); Klass* ek = caller_method->constants()->klass_at(anew.index(), CHECK); - k = Klass::cast(ek)->array_klass(CHECK); + k = ek->array_klass(CHECK); } break; case Bytecodes::_ldc: @@ -1236,7 +1236,7 @@ } else { Klass* bound = ObjArrayKlass::cast(dst->klass())->element_klass(); Klass* stype = ObjArrayKlass::cast(src->klass())->element_klass(); - if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) { + if (stype == bound || stype->is_subtype_of(bound)) { // Elements are guaranteed to be subtypes, so no check necessary bs->write_ref_array_pre(dst_addr, length); Copy::conjoint_oops_atomic(src_addr, dst_addr, length); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/bcEscapeAnalyzer.cpp --- a/src/share/vm/ci/bcEscapeAnalyzer.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -282,7 +282,7 @@ ciMethod* inline_target = NULL; if (target->is_loaded() && klass->is_loaded() && (klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized()) - && target->will_link(klass, callee_holder, code)) { + && target->is_loaded()) { if (code == Bytecodes::_invokestatic || code == Bytecodes::_invokespecial || code == Bytecodes::_invokevirtual && target->is_final_method()) { diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciClassList.hpp --- a/src/share/vm/ci/ciClassList.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciClassList.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -106,6 +106,7 @@ friend class ciArray; \ friend class ciObjArray; \ friend class ciMetadata; \ +friend class ciReplay; \ friend class ciTypeArray; \ friend class ciType; \ friend class ciReturnAddress; \ diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciEnv.cpp --- a/src/share/vm/ci/ciEnv.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciEnv.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -30,6 +30,7 @@ #include "ci/ciInstanceKlass.hpp" #include "ci/ciMethod.hpp" #include "ci/ciNullObject.hpp" +#include "ci/ciReplay.hpp" #include "ci/ciUtilities.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" @@ -426,7 +427,7 @@ for (int i = cpool->length() - 1; i >= 1; i--) { if (cpool->tag_at(i).is_klass()) { Klass* kls = cpool->resolved_klass_at(i); - if (Klass::cast(kls)->name() == sym) { + if (kls->name() == sym) { found_klass = KlassHandle(THREAD, kls); break; } @@ -772,6 +773,11 @@ : !m->method_holder()->is_loaded())) { m = NULL; } +#ifdef ASSERT + if (m != NULL && ReplayCompiles && !ciReplay::is_loaded(m)) { + m = NULL; + } +#endif if (m != NULL) { // We found the method. return get_method(m); @@ -1144,3 +1150,43 @@ // If memory is low, we stop compiling methods. record_method_not_compilable("out of memory"); } + +fileStream* ciEnv::_replay_data_stream = NULL; + +void ciEnv::dump_replay_data() { + VM_ENTRY_MARK; + MutexLocker ml(Compile_lock); + if (_replay_data_stream == NULL) { + _replay_data_stream = new (ResourceObj::C_HEAP, mtCompiler) fileStream(ReplayDataFile); + if (_replay_data_stream == NULL) { + fatal(err_msg("Can't open %s for replay data", ReplayDataFile)); + } + } + dump_replay_data(_replay_data_stream); +} + + +void ciEnv::dump_replay_data(outputStream* out) { + ASSERT_IN_VM; + +#if INCLUDE_JVMTI + out->print_cr("JvmtiExport can_access_local_variables %d", _jvmti_can_access_local_variables); + out->print_cr("JvmtiExport can_hotswap_or_post_breakpoint %d", _jvmti_can_hotswap_or_post_breakpoint); + out->print_cr("JvmtiExport can_post_on_exceptions %d", _jvmti_can_post_on_exceptions); +#endif // INCLUDE_JVMTI + + GrowableArray* objects = _factory->get_ci_metadata(); + out->print_cr("# %d ciObject found", objects->length()); + for (int i = 0; i < objects->length(); i++) { + objects->at(i)->dump_replay_data(out); + } + Method* method = task()->method(); + int entry_bci = task()->osr_bci(); + // Klass holder = method->method_holder(); + out->print_cr("compile %s %s %s %d", + method->klass_name()->as_quoted_ascii(), + method->name()->as_quoted_ascii(), + method->signature()->as_quoted_ascii(), + entry_bci); + out->flush(); +} diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciEnv.hpp --- a/src/share/vm/ci/ciEnv.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciEnv.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -46,6 +46,8 @@ friend class CompileBroker; friend class Dependencies; // for get_object, during logging + static fileStream* _replay_data_stream; + private: Arena* _arena; // Alias for _ciEnv_arena except in init_shared_objects() Arena _ciEnv_arena; @@ -448,6 +450,13 @@ // RedefineClasses support void metadata_do(void f(Metadata*)) { _factory->metadata_do(f); } + + // Dump the compilation replay data for this ciEnv to + // ReplayDataFile, creating the file if needed. + void dump_replay_data(); + + // Dump the compilation replay data for the ciEnv to the stream. + void dump_replay_data(outputStream* out); }; #endif // SHARE_VM_CI_CIENV_HPP diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciInstanceKlass.cpp --- a/src/share/vm/ci/ciInstanceKlass.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciInstanceKlass.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -561,3 +561,114 @@ } return impl; } + +// Utility class for printing of the contents of the static fields for +// use by compilation replay. It only prints out the information that +// could be consumed by the compiler, so for primitive types it prints +// out the actual value. For Strings it's the actual string value. +// For array types it it's first level array size since that's the +// only value which statically unchangeable. For all other reference +// types it simply prints out the dynamic type. + +class StaticFinalFieldPrinter : public FieldClosure { + outputStream* _out; + const char* _holder; + public: + StaticFinalFieldPrinter(outputStream* out, const char* holder) : + _out(out), + _holder(holder) { + } + void do_field(fieldDescriptor* fd) { + if (fd->is_final() && !fd->has_initial_value()) { + oop mirror = fd->field_holder()->java_mirror(); + _out->print("staticfield %s %s %s ", _holder, fd->name()->as_quoted_ascii(), fd->signature()->as_quoted_ascii()); + switch (fd->field_type()) { + case T_BYTE: _out->print_cr("%d", mirror->byte_field(fd->offset())); break; + case T_BOOLEAN: _out->print_cr("%d", mirror->bool_field(fd->offset())); break; + case T_SHORT: _out->print_cr("%d", mirror->short_field(fd->offset())); break; + case T_CHAR: _out->print_cr("%d", mirror->char_field(fd->offset())); break; + case T_INT: _out->print_cr("%d", mirror->int_field(fd->offset())); break; + case T_LONG: _out->print_cr(INT64_FORMAT, mirror->long_field(fd->offset())); break; + case T_FLOAT: { + float f = mirror->float_field(fd->offset()); + _out->print_cr("%d", *(int*)&f); + break; + } + case T_DOUBLE: { + double d = mirror->double_field(fd->offset()); + _out->print_cr(INT64_FORMAT, *(jlong*)&d); + break; + } + case T_ARRAY: { + oop value = mirror->obj_field_acquire(fd->offset()); + if (value == NULL) { + _out->print_cr("null"); + } else { + typeArrayOop ta = (typeArrayOop)value; + _out->print("%d", ta->length()); + if (value->is_objArray()) { + objArrayOop oa = (objArrayOop)value; + const char* klass_name = value->klass()->name()->as_quoted_ascii(); + _out->print(" %s", klass_name); + } + _out->cr(); + } + break; + } + case T_OBJECT: { + oop value = mirror->obj_field_acquire(fd->offset()); + if (value == NULL) { + _out->print_cr("null"); + } else if (value->is_instance()) { + if (value->is_a(SystemDictionary::String_klass())) { + _out->print("\""); + _out->print_raw(java_lang_String::as_quoted_ascii(value)); + _out->print_cr("\""); + } else { + const char* klass_name = value->klass()->name()->as_quoted_ascii(); + _out->print_cr(klass_name); + } + } else { + ShouldNotReachHere(); + } + break; + } + default: + ShouldNotReachHere(); + } + } + } +}; + + +void ciInstanceKlass::dump_replay_data(outputStream* out) { + ASSERT_IN_VM; + InstanceKlass* ik = get_instanceKlass(); + ConstantPool* cp = ik->constants(); + + // Try to record related loaded classes + Klass* sub = ik->subklass(); + while (sub != NULL) { + if (sub->oop_is_instance()) { + out->print_cr("instanceKlass %s", sub->name()->as_quoted_ascii()); + } + sub = sub->next_sibling(); + } + + // Dump out the state of the constant pool tags. During replay the + // tags will be validated for things which shouldn't change and + // classes will be resolved if the tags indicate that they were + // resolved at compile time. + out->print("ciInstanceKlass %s %d %d %d", ik->name()->as_quoted_ascii(), + is_linked(), is_initialized(), cp->length()); + for (int index = 1; index < cp->length(); index++) { + out->print(" %d", cp->tags()->at(index)); + } + out->cr(); + if (is_initialized()) { + // Dump out the static final fields in case the compilation relies + // on their value for correct replay. + StaticFinalFieldPrinter sffp(out, ik->name()->as_quoted_ascii()); + ik->do_local_static_fields(&sffp); + } +} diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciInstanceKlass.hpp --- a/src/share/vm/ci/ciInstanceKlass.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciInstanceKlass.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -230,6 +230,9 @@ // What kind of ciObject is this? bool is_instance_klass() const { return true; } bool is_java_klass() const { return true; } + + // Dump the current state of this klass for compilation replay. + virtual void dump_replay_data(outputStream* out); }; #endif // SHARE_VM_CI_CIINSTANCEKLASS_HPP diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciMetadata.hpp --- a/src/share/vm/ci/ciMetadata.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciMetadata.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -61,6 +61,7 @@ virtual bool is_array_klass() const { return false; } virtual bool is_obj_array_klass() const { return false; } virtual bool is_type_array_klass() const { return false; } + virtual void dump_replay_data(outputStream* st) { /* do nothing */ } ciMethod* as_method() { assert(is_method(), "bad cast"); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciMethod.cpp --- a/src/share/vm/ci/ciMethod.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciMethod.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -31,6 +31,7 @@ #include "ci/ciMethodData.hpp" #include "ci/ciStreams.hpp" #include "ci/ciSymbol.hpp" +#include "ci/ciReplay.hpp" #include "ci/ciUtilities.hpp" #include "classfile/systemDictionary.hpp" #include "compiler/abstractCompiler.hpp" @@ -139,6 +140,12 @@ } if (_interpreter_invocation_count == 0) _interpreter_invocation_count = 1; + _instructions_size = -1; +#ifdef ASSERT + if (ReplayCompiles) { + ciReplay::initialize(this); + } +#endif } @@ -161,7 +168,8 @@ #if defined(COMPILER2) || defined(SHARK) , _flow( NULL), - _bcea( NULL) + _bcea( NULL), + _instructions_size(-1) #endif // COMPILER2 || SHARK { // Usually holder and accessor are the same type but in some cases @@ -868,25 +876,6 @@ } // ------------------------------------------------------------------ -// ciMethod::will_link -// -// Will this method link in a specific calling context? -bool ciMethod::will_link(ciKlass* accessing_klass, - ciKlass* declared_method_holder, - Bytecodes::Code bc) { - if (!is_loaded()) { - // Method lookup failed. - return false; - } - - // The link checks have been front-loaded into the get_method - // call. This method (ciMethod::will_link()) will be removed - // in the future. - - return true; -} - -// ------------------------------------------------------------------ // ciMethod::should_exclude // // Should this method be excluded from compilation? @@ -1000,8 +989,7 @@ // ------------------------------------------------------------------ // ciMethod::has_compiled_code bool ciMethod::has_compiled_code() { - VM_ENTRY_MARK; - return get_Method()->code() != NULL; + return instructions_size() > 0; } int ciMethod::comp_level() { @@ -1039,14 +1027,18 @@ // junk like exception handler, stubs, and constant table, which are // not highly relevant to an inlined method. So we use the more // specific accessor nmethod::insts_size. -int ciMethod::instructions_size(int comp_level) { - GUARDED_VM_ENTRY( - nmethod* code = get_Method()->code(); - if (code != NULL && (comp_level == CompLevel_any || comp_level == code->comp_level())) { - return code->insts_end() - code->verified_entry_point(); - } - return 0; - ) +int ciMethod::instructions_size() { + if (_instructions_size == -1) { + GUARDED_VM_ENTRY( + nmethod* code = get_Method()->code(); + if (code != NULL && (code->comp_level() == CompLevel_full_optimization)) { + _instructions_size = code->insts_end() - code->verified_entry_point(); + } else { + _instructions_size = 0; + } + ); + } + return _instructions_size; } // ------------------------------------------------------------------ @@ -1166,6 +1158,20 @@ #undef FETCH_FLAG_FROM_VM +void ciMethod::dump_replay_data(outputStream* st) { + ASSERT_IN_VM; + Method* method = get_Method(); + Klass* holder = method->method_holder(); + st->print_cr("ciMethod %s %s %s %d %d %d %d %d", + holder->name()->as_quoted_ascii(), + method->name()->as_quoted_ascii(), + method->signature()->as_quoted_ascii(), + method->invocation_counter()->raw_counter(), + method->backedge_counter()->raw_counter(), + interpreter_invocation_count(), + interpreter_throwout_count(), + _instructions_size); +} // ------------------------------------------------------------------ // ciMethod::print_codes diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciMethod.hpp --- a/src/share/vm/ci/ciMethod.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciMethod.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -51,6 +51,7 @@ friend class ciExceptionHandlerStream; friend class ciBytecodeStream; friend class ciMethodHandle; + friend class ciReplay; private: // General method information. @@ -69,6 +70,7 @@ int _handler_count; int _interpreter_invocation_count; int _interpreter_throwout_count; + int _instructions_size; bool _uses_monitors; bool _balanced_monitors; @@ -239,9 +241,6 @@ int resolve_vtable_index(ciKlass* caller, ciKlass* receiver); // Compilation directives - bool will_link(ciKlass* accessing_klass, - ciKlass* declared_method_holder, - Bytecodes::Code bc); bool should_exclude(); bool should_inline(); bool should_not_inline(); @@ -252,7 +251,6 @@ bool can_be_osr_compiled(int entry_bci); void set_not_compilable(); bool has_compiled_code(); - int instructions_size(int comp_level = CompLevel_any); void log_nmethod_identity(xmlStream* log); bool is_not_reached(int bci); bool was_executed_more_than(int times); @@ -260,6 +258,7 @@ bool is_klass_loaded(int refinfo_index, bool must_be_resolved) const; bool check_call(int refinfo_index, bool is_static) const; bool ensure_method_data(); // make sure it exists in the VM also + int instructions_size(); int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC // JSR 292 support @@ -291,6 +290,7 @@ bool is_accessor () const; bool is_initializer () const; bool can_be_statically_bound() const { return _can_be_statically_bound; } + void dump_replay_data(outputStream* st); // Print the bytecodes of this method. void print_codes_on(outputStream* st); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciMethodData.cpp --- a/src/share/vm/ci/ciMethodData.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciMethodData.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "ci/ciMetadata.hpp" #include "ci/ciMethodData.hpp" +#include "ci/ciReplay.hpp" #include "ci/ciUtilities.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" @@ -115,6 +116,11 @@ _arg_local = mdo->arg_local(); _arg_stack = mdo->arg_stack(); _arg_returned = mdo->arg_returned(); +#ifndef PRODUCT + if (ReplayCompiles) { + ciReplay::initialize(this); + } +#endif } void ciReceiverTypeData::translate_receiver_data_from(ProfileData* data) { @@ -366,6 +372,79 @@ ciMetadata::print_impl(st); } +void ciMethodData::dump_replay_data(outputStream* out) { + ASSERT_IN_VM; + MethodData* mdo = get_MethodData(); + Method* method = mdo->method(); + Klass* holder = method->method_holder(); + out->print("ciMethodData %s %s %s %d %d", + holder->name()->as_quoted_ascii(), + method->name()->as_quoted_ascii(), + method->signature()->as_quoted_ascii(), + _state, + current_mileage()); + + // dump the contents of the MDO header as raw data + unsigned char* orig = (unsigned char*)&_orig; + int length = sizeof(_orig); + out->print(" orig %d", length); + for (int i = 0; i < length; i++) { + out->print(" %d", orig[i]); + } + + // dump the MDO data as raw data + int elements = data_size() / sizeof(intptr_t); + out->print(" data %d", elements); + for (int i = 0; i < elements; i++) { + // We could use INTPTR_FORMAT here but that's a zero justified + // which makes comparing it with the SA version of this output + // harder. +#ifdef _LP64 + out->print(" 0x%" FORMAT64_MODIFIER "x", data()[i]); +#else + out->print(" 0x%x", data()[i]); +#endif + } + + // The MDO contained oop references as ciObjects, so scan for those + // and emit pairs of offset and klass name so that they can be + // reconstructed at runtime. The first round counts the number of + // oop references and the second actually emits them. + int count = 0; + for (int round = 0; round < 2; round++) { + if (round == 1) out->print(" oops %d", count); + ProfileData* pdata = first_data(); + for ( ; is_valid(pdata); pdata = next_data(pdata)) { + if (pdata->is_ReceiverTypeData()) { + ciReceiverTypeData* vdata = (ciReceiverTypeData*)pdata; + for (uint i = 0; i < vdata->row_limit(); i++) { + ciKlass* k = vdata->receiver(i); + if (k != NULL) { + if (round == 0) { + count++; + } else { + out->print(" %d %s", dp_to_di(vdata->dp() + in_bytes(vdata->receiver_offset(i))) / sizeof(intptr_t), k->name()->as_quoted_ascii()); + } + } + } + } else if (pdata->is_VirtualCallData()) { + ciVirtualCallData* vdata = (ciVirtualCallData*)pdata; + for (uint i = 0; i < vdata->row_limit(); i++) { + ciKlass* k = vdata->receiver(i); + if (k != NULL) { + if (round == 0) { + count++; + } else { + out->print(" %d %s", dp_to_di(vdata->dp() + in_bytes(vdata->receiver_offset(i))) / sizeof(intptr_t), k->name()->as_quoted_ascii()); + } + } + } + } + } + } + out->cr(); +} + #ifndef PRODUCT void ciMethodData::print() { print_data_on(tty); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciMethodData.hpp --- a/src/share/vm/ci/ciMethodData.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciMethodData.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -144,6 +144,7 @@ class ciMethodData : public ciMetadata { CI_PACKAGE_ACCESS + friend class ciReplay; private: // Size in bytes @@ -320,6 +321,7 @@ void print(); void print_data_on(outputStream* st); #endif + void dump_replay_data(outputStream* out); }; #endif // SHARE_VM_CI_CIMETHODDATA_HPP diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciObject.hpp --- a/src/share/vm/ci/ciObject.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciObject.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -131,6 +131,7 @@ // Is this a type or value which has no associated class? // It is true of primitive types and null objects. virtual bool is_classless() const { return false; } + virtual void dump_replay_data(outputStream* st) { /* do nothing */ } // Note: some ciObjects refer to oops which have yet to be created. // We refer to these as "unloaded". Specifically, there are diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciObjectFactory.hpp --- a/src/share/vm/ci/ciObjectFactory.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciObjectFactory.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -137,6 +137,7 @@ ciReturnAddress* get_return_address(int bci); + GrowableArray* get_ci_metadata() const { return _ci_metadata; } // RedefineClasses support void metadata_do(void f(Metadata*)); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciReplay.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/ci/ciReplay.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -0,0 +1,942 @@ +/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "ci/ciMethodData.hpp" +#include "ci/ciReplay.hpp" +#include "ci/ciUtilities.hpp" +#include "compiler/compileBroker.hpp" +#include "memory/allocation.inline.hpp" +#include "memory/oopFactory.hpp" +#include "memory/resourceArea.hpp" +#include "utilities/copy.hpp" + +#ifdef ASSERT + +// ciReplay + +typedef struct _ciMethodDataRecord { + const char* klass; + const char* method; + const char* signature; + int state; + int current_mileage; + intptr_t* data; + int data_length; + char* orig_data; + int orig_data_length; + int oops_length; + jobject* oops_handles; + int* oops_offsets; +} ciMethodDataRecord; + +typedef struct _ciMethodRecord { + const char* klass; + const char* method; + const char* signature; + int instructions_size; + int interpreter_invocation_count; + int interpreter_throwout_count; + int invocation_counter; + int backedge_counter; +} ciMethodRecord; + +class CompileReplay; +static CompileReplay* replay_state; + +class CompileReplay : public StackObj { + private: + FILE* stream; + Thread* thread; + Handle protection_domain; + Handle loader; + + GrowableArray ci_method_records; + GrowableArray ci_method_data_records; + + const char* _error_message; + + char* bufptr; + char* buffer; + int buffer_length; + int buffer_end; + int line_no; + + public: + CompileReplay(const char* filename, TRAPS) { + thread = THREAD; + loader = Handle(thread, SystemDictionary::java_system_loader()); + stream = fopen(filename, "rt"); + if (stream == NULL) { + fprintf(stderr, "Can't open replay file %s\n", filename); + } + buffer_length = 32; + buffer = NEW_RESOURCE_ARRAY(char, buffer_length); + _error_message = NULL; + + test(); + } + + ~CompileReplay() { + if (stream != NULL) fclose(stream); + } + + void test() { + strcpy(buffer, "1 2 foo 4 bar 0x9 \"this is it\""); + bufptr = buffer; + assert(parse_int("test") == 1, "what"); + assert(parse_int("test") == 2, "what"); + assert(strcmp(parse_string(), "foo") == 0, "what"); + assert(parse_int("test") == 4, "what"); + assert(strcmp(parse_string(), "bar") == 0, "what"); + assert(parse_intptr_t("test") == 9, "what"); + assert(strcmp(parse_quoted_string(), "this is it") == 0, "what"); + } + + bool had_error() { + return _error_message != NULL || thread->has_pending_exception(); + } + + bool can_replay() { + return !(stream == NULL || had_error()); + } + + void report_error(const char* msg) { + _error_message = msg; + // Restore the buffer contents for error reporting + for (int i = 0; i < buffer_end; i++) { + if (buffer[i] == '\0') buffer[i] = ' '; + } + } + + int parse_int(const char* label) { + if (had_error()) { + return 0; + } + + int v = 0; + int read; + if (sscanf(bufptr, "%i%n", &v, &read) != 1) { + report_error(label); + } else { + bufptr += read; + } + return v; + } + + intptr_t parse_intptr_t(const char* label) { + if (had_error()) { + return 0; + } + + intptr_t v = 0; + int read; + if (sscanf(bufptr, INTPTR_FORMAT "%n", &v, &read) != 1) { + report_error(label); + } else { + bufptr += read; + } + return v; + } + + void skip_ws() { + // Skip any leading whitespace + while (*bufptr == ' ' || *bufptr == '\t') { + bufptr++; + } + } + + + char* scan_and_terminate(char delim) { + char* str = bufptr; + while (*bufptr != delim && *bufptr != '\0') { + bufptr++; + } + if (*bufptr != '\0') { + *bufptr++ = '\0'; + } + if (bufptr == str) { + // nothing here + return NULL; + } + return str; + } + + char* parse_string() { + if (had_error()) return NULL; + + skip_ws(); + return scan_and_terminate(' '); + } + + char* parse_quoted_string() { + if (had_error()) return NULL; + + skip_ws(); + + if (*bufptr == '"') { + bufptr++; + return scan_and_terminate('"'); + } else { + return scan_and_terminate(' '); + } + } + + const char* parse_escaped_string() { + char* result = parse_quoted_string(); + if (result != NULL) { + unescape_string(result); + } + return result; + } + + // Look for the tag 'tag' followed by an + bool parse_tag_and_count(const char* tag, int& length) { + const char* t = parse_string(); + if (t == NULL) { + return false; + } + + if (strcmp(tag, t) != 0) { + report_error(tag); + return false; + } + length = parse_int("parse_tag_and_count"); + return !had_error(); + } + + // Parse a sequence of raw data encoded as bytes and return the + // resulting data. + char* parse_data(const char* tag, int& length) { + if (!parse_tag_and_count(tag, length)) { + return NULL; + } + + char * result = NEW_RESOURCE_ARRAY(char, length); + for (int i = 0; i < length; i++) { + int val = parse_int("data"); + result[i] = val; + } + return result; + } + + // Parse a standard chunk of data emitted as: + // 'tag' # # ... + // Where each # is an intptr_t item + intptr_t* parse_intptr_data(const char* tag, int& length) { + if (!parse_tag_and_count(tag, length)) { + return NULL; + } + + intptr_t* result = NEW_RESOURCE_ARRAY(intptr_t, length); + for (int i = 0; i < length; i++) { + skip_ws(); + intptr_t val = parse_intptr_t("data"); + result[i] = val; + } + return result; + } + + // Parse a possibly quoted version of a symbol into a symbolOop + Symbol* parse_symbol(TRAPS) { + const char* str = parse_escaped_string(); + if (str != NULL) { + Symbol* sym = SymbolTable::lookup(str, (int)strlen(str), CHECK_NULL); + return sym; + } + return NULL; + } + + // Parse a valid klass name and look it up + Klass* parse_klass(TRAPS) { + const char* str = parse_escaped_string(); + Symbol* klass_name = SymbolTable::lookup(str, (int)strlen(str), CHECK_NULL); + if (klass_name != NULL) { + Klass* k = SystemDictionary::resolve_or_fail(klass_name, loader, protection_domain, true, THREAD); + if (HAS_PENDING_EXCEPTION) { + oop throwable = PENDING_EXCEPTION; + java_lang_Throwable::print(throwable, tty); + tty->cr(); + report_error(str); + return NULL; + } + return k; + } + return NULL; + } + + // Lookup a klass + Klass* resolve_klass(const char* klass, TRAPS) { + Symbol* klass_name = SymbolTable::lookup(klass, (int)strlen(klass), CHECK_NULL); + return SystemDictionary::resolve_or_fail(klass_name, loader, protection_domain, true, CHECK_NULL); + } + + // Parse the standard tuple of + Method* parse_method(TRAPS) { + InstanceKlass* k = (InstanceKlass*)parse_klass(CHECK_NULL); + Symbol* method_name = parse_symbol(CHECK_NULL); + Symbol* method_signature = parse_symbol(CHECK_NULL); + Method* m = k->find_method(method_name, method_signature); + if (m == NULL) { + report_error("can't find method"); + } + return m; + } + + // Process each line of the replay file executing each command until + // the file ends. + void process(TRAPS) { + line_no = 1; + int pos = 0; + int c = getc(stream); + while(c != EOF) { + if (pos + 1 >= buffer_length) { + int newl = buffer_length * 2; + char* newb = NEW_RESOURCE_ARRAY(char, newl); + memcpy(newb, buffer, pos); + buffer = newb; + buffer_length = newl; + } + if (c == '\n') { + // null terminate it, reset the pointer and process the line + buffer[pos] = '\0'; + buffer_end = pos++; + bufptr = buffer; + process_command(CHECK); + if (had_error()) { + tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message); + tty->print_cr("%s", buffer); + assert(false, "error"); + return; + } + pos = 0; + buffer_end = 0; + line_no++; + } else if (c == '\r') { + // skip LF + } else { + buffer[pos++] = c; + } + c = getc(stream); + } + } + + void process_command(TRAPS) { + char* cmd = parse_string(); + if (cmd == NULL) { + return; + } + if (strcmp("#", cmd) == 0) { + // ignore + } else if (strcmp("compile", cmd) == 0) { + process_compile(CHECK); + } else if (strcmp("ciMethod", cmd) == 0) { + process_ciMethod(CHECK); + } else if (strcmp("ciMethodData", cmd) == 0) { + process_ciMethodData(CHECK); + } else if (strcmp("staticfield", cmd) == 0) { + process_staticfield(CHECK); + } else if (strcmp("ciInstanceKlass", cmd) == 0) { + process_ciInstanceKlass(CHECK); + } else if (strcmp("instanceKlass", cmd) == 0) { + process_instanceKlass(CHECK); +#if INCLUDE_JVMTI + } else if (strcmp("JvmtiExport", cmd) == 0) { + process_JvmtiExport(CHECK); +#endif // INCLUDE_JVMTI + } else { + report_error("unknown command"); + } + } + + // compile + void process_compile(TRAPS) { + // methodHandle method; + Method* method = parse_method(CHECK); + int entry_bci = parse_int("entry_bci"); + Klass* k = method->method_holder(); + ((InstanceKlass*)k)->initialize(THREAD); + if (HAS_PENDING_EXCEPTION) { + oop throwable = PENDING_EXCEPTION; + java_lang_Throwable::print(throwable, tty); + tty->cr(); + if (ReplayIgnoreInitErrors) { + CLEAR_PENDING_EXCEPTION; + ((InstanceKlass*)k)->set_init_state(InstanceKlass::fully_initialized); + } else { + return; + } + } + // Make sure the existence of a prior compile doesn't stop this one + nmethod* nm = (entry_bci != InvocationEntryBci) ? method->lookup_osr_nmethod_for(entry_bci, CompLevel_full_optimization, true) : method->code(); + if (nm != NULL) { + nm->make_not_entrant(); + } + replay_state = this; + CompileBroker::compile_method(method, entry_bci, CompLevel_full_optimization, + methodHandle(), 0, "replay", THREAD); + replay_state = NULL; + reset(); + } + + // ciMethod + // + // + void process_ciMethod(TRAPS) { + Method* method = parse_method(CHECK); + ciMethodRecord* rec = new_ciMethod(method); + rec->invocation_counter = parse_int("invocation_counter"); + rec->backedge_counter = parse_int("backedge_counter"); + rec->interpreter_invocation_count = parse_int("interpreter_invocation_count"); + rec->interpreter_throwout_count = parse_int("interpreter_throwout_count"); + rec->instructions_size = parse_int("instructions_size"); + } + + // ciMethodData orig # # ... data # # ... oops + void process_ciMethodData(TRAPS) { + Method* method = parse_method(CHECK); + /* jsut copied from Method, to build interpret data*/ + if (InstanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) { + return; + } + // methodOopDesc::build_interpreter_method_data(method, CHECK); + { + // Grab a lock here to prevent multiple + // MethodData*s from being created. + MutexLocker ml(MethodData_lock, THREAD); + if (method->method_data() == NULL) { + ClassLoaderData* loader_data = method->method_holder()->class_loader_data(); + MethodData* method_data = MethodData::allocate(loader_data, method, CHECK); + method->set_method_data(method_data); + } + } + + // collect and record all the needed information for later + ciMethodDataRecord* rec = new_ciMethodData(method); + rec->state = parse_int("state"); + rec->current_mileage = parse_int("current_mileage"); + + rec->orig_data = parse_data("orig", rec->orig_data_length); + if (rec->orig_data == NULL) { + return; + } + rec->data = parse_intptr_data("data", rec->data_length); + if (rec->data == NULL) { + return; + } + if (!parse_tag_and_count("oops", rec->oops_length)) { + return; + } + rec->oops_handles = NEW_RESOURCE_ARRAY(jobject, rec->oops_length); + rec->oops_offsets = NEW_RESOURCE_ARRAY(int, rec->oops_length); + for (int i = 0; i < rec->oops_length; i++) { + int offset = parse_int("offset"); + if (had_error()) { + return; + } + Klass* k = parse_klass(CHECK); + rec->oops_offsets[i] = offset; + rec->oops_handles[i] = (jobject)(new KlassHandle(THREAD, k)); + } + } + + // instanceKlass + // + // Loads and initializes the klass 'name'. This can be used to + // create particular class loading environments + void process_instanceKlass(TRAPS) { + // just load the referenced class + Klass* k = parse_klass(CHECK); + } + + // ciInstanceKlass tag # # # ... + // + // Load the klass 'name' and link or initialize it. Verify that the + // constant pool is the same length as 'length' and make sure the + // constant pool tags are in the same state. + void process_ciInstanceKlass(TRAPS) { + InstanceKlass* k = (InstanceKlass *)parse_klass(CHECK); + int is_linked = parse_int("is_linked"); + int is_initialized = parse_int("is_initialized"); + int length = parse_int("length"); + if (is_initialized) { + k->initialize(THREAD); + if (HAS_PENDING_EXCEPTION) { + oop throwable = PENDING_EXCEPTION; + java_lang_Throwable::print(throwable, tty); + tty->cr(); + if (ReplayIgnoreInitErrors) { + CLEAR_PENDING_EXCEPTION; + k->set_init_state(InstanceKlass::fully_initialized); + } else { + return; + } + } + } else if (is_linked) { + k->link_class(CHECK); + } + ConstantPool* cp = k->constants(); + if (length != cp->length()) { + report_error("constant pool length mismatch: wrong class files?"); + return; + } + + int parsed_two_word = 0; + for (int i = 1; i < length; i++) { + int tag = parse_int("tag"); + if (had_error()) { + return; + } + switch (cp->tag_at(i).value()) { + case JVM_CONSTANT_UnresolvedClass: { + if (tag == JVM_CONSTANT_Class) { + tty->print_cr("Resolving klass %s at %d", cp->unresolved_klass_at(i)->as_utf8(), i); + Klass* k = cp->klass_at(i, CHECK); + } + break; + } + case JVM_CONSTANT_Long: + case JVM_CONSTANT_Double: + parsed_two_word = i + 1; + + case JVM_CONSTANT_ClassIndex: + case JVM_CONSTANT_StringIndex: + case JVM_CONSTANT_String: + case JVM_CONSTANT_UnresolvedClassInError: + case JVM_CONSTANT_Fieldref: + case JVM_CONSTANT_Methodref: + case JVM_CONSTANT_InterfaceMethodref: + case JVM_CONSTANT_NameAndType: + case JVM_CONSTANT_Utf8: + case JVM_CONSTANT_Integer: + case JVM_CONSTANT_Float: + if (tag != cp->tag_at(i).value()) { + report_error("tag mismatch: wrong class files?"); + return; + } + break; + + case JVM_CONSTANT_Class: + if (tag == JVM_CONSTANT_Class) { + } else if (tag == JVM_CONSTANT_UnresolvedClass) { + tty->print_cr("Warning: entry was unresolved in the replay data"); + } else { + report_error("Unexpected tag"); + return; + } + break; + + case 0: + if (parsed_two_word == i) continue; + + default: + ShouldNotReachHere(); + break; + } + + } + } + + // Initialize a class and fill in the value for a static field. + // This is useful when the compile was dependent on the value of + // static fields but it's impossible to properly rerun the static + // initiailizer. + void process_staticfield(TRAPS) { + InstanceKlass* k = (InstanceKlass *)parse_klass(CHECK); + + if (ReplaySuppressInitializers == 0 || + ReplaySuppressInitializers == 2 && k->class_loader() == NULL) { + return; + } + + assert(k->is_initialized(), "must be"); + + const char* field_name = parse_escaped_string();; + const char* field_signature = parse_string(); + fieldDescriptor fd; + Symbol* name = SymbolTable::lookup(field_name, (int)strlen(field_name), CHECK); + Symbol* sig = SymbolTable::lookup(field_signature, (int)strlen(field_signature), CHECK); + if (!k->find_local_field(name, sig, &fd) || + !fd.is_static() || + fd.has_initial_value()) { + report_error(field_name); + return; + } + + oop java_mirror = k->java_mirror(); + if (field_signature[0] == '[') { + int length = parse_int("array length"); + oop value = NULL; + + if (field_signature[1] == '[') { + // multi dimensional array + ArrayKlass* kelem = (ArrayKlass *)parse_klass(CHECK); + int rank = 0; + while (field_signature[rank] == '[') { + rank++; + } + int* dims = NEW_RESOURCE_ARRAY(int, rank); + dims[0] = length; + for (int i = 1; i < rank; i++) { + dims[i] = 1; // These aren't relevant to the compiler + } + value = kelem->multi_allocate(rank, dims, CHECK); + } else { + if (strcmp(field_signature, "[B") == 0) { + value = oopFactory::new_byteArray(length, CHECK); + } else if (strcmp(field_signature, "[Z") == 0) { + value = oopFactory::new_boolArray(length, CHECK); + } else if (strcmp(field_signature, "[C") == 0) { + value = oopFactory::new_charArray(length, CHECK); + } else if (strcmp(field_signature, "[S") == 0) { + value = oopFactory::new_shortArray(length, CHECK); + } else if (strcmp(field_signature, "[F") == 0) { + value = oopFactory::new_singleArray(length, CHECK); + } else if (strcmp(field_signature, "[D") == 0) { + value = oopFactory::new_doubleArray(length, CHECK); + } else if (strcmp(field_signature, "[I") == 0) { + value = oopFactory::new_intArray(length, CHECK); + } else if (strcmp(field_signature, "[J") == 0) { + value = oopFactory::new_longArray(length, CHECK); + } else if (field_signature[0] == '[' && field_signature[1] == 'L') { + KlassHandle kelem = resolve_klass(field_signature + 1, CHECK); + value = oopFactory::new_objArray(kelem(), length, CHECK); + } else { + report_error("unhandled array staticfield"); + } + } + java_mirror->obj_field_put(fd.offset(), value); + } else { + const char* string_value = parse_escaped_string(); + if (strcmp(field_signature, "I") == 0) { + int value = atoi(string_value); + java_mirror->int_field_put(fd.offset(), value); + } else if (strcmp(field_signature, "B") == 0) { + int value = atoi(string_value); + java_mirror->byte_field_put(fd.offset(), value); + } else if (strcmp(field_signature, "C") == 0) { + int value = atoi(string_value); + java_mirror->char_field_put(fd.offset(), value); + } else if (strcmp(field_signature, "S") == 0) { + int value = atoi(string_value); + java_mirror->short_field_put(fd.offset(), value); + } else if (strcmp(field_signature, "Z") == 0) { + int value = atol(string_value); + java_mirror->bool_field_put(fd.offset(), value); + } else if (strcmp(field_signature, "J") == 0) { + jlong value; + if (sscanf(string_value, INT64_FORMAT, &value) != 1) { + fprintf(stderr, "Error parsing long: %s\n", string_value); + return; + } + java_mirror->long_field_put(fd.offset(), value); + } else if (strcmp(field_signature, "F") == 0) { + float value = atof(string_value); + java_mirror->float_field_put(fd.offset(), value); + } else if (strcmp(field_signature, "D") == 0) { + double value = atof(string_value); + java_mirror->double_field_put(fd.offset(), value); + } else if (strcmp(field_signature, "Ljava/lang/String;") == 0) { + Handle value = java_lang_String::create_from_str(string_value, CHECK); + java_mirror->obj_field_put(fd.offset(), value()); + } else if (field_signature[0] == 'L') { + Symbol* klass_name = SymbolTable::lookup(field_signature, (int)strlen(field_signature), CHECK); + KlassHandle kelem = resolve_klass(field_signature, CHECK); + oop value = ((InstanceKlass*)kelem())->allocate_instance(CHECK); + java_mirror->obj_field_put(fd.offset(), value); + } else { + report_error("unhandled staticfield"); + } + } + } + +#if INCLUDE_JVMTI + void process_JvmtiExport(TRAPS) { + const char* field = parse_string(); + bool value = parse_int("JvmtiExport flag") != 0; + if (strcmp(field, "can_access_local_variables") == 0) { + JvmtiExport::set_can_access_local_variables(value); + } else if (strcmp(field, "can_hotswap_or_post_breakpoint") == 0) { + JvmtiExport::set_can_hotswap_or_post_breakpoint(value); + } else if (strcmp(field, "can_post_on_exceptions") == 0) { + JvmtiExport::set_can_post_on_exceptions(value); + } else { + report_error("Unrecognized JvmtiExport directive"); + } + } +#endif // INCLUDE_JVMTI + + // Create and initialize a record for a ciMethod + ciMethodRecord* new_ciMethod(Method* method) { + ciMethodRecord* rec = NEW_RESOURCE_OBJ(ciMethodRecord); + rec->klass = method->method_holder()->name()->as_utf8(); + rec->method = method->name()->as_utf8(); + rec->signature = method->signature()->as_utf8(); + ci_method_records.append(rec); + return rec; + } + + // Lookup data for a ciMethod + ciMethodRecord* find_ciMethodRecord(Method* method) { + const char* klass_name = method->method_holder()->name()->as_utf8(); + const char* method_name = method->name()->as_utf8(); + const char* signature = method->signature()->as_utf8(); + for (int i = 0; i < ci_method_records.length(); i++) { + ciMethodRecord* rec = ci_method_records.at(i); + if (strcmp(rec->klass, klass_name) == 0 && + strcmp(rec->method, method_name) == 0 && + strcmp(rec->signature, signature) == 0) { + return rec; + } + } + return NULL; + } + + // Create and initialize a record for a ciMethodData + ciMethodDataRecord* new_ciMethodData(Method* method) { + ciMethodDataRecord* rec = NEW_RESOURCE_OBJ(ciMethodDataRecord); + rec->klass = method->method_holder()->name()->as_utf8(); + rec->method = method->name()->as_utf8(); + rec->signature = method->signature()->as_utf8(); + ci_method_data_records.append(rec); + return rec; + } + + // Lookup data for a ciMethodData + ciMethodDataRecord* find_ciMethodDataRecord(Method* method) { + const char* klass_name = method->method_holder()->name()->as_utf8(); + const char* method_name = method->name()->as_utf8(); + const char* signature = method->signature()->as_utf8(); + for (int i = 0; i < ci_method_data_records.length(); i++) { + ciMethodDataRecord* rec = ci_method_data_records.at(i); + if (strcmp(rec->klass, klass_name) == 0 && + strcmp(rec->method, method_name) == 0 && + strcmp(rec->signature, signature) == 0) { + return rec; + } + } + return NULL; + } + + const char* error_message() { + return _error_message; + } + + void reset() { + _error_message = NULL; + ci_method_records.clear(); + ci_method_data_records.clear(); + } + + // Take an ascii string contain \u#### escapes and convert it to utf8 + // in place. + static void unescape_string(char* value) { + char* from = value; + char* to = value; + while (*from != '\0') { + if (*from != '\\') { + *from++ = *to++; + } else { + switch (from[1]) { + case 'u': { + from += 2; + jchar value=0; + for (int i=0; i<4; i++) { + char c = *from++; + switch (c) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + value = (value << 4) + c - '0'; + break; + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': + value = (value << 4) + 10 + c - 'a'; + break; + case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': + value = (value << 4) + 10 + c - 'A'; + break; + default: + ShouldNotReachHere(); + } + } + UNICODE::convert_to_utf8(&value, 1, to); + to++; + break; + } + case 't': *to++ = '\t'; from += 2; break; + case 'n': *to++ = '\n'; from += 2; break; + case 'r': *to++ = '\r'; from += 2; break; + case 'f': *to++ = '\f'; from += 2; break; + default: + ShouldNotReachHere(); + } + } + } + *from = *to; + } +}; + +void ciReplay::replay(TRAPS) { + int exit_code = replay_impl(THREAD); + + Threads::destroy_vm(); + + vm_exit(exit_code); +} + +int ciReplay::replay_impl(TRAPS) { + HandleMark hm; + ResourceMark rm; + // Make sure we don't run with background compilation + BackgroundCompilation = false; + + if (ReplaySuppressInitializers > 2) { + // ReplaySuppressInitializers > 2 means that we want to allow + // normal VM bootstrap but once we get into the replay itself + // don't allow any intializers to be run. + ReplaySuppressInitializers = 1; + } + + // Load and parse the replay data + CompileReplay rp(ReplayDataFile, THREAD); + int exit_code = 0; + if (rp.can_replay()) { + rp.process(THREAD); + } else { + exit_code = 1; + return exit_code; + } + + if (HAS_PENDING_EXCEPTION) { + oop throwable = PENDING_EXCEPTION; + CLEAR_PENDING_EXCEPTION; + java_lang_Throwable::print(throwable, tty); + tty->cr(); + java_lang_Throwable::print_stack_trace(throwable, tty); + tty->cr(); + exit_code = 2; + } + + if (rp.had_error()) { + tty->print_cr("Failed on %s", rp.error_message()); + exit_code = 1; + } + return exit_code; +} + + +void ciReplay::initialize(ciMethodData* m) { + if (replay_state == NULL) { + return; + } + + ASSERT_IN_VM; + ResourceMark rm; + + Method* method = m->get_MethodData()->method(); + ciMethodDataRecord* rec = replay_state->find_ciMethodDataRecord(method); + if (rec == NULL) { + // This indicates some mismatch with the original environment and + // the replay environment though it's not always enough to + // interfere with reproducing a bug + tty->print_cr("Warning: requesting ciMethodData record for method with no data: "); + method->print_name(tty); + tty->cr(); + } else { + m->_state = rec->state; + m->_current_mileage = rec->current_mileage; + if (rec->data_length != 0) { + assert(m->_data_size == rec->data_length * (int)sizeof(rec->data[0]), "must agree"); + + // Write the correct ciObjects back into the profile data + ciEnv* env = ciEnv::current(); + for (int i = 0; i < rec->oops_length; i++) { + KlassHandle *h = (KlassHandle *)rec->oops_handles[i]; + *(ciMetadata**)(rec->data + rec->oops_offsets[i]) = + env->get_metadata((*h)()); + } + // Copy the updated profile data into place as intptr_ts +#ifdef _LP64 + Copy::conjoint_jlongs_atomic((jlong *)rec->data, (jlong *)m->_data, rec->data_length); +#else + Copy::conjoint_jints_atomic((jint *)rec->data, (jint *)m->_data, rec->data_length); +#endif + } + + // copy in the original header + Copy::conjoint_jbytes(rec->orig_data, (char*)&m->_orig, rec->orig_data_length); + } +} + + +bool ciReplay::should_not_inline(ciMethod* method) { + if (replay_state == NULL) { + return false; + } + + VM_ENTRY_MARK; + // ciMethod without a record shouldn't be inlined. + return replay_state->find_ciMethodRecord(method->get_Method()) == NULL; +} + + +void ciReplay::initialize(ciMethod* m) { + if (replay_state == NULL) { + return; + } + + ASSERT_IN_VM; + ResourceMark rm; + + Method* method = m->get_Method(); + ciMethodRecord* rec = replay_state->find_ciMethodRecord(method); + if (rec == NULL) { + // This indicates some mismatch with the original environment and + // the replay environment though it's not always enough to + // interfere with reproducing a bug + tty->print_cr("Warning: requesting ciMethod record for method with no data: "); + method->print_name(tty); + tty->cr(); + } else { + // m->_instructions_size = rec->instructions_size; + m->_instructions_size = -1; + m->_interpreter_invocation_count = rec->interpreter_invocation_count; + m->_interpreter_throwout_count = rec->interpreter_throwout_count; + method->invocation_counter()->_counter = rec->invocation_counter; + method->backedge_counter()->_counter = rec->backedge_counter; + } +} + +bool ciReplay::is_loaded(Method* method) { + if (replay_state == NULL) { + return true; + } + + ASSERT_IN_VM; + ResourceMark rm; + + ciMethodRecord* rec = replay_state->find_ciMethodRecord(method); + return rec != NULL; +} +#endif diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciReplay.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/ci/ciReplay.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_CI_CIREPLAY_HPP +#define SHARE_VM_CI_CIREPLAY_HPP + +#include "ci/ciMethod.hpp" + +// ciReplay + +class ciReplay { + CI_PACKAGE_ACCESS + +#ifdef ASSERT + private: + static int replay_impl(TRAPS); + + public: + static void replay(TRAPS); + + // These are used by the CI to fill in the cached data from the + // replay file when replaying compiles. + static void initialize(ciMethodData* method); + static void initialize(ciMethod* method); + + static bool is_loaded(Method* method); + static bool is_loaded(Klass* klass); + + static bool should_not_inline(ciMethod* method); + +#endif +}; + +#endif // SHARE_VM_CI_CIREPLAY_HPP diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciSymbol.cpp --- a/src/share/vm/ci/ciSymbol.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciSymbol.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -63,6 +63,11 @@ return s->as_utf8(); } +// The text of the symbol as a null-terminated C string. +const char* ciSymbol::as_quoted_ascii() { + GUARDED_VM_QUICK_ENTRY(return get_symbol()->as_quoted_ascii();) +} + // ------------------------------------------------------------------ // ciSymbol::base const jbyte* ciSymbol::base() { diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciSymbol.hpp --- a/src/share/vm/ci/ciSymbol.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciSymbol.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -73,6 +73,9 @@ const char* as_utf8(); int utf8_length(); + // The text of the symbol as ascii with all non-printable characters quoted as \u#### + const char* as_quoted_ascii(); + // Return the i-th utf8 byte, where i < utf8_length int byte_at(int i); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciType.cpp --- a/src/share/vm/ci/ciType.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciType.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -45,7 +45,7 @@ } ciType::ciType(KlassHandle k) : ciMetadata(k()) { - _basic_type = Klass::cast(k())->oop_is_array() ? T_ARRAY : T_OBJECT; + _basic_type = k()->oop_is_array() ? T_ARRAY : T_OBJECT; } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/ci/ciUtilities.hpp --- a/src/share/vm/ci/ciUtilities.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/ci/ciUtilities.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,6 +80,9 @@ #define GUARDED_VM_ENTRY(action) \ {if (IS_IN_VM) { action } else { VM_ENTRY_MARK; { action }}} +#define GUARDED_VM_QUICK_ENTRY(action) \ + {if (IS_IN_VM) { action } else { VM_QUICK_ENTRY_MARK; { action }}} + // Redefine this later. #define KILL_COMPILE_ON_FATAL_(result) \ THREAD); \ diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/classfile/classFileParser.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -824,7 +824,7 @@ interf = KlassHandle(THREAD, k); } - if (!Klass::cast(interf())->is_interface()) { + if (!interf()->is_interface()) { THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", NULL); } if (InstanceKlass::cast(interf())->has_default_methods()) { @@ -3831,7 +3831,7 @@ if (TraceClassResolution) { ResourceMark rm; // print out the superclass. - const char * from = Klass::cast(this_klass())->external_name(); + const char * from = this_klass()->external_name(); if (this_klass->java_super() != NULL) { tty->print("RESOLVE %s %s (super)\n", from, InstanceKlass::cast(this_klass->java_super())->external_name()); } @@ -3982,13 +3982,13 @@ // java.lang.Object has empty default constructor k->set_has_vanilla_constructor(); } else { - if (Klass::cast(super)->has_vanilla_constructor() && + if (super->has_vanilla_constructor() && _has_vanilla_constructor) { k->set_has_vanilla_constructor(); } #ifdef ASSERT bool v = false; - if (Klass::cast(super)->has_vanilla_constructor()) { + if (super->has_vanilla_constructor()) { Method* constructor = k->find_method(vmSymbols::object_initializer_name( ), vmSymbols::void_method_signature()); if (constructor != NULL && constructor->is_vanilla_constructor()) { @@ -4130,7 +4130,7 @@ int lng = local_interfaces->length(); for (int i = lng - 1; i >= 0; i--) { Klass* k = local_interfaces->at(i); - assert (k != NULL && Klass::cast(k)->is_interface(), "invalid interface"); + assert (k != NULL && k->is_interface(), "invalid interface"); if (!Reflection::verify_class_access(this_klass(), k, false)) { ResourceMark rm(THREAD); Exceptions::fthrow( diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/classfile/classLoader.cpp --- a/src/share/vm/classfile/classLoader.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/classfile/classLoader.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -605,8 +605,10 @@ // Load zip library char path[JVM_MAXPATHLEN]; char ebuf[1024]; - os::dll_build_name(path, sizeof(path), Arguments::get_dll_dir(), "zip"); - void* handle = os::dll_load(path, ebuf, sizeof ebuf); + void* handle = NULL; + if (os::dll_build_name(path, sizeof(path), Arguments::get_dll_dir(), "zip")) { + handle = os::dll_load(path, ebuf, sizeof ebuf); + } if (handle == NULL) { vm_exit_during_initialization("Unable to load ZIP library", path); } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/classfile/dictionary.cpp --- a/src/share/vm/classfile/dictionary.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/classfile/dictionary.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -346,7 +346,7 @@ KlassHandle obj) { assert_locked_or_safepoint(SystemDictionary_lock); assert(obj() != NULL, "adding NULL obj"); - assert(Klass::cast(obj())->name() == class_name, "sanity check on name"); + assert(obj()->name() == class_name, "sanity check on name"); unsigned int hash = compute_hash(class_name, loader_data); int index = hash_to_index(hash); @@ -553,7 +553,7 @@ bool is_defining_class = (loader_data == InstanceKlass::cast(e)->class_loader_data()); tty->print("%s%s", is_defining_class ? " " : "^", - Klass::cast(e)->external_name()); + e->external_name()); tty->print(", loader "); loader_data->print_value(); @@ -575,7 +575,7 @@ probe = probe->next()) { Klass* e = probe->klass(); ClassLoaderData* loader_data = probe->loader_data(); - guarantee(Klass::cast(e)->oop_is_instance(), + guarantee(e->oop_is_instance(), "Verify of system dictionary failed"); // class loader must be present; a null class loader is the // boostrap loader diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/classfile/javaClasses.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -348,6 +348,22 @@ return java_lang_String::to_hash(value->char_at_addr(offset), length); } +char* java_lang_String::as_quoted_ascii(oop java_string) { + typeArrayOop value = java_lang_String::value(java_string); + int offset = java_lang_String::offset(java_string); + int length = java_lang_String::length(java_string); + + jchar* base = (length == 0) ? NULL : value->char_at_addr(offset); + if (base == NULL) return NULL; + + int result_length = UNICODE::quoted_ascii_length(base, length) + 1; + char* result = NEW_RESOURCE_ARRAY(char, result_length); + UNICODE::as_quoted_ascii(base, length, result, result_length); + assert(result_length >= length + 1, "must not be shorter"); + assert(result_length == (int)strlen(result) + 1, "must match"); + return result; +} + unsigned int java_lang_String::hash_string(oop java_string) { int length = java_lang_String::length(java_string); // Zero length string doesn't hash necessarily hash to zero. @@ -545,7 +561,7 @@ assert(k->oop_is_objArray(), "Must be"); Klass* element_klass = ObjArrayKlass::cast(k())->element_klass(); assert(element_klass != NULL, "Must have an element klass"); - comp_mirror = Klass::cast(element_klass)->java_mirror(); + comp_mirror = element_klass->java_mirror(); } assert(comp_mirror.not_null(), "must have a mirror"); @@ -628,8 +644,8 @@ name = vmSymbols::type_signature(primitive_type(java_class)); } else { Klass* k = as_Klass(java_class); - is_instance = Klass::cast(k)->oop_is_instance(); - name = Klass::cast(k)->name(); + is_instance = k->oop_is_instance(); + name = k->name(); } if (name == NULL) { st->print(""); @@ -651,12 +667,12 @@ name->increment_refcount(); } else { Klass* k = as_Klass(java_class); - if (!Klass::cast(k)->oop_is_instance()) { - name = Klass::cast(k)->name(); + if (!k->oop_is_instance()) { + name = k->name(); name->increment_refcount(); } else { ResourceMark rm; - const char* sigstr = Klass::cast(k)->signature_name(); + const char* sigstr = k->signature_name(); int siglen = (int) strlen(sigstr); if (!intern_if_not_found) { name = SymbolTable::probe(sigstr, siglen); @@ -671,13 +687,13 @@ Klass* java_lang_Class::array_klass(oop java_class) { Klass* k = ((Klass*)java_class->metadata_field(_array_klass_offset)); - assert(k == NULL || k->is_klass() && Klass::cast(k)->oop_is_array(), "should be array klass"); + assert(k == NULL || k->is_klass() && k->oop_is_array(), "should be array klass"); return k; } void java_lang_Class::set_array_klass(oop java_class, Klass* klass) { - assert(klass->is_klass() && Klass::cast(klass)->oop_is_array(), "should be array klass"); + assert(klass->is_klass() && klass->oop_is_array(), "should be array klass"); java_class->metadata_field_put(_array_klass_offset, klass); } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/classfile/javaClasses.hpp --- a/src/share/vm/classfile/javaClasses.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/classfile/javaClasses.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -154,6 +154,8 @@ static char* as_utf8_string(oop java_string, int start, int len); static char* as_platform_dependent_str(Handle java_string, TRAPS); static jchar* as_unicode_string(oop java_string, int& length); + // produce an ascii string with all other values quoted using \u#### + static char* as_quoted_ascii(oop java_string); // Compute the hash value for a java.lang.String object which would // contain the characters passed in. @@ -912,7 +914,7 @@ // Testers static bool is_subclass(Klass* klass) { - return Klass::cast(klass)->is_subclass_of(SystemDictionary::MethodHandle_klass()); + return klass->is_subclass_of(SystemDictionary::MethodHandle_klass()); } static bool is_instance(oop obj) { return obj != NULL && is_subclass(obj->klass()); @@ -942,7 +944,7 @@ // Testers static bool is_subclass(Klass* klass) { return SystemDictionary::LambdaForm_klass() != NULL && - Klass::cast(klass)->is_subclass_of(SystemDictionary::LambdaForm_klass()); + klass->is_subclass_of(SystemDictionary::LambdaForm_klass()); } static bool is_instance(oop obj) { return obj != NULL && is_subclass(obj->klass()); @@ -1004,7 +1006,7 @@ // Testers static bool is_subclass(Klass* klass) { - return Klass::cast(klass)->is_subclass_of(SystemDictionary::MemberName_klass()); + return klass->is_subclass_of(SystemDictionary::MemberName_klass()); } static bool is_instance(oop obj) { return obj != NULL && is_subclass(obj->klass()); @@ -1090,7 +1092,7 @@ // Testers static bool is_subclass(Klass* klass) { - return Klass::cast(klass)->is_subclass_of(SystemDictionary::CallSite_klass()); + return klass->is_subclass_of(SystemDictionary::CallSite_klass()); } static bool is_instance(oop obj) { return obj != NULL && is_subclass(obj->klass()); @@ -1160,7 +1162,7 @@ // Testers static bool is_subclass(Klass* klass) { - return Klass::cast(klass)->is_subclass_of(SystemDictionary::ClassLoader_klass()); + return klass->is_subclass_of(SystemDictionary::ClassLoader_klass()); } static bool is_instance(oop obj) { return obj != NULL && is_subclass(obj->klass()); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/classfile/loaderConstraints.cpp --- a/src/share/vm/classfile/loaderConstraints.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/classfile/loaderConstraints.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -320,7 +320,7 @@ Handle loader) { LoaderConstraintEntry *p = *(find_loader_constraint(name, loader)); if (p != NULL && p->klass() != NULL) { - if (Klass::cast(p->klass())->oop_is_instance() && !InstanceKlass::cast(p->klass())->is_loaded()) { + if (p->klass()->oop_is_instance() && !InstanceKlass::cast(p->klass())->is_loaded()) { // Only return fully loaded classes. Classes found through the // constraints might still be in the process of loading. return NULL; diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/classfile/placeholders.cpp --- a/src/share/vm/classfile/placeholders.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/classfile/placeholders.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -45,7 +45,7 @@ entry->set_loadInstanceThreadQ(NULL); entry->set_defineThreadQ(NULL); entry->set_definer(NULL); - entry->set_instanceKlass(NULL); + entry->set_instance_klass(NULL); return entry; } @@ -188,7 +188,7 @@ void PlaceholderEntry::classes_do(KlassClosure* closure) { assert(klassname() != NULL, "should have a non-null klass"); if (_instanceKlass != NULL) { - closure->do_klass(InstanceKlass()); + closure->do_klass(instance_klass()); } } @@ -220,9 +220,9 @@ tty->print(", definer "); definer()->print_value(); } - if (InstanceKlass() != NULL) { + if (instance_klass() != NULL) { tty->print(", InstanceKlass "); - InstanceKlass()->print_value(); + instance_klass()->print_value(); } tty->print("\n"); tty->print("loadInstanceThreadQ threads:"); @@ -241,9 +241,9 @@ guarantee(loader_data() != NULL, "Must have been setup."); guarantee(loader_data()->class_loader() == NULL || loader_data()->class_loader()->is_instance(), "checking type of _loader"); - guarantee(InstanceKlass() == NULL - || Klass::cast(InstanceKlass())->oop_is_instance(), - "checking type of InstanceKlass result"); + guarantee(instance_klass() == NULL + || instance_klass()->oop_is_instance(), + "checking type of instance_klass result"); } void PlaceholderTable::verify() { diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/classfile/placeholders.hpp --- a/src/share/vm/classfile/placeholders.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/classfile/placeholders.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -191,8 +191,8 @@ Thread* definer() const {return _definer; } void set_definer(Thread* definer) { _definer = definer; } - Klass* InstanceKlass() const {return _instanceKlass; } - void set_instanceKlass(Klass* InstanceKlass) { _instanceKlass = InstanceKlass; } + Klass* instance_klass() const {return _instanceKlass; } + void set_instance_klass(Klass* ik) { _instanceKlass = ik; } SeenThread* superThreadQ() const { return _superThreadQ; } void set_superThreadQ(SeenThread* SeenThread) { _superThreadQ = SeenThread; } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/classfile/symbolTable.hpp --- a/src/share/vm/classfile/symbolTable.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/classfile/symbolTable.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -262,19 +262,14 @@ // The string table static StringTable* the_table() { return _the_table; } + // Size of one bucket in the string table. Used when checking for rollover. + static uint bucket_size() { return sizeof(HashtableBucket); } + static void create_table() { assert(_the_table == NULL, "One string table allowed."); _the_table = new StringTable(); } - static void create_table(HashtableBucket* t, int length, - int number_of_entries) { - assert(_the_table == NULL, "One string table allowed."); - assert((size_t)length == StringTableSize * sizeof(HashtableBucket), - "bad shared string size."); - _the_table = new StringTable(t, number_of_entries); - } - // GC support // Delete pointers to otherwise-unreachable objects. static void unlink(BoolObjectClosure* cl); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/classfile/systemDictionary.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -240,7 +240,7 @@ protection_domain, CHECK_NULL); if (k != NULL) { - k = Klass::cast(k)->array_klass(fd.dimension(), CHECK_NULL); + k = k->array_klass(fd.dimension(), CHECK_NULL); } } else { k = Universe::typeArrayKlassObj(t); @@ -328,8 +328,8 @@ if ((childk != NULL ) && (is_superclass) && ((quicksuperk = InstanceKlass::cast(childk)->super()) != NULL) && - ((Klass::cast(quicksuperk)->name() == class_name) && - (Klass::cast(quicksuperk)->class_loader() == class_loader()))) { + ((quicksuperk->name() == class_name) && + (quicksuperk->class_loader() == class_loader()))) { return quicksuperk; } else { PlaceholderEntry* probe = placeholders()->get_entry(p_index, p_hash, child_name, loader_data); @@ -928,7 +928,7 @@ k = SystemDictionary::find(fd.object_key(), class_loader, protection_domain, THREAD); } if (k != NULL) { - k = Klass::cast(k)->array_klass_or_null(fd.dimension()); + k = k->array_klass_or_null(fd.dimension()); } } else { k = find(class_name, class_loader, protection_domain, THREAD); @@ -1537,7 +1537,7 @@ // Only special cases allow parallel defines and can use other thread's results // Other cases fall through, and may run into duplicate defines // caught by finding an entry in the SystemDictionary - if ((UnsyncloadClass || is_parallelDefine(class_loader)) && (probe->InstanceKlass() != NULL)) { + if ((UnsyncloadClass || is_parallelDefine(class_loader)) && (probe->instance_klass() != NULL)) { probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS); placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, THREAD); SystemDictionary_lock->notify_all(); @@ -1545,7 +1545,7 @@ Klass* check = find_class(d_index, d_hash, name_h, loader_data); assert(check != NULL, "definer missed recording success"); #endif - return(instanceKlassHandle(THREAD, probe->InstanceKlass())); + return(instanceKlassHandle(THREAD, probe->instance_klass())); } else { // This thread will define the class (even if earlier thread tried and had an error) probe->set_definer(THREAD); @@ -1566,7 +1566,7 @@ linkage_exception = Handle(THREAD,PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION; } else { - probe->set_instanceKlass(k()); + probe->set_instance_klass(k()); } probe->set_definer(NULL); probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS); @@ -2149,7 +2149,7 @@ } // If element class already loaded, allocate array klass if (klass != NULL) { - klass = Klass::cast(klass)->array_klass_or_null(fd.dimension()); + klass = klass->array_klass_or_null(fd.dimension()); } } else { MutexLocker mu(SystemDictionary_lock, THREAD); @@ -2466,9 +2466,9 @@ Klass* sel_klass = java_lang_Class::as_Klass(mirror); mirror = NULL; // safety // Emulate ConstantPool::verify_constant_pool_resolve. - if (Klass::cast(sel_klass)->oop_is_objArray()) + if (sel_klass->oop_is_objArray()) sel_klass = ObjArrayKlass::cast(sel_klass)->bottom_klass(); - if (Klass::cast(sel_klass)->oop_is_instance()) { + if (sel_klass->oop_is_instance()) { KlassHandle sel_kh(THREAD, sel_klass); LinkResolver::check_klass_accessability(accessing_klass, sel_kh, CHECK_(empty)); } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/code/dependencies.cpp --- a/src/share/vm/code/dependencies.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/code/dependencies.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -552,7 +552,7 @@ } tty->print(" %s = %s", what, (put_star? "*": "")); if (arg.is_klass()) - tty->print("%s", Klass::cast((Klass*)arg.metadata_value())->external_name()); + tty->print("%s", ((Klass*)arg.metadata_value())->external_name()); else if (arg.is_method()) ((Method*)arg.metadata_value())->print_value(); else @@ -563,12 +563,13 @@ bool put_star = !Dependencies::is_concrete_klass(witness); tty->print_cr(" witness = %s%s", (put_star? "*": ""), - Klass::cast(witness)->external_name()); + witness->external_name()); } } void Dependencies::DepStream::log_dependency(Klass* witness) { if (_deps == NULL && xtty == NULL) return; // fast cutout for runtime + ResourceMark rm; int nargs = argument_count(); DepArgument args[max_arg_count]; for (int j = 0; j < nargs; j++) { @@ -808,7 +809,7 @@ if (!(m->is_public() || m->is_protected())) // The override story is complex when packages get involved. return true; // Must punt the assertion to true. - Klass* k = Klass::cast(ctxk); + Klass* k = ctxk; Method* lm = k->lookup_method(m->name(), m->signature()); if (lm == NULL && k->oop_is_instance()) { // It might be an abstract interface method, devoid of mirandas. @@ -835,7 +836,7 @@ } ResourceMark rm; tty->print_cr("Dependency method not found in the associated context:"); - tty->print_cr(" context = %s", Klass::cast(ctxk)->external_name()); + tty->print_cr(" context = %s", ctxk->external_name()); tty->print( " method = "); m->print_short_name(tty); tty->cr(); if (lm != NULL) { tty->print( " found = "); lm->print_short_name(tty); tty->cr(); @@ -1010,7 +1011,7 @@ for (int i = 0; i < num_participants(); i++) { Klass* part = participant(i); if (part == NULL) continue; - assert(changes.involves_context(part) == Klass::cast(new_type)->is_subtype_of(part), + assert(changes.involves_context(part) == new_type->is_subtype_of(part), "correct marking of participants, b/c new_type is unique"); if (changes.involves_context(part)) { // new guy is protected from this check by previous participant @@ -1146,7 +1147,7 @@ bool Dependencies::is_concrete_klass(Klass* k) { - if (Klass::cast(k)->is_abstract()) return false; + if (k->is_abstract()) return false; // %%% We could treat classes which are concrete but // have not yet been instantiated as virtually abstract. // This would require a deoptimization barrier on first instantiation. @@ -1705,12 +1706,12 @@ } bool KlassDepChange::involves_context(Klass* k) { - if (k == NULL || !Klass::cast(k)->oop_is_instance()) { + if (k == NULL || !k->oop_is_instance()) { return false; } InstanceKlass* ik = InstanceKlass::cast(k); bool is_contained = ik->is_marked_dependent(); - assert(is_contained == Klass::cast(new_type())->is_subtype_of(k), + assert(is_contained == new_type()->is_subtype_of(k), "correct marking of potential context types"); return is_contained; } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/code/nmethod.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -2568,9 +2568,8 @@ deps.print_dependency(); Klass* ctxk = deps.context_type(); if (ctxk != NULL) { - Klass* k = Klass::cast(ctxk); - if (k->oop_is_instance() && ((InstanceKlass*)k)->is_dependent_nmethod(this)) { - tty->print_cr(" [nmethod<=klass]%s", k->external_name()); + if (ctxk->oop_is_instance() && ((InstanceKlass*)ctxk)->is_dependent_nmethod(this)) { + tty->print_cr(" [nmethod<=klass]%s", ctxk->external_name()); } } deps.log_dependency(); // put it into the xml log also diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/compiler/disassembler.cpp --- a/src/share/vm/compiler/disassembler.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/compiler/disassembler.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -353,7 +353,7 @@ obj->print_value_on(st); if (st->count() == c) { // No output. (Can happen in product builds.) - st->print("(a %s)", Klass::cast(obj->klass())->external_name()); + st->print("(a %s)", obj->klass()->external_name()); } return; } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/interpreter/bytecodeInterpreter.cpp --- a/src/share/vm/interpreter/bytecodeInterpreter.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -2043,8 +2043,8 @@ if (objKlassOop != klassOf && !objKlassOop->is_subtype_of(klassOf)) { ResourceMark rm(THREAD); - const char* objName = Klass::cast(objKlassOop)->external_name(); - const char* klassName = Klass::cast(klassOf)->external_name(); + const char* objName = objKlassOop->external_name(); + const char* klassName = klassOf->external_name(); char* message = SharedRuntime::generate_class_cast_message( objName, klassName); VM_JAVA_ERROR(vmSymbols::java_lang_ClassCastException(), message); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/interpreter/interpreterRuntime.cpp --- a/src/share/vm/interpreter/interpreterRuntime.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -312,7 +312,7 @@ IRT_ENTRY(void, InterpreterRuntime::create_klass_exception(JavaThread* thread, char* name, oopDesc* obj)) ResourceMark rm(thread); - const char* klass_name = Klass::cast(obj->klass())->external_name(); + const char* klass_name = obj->klass()->external_name(); // lookup exception klass TempNewSymbol s = SymbolTable::new_symbol(name, CHECK); if (ProfileTraps) { @@ -341,7 +341,7 @@ ResourceMark rm(thread); char* message = SharedRuntime::generate_class_cast_message( - thread, Klass::cast(obj->klass())->external_name()); + thread, obj->klass()->external_name()); if (ProfileTraps) { note_trap(thread, Deoptimization::Reason_class_check, CHECK); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/interpreter/invocationCounter.hpp --- a/src/share/vm/interpreter/invocationCounter.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/interpreter/invocationCounter.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ class InvocationCounter VALUE_OBJ_CLASS_SPEC { friend class VMStructs; + friend class ciReplay; private: // bit no: |31 3| 2 | 1 0 | unsigned int _counter; // format: [count|carry|state] @@ -85,6 +86,8 @@ void set_carry(); // set the sticky carry bit void set_carry_flag() { _counter |= carry_mask; } + int raw_counter() { return _counter; } + // Accessors State state() const { return (State)(_counter & state_mask); } bool carry() const { return (_counter & carry_mask) != 0; } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/interpreter/linkResolver.cpp --- a/src/share/vm/interpreter/linkResolver.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/interpreter/linkResolver.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -203,7 +203,7 @@ Method* result_oop = klass->uncached_lookup_method(name, signature); result = methodHandle(THREAD, result_oop); while (!result.is_null() && result->is_static()) { - klass = KlassHandle(THREAD, Klass::cast(result->method_holder())->super()); + klass = KlassHandle(THREAD, result->method_holder()->super()); result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature)); } } @@ -428,7 +428,7 @@ // 3. method lookup failed ResourceMark rm(THREAD); THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(), - Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), + Method::name_and_sig_as_C_string(resolved_klass(), method_name, method_signature), nested_exception); @@ -448,7 +448,7 @@ if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), + Method::name_and_sig_as_C_string(resolved_klass(), method_name, method_signature)); } @@ -477,7 +477,7 @@ " \"%s\" the class loader (instance of %s) of the current class, %s," " and the class loader (instance of %s) for resolved class, %s, have" " different Class objects for the type %s used in the signature"; - char* sig = Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()),method_name,method_signature); + char* sig = Method::name_and_sig_as_C_string(resolved_klass(),method_name,method_signature); const char* loader1 = SystemDictionary::loader_name(loader()); char* current = InstanceKlass::cast(current_klass())->name()->as_C_string(); const char* loader2 = SystemDictionary::loader_name(class_loader()); @@ -505,7 +505,7 @@ if (!resolved_klass->is_interface()) { ResourceMark rm(THREAD); char buf[200]; - jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", Klass::cast(resolved_klass())->external_name()); + jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", resolved_klass()->external_name()); THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } @@ -519,7 +519,7 @@ // no method found ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(), - Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), + Method::name_and_sig_as_C_string(resolved_klass(), method_name, method_signature)); } @@ -540,7 +540,7 @@ "current class, %s, and the class loader (instance of %s) for " "resolved class, %s, have different Class objects for the type %s " "used in the signature"; - char* sig = Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()),method_name,method_signature); + char* sig = Method::name_and_sig_as_C_string(resolved_klass(),method_name,method_signature); const char* loader1 = SystemDictionary::loader_name(loader()); char* current = InstanceKlass::cast(current_klass())->name()->as_C_string(); const char* loader2 = SystemDictionary::loader_name(class_loader()); @@ -627,7 +627,7 @@ if (is_static != fd.is_static()) { ResourceMark rm(THREAD); char msg[200]; - jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", Klass::cast(resolved_klass())->external_name(), fd.name()->as_C_string()); + jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", resolved_klass()->external_name(), fd.name()->as_C_string()); THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg); } @@ -701,7 +701,7 @@ bool check_access, bool initialize_class, TRAPS) { methodHandle resolved_method; linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); - resolved_klass = KlassHandle(THREAD, Klass::cast(resolved_method->method_holder())); + resolved_klass = KlassHandle(THREAD, resolved_method->method_holder()); // Initialize klass (this should only happen if everything is ok) if (initialize_class && resolved_klass->should_be_initialized()) { @@ -725,7 +725,7 @@ if (!resolved_method->is_static()) { ResourceMark rm(THREAD); char buf[200]; - jio_snprintf(buf, sizeof(buf), "Expected static method %s", Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), + jio_snprintf(buf, sizeof(buf), "Expected static method %s", Method::name_and_sig_as_C_string(resolved_klass(), resolved_method->name(), resolved_method->signature())); THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); @@ -789,7 +789,7 @@ char buf[200]; jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", - Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), + Method::name_and_sig_as_C_string(resolved_klass(), resolved_method->name(), resolved_method->signature())); THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); @@ -829,7 +829,7 @@ if (sel_method.is_null()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), + Method::name_and_sig_as_C_string(resolved_klass(), resolved_method->name(), resolved_method->signature())); } @@ -840,7 +840,7 @@ if (sel_method->is_static()) { ResourceMark rm(THREAD); char buf[200]; - jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), + jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass(), resolved_method->name(), resolved_method->signature())); THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); @@ -850,7 +850,7 @@ if (sel_method->is_abstract()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), + Method::name_and_sig_as_C_string(resolved_klass(), sel_method->name(), sel_method->signature())); } @@ -881,7 +881,7 @@ if (resolved_method->is_static()) { ResourceMark rm(THREAD); char buf[200]; - jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), + jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass(), resolved_method->name(), resolved_method->signature())); THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); @@ -950,7 +950,7 @@ if (selected_method.is_null()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), + Method::name_and_sig_as_C_string(resolved_klass(), resolved_method->name(), resolved_method->signature())); } @@ -959,7 +959,7 @@ if (check_null_and_abstract && selected_method->is_abstract()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), + Method::name_and_sig_as_C_string(resolved_klass(), selected_method->name(), selected_method->signature())); } @@ -999,8 +999,8 @@ ResourceMark rm(THREAD); char buf[200]; jio_snprintf(buf, sizeof(buf), "Class %s does not implement the requested interface %s", - (Klass::cast(recv_klass()))->external_name(), - (Klass::cast(resolved_klass()))->external_name()); + recv_klass()->external_name(), + resolved_klass()->external_name()); THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } // do lookup based on receiver klass @@ -1012,7 +1012,7 @@ if (sel_method.is_null()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(Klass::cast(recv_klass()), + Method::name_and_sig_as_C_string(recv_klass(), resolved_method->name(), resolved_method->signature())); } @@ -1020,7 +1020,7 @@ if (!sel_method->is_public()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), - Method::name_and_sig_as_C_string(Klass::cast(recv_klass()), + Method::name_and_sig_as_C_string(recv_klass(), sel_method->name(), sel_method->signature())); } @@ -1028,7 +1028,7 @@ if (check_null_and_abstract && sel_method->is_abstract()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(Klass::cast(recv_klass()), + Method::name_and_sig_as_C_string(recv_klass(), sel_method->name(), sel_method->signature())); } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/memory/binaryTreeDictionary.cpp --- a/src/share/vm/memory/binaryTreeDictionary.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/memory/binaryTreeDictionary.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -239,7 +239,7 @@ } else { if (nextTC == NULL) { // Removing chunk at tail of list - link_tail(prevFC); + this->link_tail(prevFC); } // Chunk is interior to the list prevFC->link_after(nextTC); @@ -296,7 +296,7 @@ Chunk_t* fc = tail(); fc->link_after(chunk); - link_tail(chunk); + this->link_tail(chunk); assert(!tail() || size() == tail()->size(), "Wrong sized chunk in list"); FreeList_t::increment_count(); @@ -323,7 +323,7 @@ chunk->link_after(fc); } else { assert(tail() == NULL, "List is inconsistent"); - link_tail(chunk); + this->link_tail(chunk); } head()->link_after(chunk); assert(!head() || size() == head()->size(), "Wrong sized chunk in list"); @@ -940,7 +940,7 @@ void do_tree(TreeList* tl) { if (tl != NULL) { do_tree(tl->left()); - do_list(tl); + this->do_list(tl); do_tree(tl->right()); } } @@ -952,7 +952,7 @@ void do_tree(TreeList* tl) { if (tl != NULL) { do_tree(tl->right()); - do_list(tl); + this->do_list(tl); do_tree(tl->left()); } } @@ -1022,7 +1022,7 @@ bool do_tree(TreeList* tl) { if (tl != NULL) { if (do_tree(tl->right())) return true; - if (do_list(tl)) return true; + if (this->do_list(tl)) return true; if (do_tree(tl->left())) return true; } return false; diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/memory/metaspace.cpp --- a/src/share/vm/memory/metaspace.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/memory/metaspace.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -42,6 +42,10 @@ typedef BinaryTreeDictionary BlockTreeDictionary; typedef BinaryTreeDictionary ChunkTreeDictionary; +// Define this macro to enable slow integrity checking of +// the free chunk lists +const bool metaspace_slow_verify = false; + // Parameters for stress mode testing const uint metadata_deallocate_a_lot_block = 10; @@ -161,7 +165,17 @@ size_t sum_free_chunks_count(); void locked_verify_free_chunks_total(); + void slow_locked_verify_free_chunks_total() { + if (metaspace_slow_verify) { + locked_verify_free_chunks_total(); + } + } void locked_verify_free_chunks_count(); + void slow_locked_verify_free_chunks_count() { + if (metaspace_slow_verify) { + locked_verify_free_chunks_count(); + } + } void verify_free_chunks_count(); public: @@ -201,7 +215,17 @@ // Debug support void verify(); + void slow_verify() { + if (metaspace_slow_verify) { + verify(); + } + } void locked_verify(); + void slow_locked_verify() { + if (metaspace_slow_verify) { + locked_verify(); + } + } void verify_free_chunks_total(); void locked_print_free_chunks(outputStream* st); @@ -1507,7 +1531,7 @@ if (!UseConcMarkSweepGC && !SpaceManager::expand_lock()->is_locked()) { MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); - locked_verify_free_chunks_total(); + slow_locked_verify_free_chunks_total(); } #endif return _free_chunks_total; @@ -1524,10 +1548,10 @@ Mutex::_no_safepoint_check_flag); // This lock is only needed in debug because the verification // of the _free_chunks_totals walks the list of free chunks - locked_verify_free_chunks_count(); + slow_locked_verify_free_chunks_count(); } #endif - return _free_chunks_count; + return _free_chunks_count; } void ChunkManager::locked_verify_free_chunks_total() { @@ -1561,14 +1585,9 @@ } void ChunkManager::verify() { -#ifdef ASSERT - if (!UseConcMarkSweepGC) { - MutexLockerEx cl(SpaceManager::expand_lock(), - Mutex::_no_safepoint_check_flag); - locked_verify_free_chunks_total(); - locked_verify_free_chunks_count(); - } -#endif + MutexLockerEx cl(SpaceManager::expand_lock(), + Mutex::_no_safepoint_check_flag); + locked_verify(); } void ChunkManager::locked_verify() { @@ -1642,7 +1661,7 @@ free_list->set_head(chunk); // chunk is being returned to the chunk free list inc_free_chunks_total(chunk->capacity_word_size()); - locked_verify(); + slow_locked_verify(); } void ChunkManager::chunk_freelist_deallocate(Metachunk* chunk) { @@ -1650,8 +1669,8 @@ // manangement code for a Metaspace and does not hold the // lock. assert(chunk != NULL, "Deallocating NULL"); - // MutexLockerEx fcl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); - locked_verify(); + assert_lock_strong(SpaceManager::expand_lock()); + slow_locked_verify(); if (TraceMetadataChunkAllocation) { tty->print_cr("ChunkManager::chunk_freelist_deallocate: chunk " PTR_FORMAT " size " SIZE_FORMAT, @@ -1663,7 +1682,7 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) { assert_lock_strong(SpaceManager::expand_lock()); - locked_verify(); + slow_locked_verify(); Metachunk* chunk = NULL; if (!SpaceManager::is_humongous(word_size)) { @@ -1708,13 +1727,13 @@ #endif } } - locked_verify(); + slow_locked_verify(); return chunk; } Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) { assert_lock_strong(SpaceManager::expand_lock()); - locked_verify(); + slow_locked_verify(); // Take from the beginning of the list Metachunk* chunk = free_chunks_get(word_size); @@ -1959,7 +1978,7 @@ ChunkManager* chunk_manager = vs_list()->chunk_manager(); - chunk_manager->locked_verify(); + chunk_manager->slow_locked_verify(); if (TraceMetadataChunkAllocation && Verbose) { gclog_or_tty->print_cr("~SpaceManager(): " PTR_FORMAT, this); @@ -2015,7 +2034,7 @@ humongous_chunks = next_humongous_chunks; } set_chunks_in_use(HumongousIndex, NULL); - chunk_manager->locked_verify(); + chunk_manager->slow_locked_verify(); } void SpaceManager::deallocate(MetaWord* p, size_t word_size) { @@ -2330,8 +2349,7 @@ ChunkManager* chunk = (mdtype == Metaspace::ClassType) ? Metaspace::class_space_list()->chunk_manager() : Metaspace::space_list()->chunk_manager(); - - chunk->verify_free_chunks_total(); + chunk->slow_verify(); return chunk->free_chunks_total(); } @@ -2435,6 +2453,11 @@ print_waste(out); } +void MetaspaceAux::verify_free_chunks() { + Metaspace::space_list()->chunk_manager()->verify(); + Metaspace::class_space_list()->chunk_manager()->verify(); +} + // Metaspace methods size_t Metaspace::_first_chunk_word_size = 0; diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/memory/metaspace.hpp --- a/src/share/vm/memory/metaspace.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/memory/metaspace.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -189,6 +189,7 @@ static void print_waste(outputStream* out); static void dump(outputStream* out); + static void verify_free_chunks(); }; // Metaspace are deallocated when their class loader are GC'ed. diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/memory/metaspaceShared.cpp --- a/src/share/vm/memory/metaspaceShared.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/memory/metaspaceShared.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -431,7 +431,7 @@ } static void link_shared_classes(Klass* obj, TRAPS) { - Klass* k = Klass::cast(obj); + Klass* k = obj; if (k->oop_is_instance()) { InstanceKlass* ik = (InstanceKlass*) k; // Link the class to cause the bytecodes to be rewritten and the diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/memory/universe.cpp --- a/src/share/vm/memory/universe.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/memory/universe.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -346,7 +346,7 @@ // --- // New // Have already been initialized. - Klass::cast(_objectArrayKlassObj)->append_to_sibling_list(); + _objectArrayKlassObj->append_to_sibling_list(); // Compute is_jdk version flags. // Only 1.3 or later has the java.lang.Shutdown class. @@ -1304,6 +1304,8 @@ if (!silent) gclog_or_tty->print("cldg "); ClassLoaderDataGraph::verify(); #endif + if (!silent) gclog_or_tty->print("metaspace chunks "); + MetaspaceAux::verify_free_chunks(); if (!silent) gclog_or_tty->print("hand "); JNIHandles::verify(); if (!silent) gclog_or_tty->print("C-heap "); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/oops/arrayKlass.cpp --- a/src/share/vm/oops/arrayKlass.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/oops/arrayKlass.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -67,7 +67,7 @@ Method* ArrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const { // There are no methods in an array klass but the super class (Object) has some assert(super(), "super klass must be present"); - return Klass::cast(super())->uncached_lookup_method(name, signature); + return super()->uncached_lookup_method(name, signature); } ArrayKlass::ArrayKlass(Symbol* name) { diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/oops/cpCache.cpp --- a/src/share/vm/oops/cpCache.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/oops/cpCache.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -371,7 +371,7 @@ int holder_index = cpool->uncached_klass_ref_index_at(constant_pool_index()); if (cpool->tag_at(holder_index).is_klass()) { Klass* klass = cpool->resolved_klass_at(holder_index); - if (!Klass::cast(klass)->oop_is_instance()) + if (!klass->oop_is_instance()) klass = SystemDictionary::Object_klass(); return InstanceKlass::cast(klass)->method_at_vtable(f2_as_index()); } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/oops/instanceKlass.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -727,8 +727,8 @@ // Step 7 Klass* super_klass = this_oop->super(); - if (super_klass != NULL && !this_oop->is_interface() && Klass::cast(super_klass)->should_be_initialized()) { - Klass::cast(super_klass)->initialize(THREAD); + if (super_klass != NULL && !this_oop->is_interface() && super_klass->should_be_initialized()) { + super_klass->initialize(THREAD); if (HAS_PENDING_EXCEPTION) { Handle e(THREAD, PENDING_EXCEPTION); @@ -924,7 +924,7 @@ } bool InstanceKlass::compute_is_subtype_of(Klass* k) { - if (Klass::cast(k)->is_interface()) { + if (k->is_interface()) { return implements_interface(k); } else { return Klass::compute_is_subtype_of(k); @@ -933,7 +933,7 @@ bool InstanceKlass::implements_interface(Klass* k) const { if (this == k) return true; - assert(Klass::cast(k)->is_interface(), "should be an interface class"); + assert(k->is_interface(), "should be an interface class"); for (int i = 0; i < transitive_interfaces()->length(); i++) { if (transitive_interfaces()->at(i) == k) { return true; @@ -1052,6 +1052,13 @@ } void InstanceKlass::call_class_initializer_impl(instanceKlassHandle this_oop, TRAPS) { + if (ReplayCompiles && + (ReplaySuppressInitializers == 1 || + ReplaySuppressInitializers >= 2 && this_oop->class_loader() != NULL)) { + // Hide the existence of the initializer for the purpose of replaying the compile + return; + } + methodHandle h_method(THREAD, this_oop->class_initializer()); assert(!this_oop->is_initialized(), "we cannot initialize twice"); if (TraceClassInitialization) { @@ -1100,7 +1107,7 @@ const int n = local_interfaces()->length(); for (int i = 0; i < n; i++) { Klass* intf1 = local_interfaces()->at(i); - assert(Klass::cast(intf1)->is_interface(), "just checking type"); + assert(intf1->is_interface(), "just checking type"); // search for field in current interface if (InstanceKlass::cast(intf1)->find_local_field(name, sig, fd)) { assert(fd->is_static(), "interface field must be static"); @@ -1171,7 +1178,7 @@ if (InstanceKlass::cast(klass)->find_local_field_from_offset(offset, is_static, fd)) { return true; } - klass = Klass::cast(klass)->super(); + klass = klass->super(); } return false; } @@ -2359,19 +2366,19 @@ bool InstanceKlass::is_same_class_package(Klass* class2) { Klass* class1 = this; oop classloader1 = InstanceKlass::cast(class1)->class_loader(); - Symbol* classname1 = Klass::cast(class1)->name(); - - if (Klass::cast(class2)->oop_is_objArray()) { + Symbol* classname1 = class1->name(); + + if (class2->oop_is_objArray()) { class2 = ObjArrayKlass::cast(class2)->bottom_klass(); } oop classloader2; - if (Klass::cast(class2)->oop_is_instance()) { + if (class2->oop_is_instance()) { classloader2 = InstanceKlass::cast(class2)->class_loader(); } else { - assert(Klass::cast(class2)->oop_is_typeArray(), "should be type array"); + assert(class2->oop_is_typeArray(), "should be type array"); classloader2 = NULL; } - Symbol* classname2 = Klass::cast(class2)->name(); + Symbol* classname2 = class2->name(); return InstanceKlass::is_same_class_package(classloader1, classname1, classloader2, classname2); @@ -2380,7 +2387,7 @@ bool InstanceKlass::is_same_class_package(oop classloader2, Symbol* classname2) { Klass* class1 = this; oop classloader1 = InstanceKlass::cast(class1)->class_loader(); - Symbol* classname1 = Klass::cast(class1)->name(); + Symbol* classname1 = class1->name(); return InstanceKlass::is_same_class_package(classloader1, classname1, classloader2, classname2); @@ -2471,7 +2478,7 @@ bool InstanceKlass::is_same_package_member_impl(instanceKlassHandle class1, Klass* class2_oop, TRAPS) { if (class2_oop == class1()) return true; - if (!Klass::cast(class2_oop)->oop_is_instance()) return false; + if (!class2_oop->oop_is_instance()) return false; instanceKlassHandle class2(THREAD, class2_oop); // must be in same package before we try anything else @@ -3004,7 +3011,7 @@ if (im != NULL) { guarantee(is_interface(), "only interfaces should have implementor set"); guarantee(im->is_klass(), "should be klass"); - guarantee(!Klass::cast(im)->is_interface() || im == this, + guarantee(!im->is_interface() || im == this, "implementors cannot be interfaces"); } @@ -3013,7 +3020,7 @@ Array* local_interfaces = this->local_interfaces(); for (int j = 0; j < local_interfaces->length(); j++) { Klass* e = local_interfaces->at(j); - guarantee(e->is_klass() && Klass::cast(e)->is_interface(), "invalid local interface"); + guarantee(e->is_klass() && e->is_interface(), "invalid local interface"); } } @@ -3022,7 +3029,7 @@ Array* transitive_interfaces = this->transitive_interfaces(); for (int j = 0; j < transitive_interfaces->length(); j++) { Klass* e = transitive_interfaces->at(j); - guarantee(e->is_klass() && Klass::cast(e)->is_interface(), "invalid transitive interface"); + guarantee(e->is_klass() && e->is_interface(), "invalid transitive interface"); } } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/oops/instanceKlass.hpp --- a/src/share/vm/oops/instanceKlass.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/oops/instanceKlass.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -133,6 +133,7 @@ class InstanceKlass: public Klass { friend class VMStructs; friend class ClassFileParser; + friend class CompileReplay; protected: // Constructor diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/oops/klass.cpp --- a/src/share/vm/oops/klass.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/oops/klass.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -56,7 +56,7 @@ while (t != NULL) { if (t == k) return true; - t = Klass::cast(t)->super(); + t = t->super(); } return false; } @@ -243,16 +243,16 @@ juint j = super_depth(); assert(j == my_depth, "computed accessor gets right answer"); Klass* t = this; - while (!Klass::cast(t)->can_be_primary_super()) { - t = Klass::cast(t)->super(); - j = Klass::cast(t)->super_depth(); + while (!t->can_be_primary_super()) { + t = t->super(); + j = t->super_depth(); } for (juint j1 = j+1; j1 < primary_super_limit(); j1++) { assert(primary_super_of_depth(j1) == NULL, "super list padding"); } while (t != NULL) { assert(primary_super_of_depth(j) == t, "super list initialization"); - t = Klass::cast(t)->super(); + t = t->super(); --j; } assert(j == (juint)-1, "correct depth count"); @@ -333,7 +333,7 @@ Klass* Klass::subklass() const { - return _subklass == NULL ? NULL : Klass::cast(_subklass); + return _subklass == NULL ? NULL : _subklass; } InstanceKlass* Klass::superklass() const { @@ -342,7 +342,7 @@ } Klass* Klass::next_sibling() const { - return _next_sibling == NULL ? NULL : Klass::cast(_next_sibling); + return _next_sibling == NULL ? NULL : _next_sibling; } void Klass::set_subklass(Klass* s) { diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/oops/klass.hpp --- a/src/share/vm/oops/klass.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/oops/klass.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -422,12 +422,6 @@ // if not, throw either an Error or an Exception. virtual void check_valid_for_instantiation(bool throwError, TRAPS); - // Casting - static Klass* cast(Klass* k) { - assert(k->is_klass(), "cast to Klass"); - return k; - } - // array copying virtual void copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/oops/klassVtable.cpp --- a/src/share/vm/oops/klassVtable.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/oops/klassVtable.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -746,7 +746,7 @@ while (target != NULL && target->is_static()) { // continue with recursive lookup through the superclass Klass* super = target->method_holder()->super(); - target = (super == NULL) ? (Method*)NULL : Klass::cast(super)->uncached_lookup_method(method_name, method_signature); + target = (super == NULL) ? (Method*)NULL : super->uncached_lookup_method(method_name, method_signature); } if (target == NULL || !target->is_public() || target->is_abstract()) { // Entry do not resolve. Leave it empty @@ -852,7 +852,7 @@ // Handle array argument for(int i = 0; i < transitive_intf->length(); i++) { Klass* intf = transitive_intf->at(i); - assert(Klass::cast(intf)->is_interface(), "sanity check"); + assert(intf->is_interface(), "sanity check"); // Find no. of methods excluding a int method_count = InstanceKlass::cast(intf)->methods()->length(); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/oops/method.cpp --- a/src/share/vm/oops/method.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/oops/method.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -152,11 +152,11 @@ } char* Method::name_and_sig_as_C_string() const { - return name_and_sig_as_C_string(Klass::cast(constants()->pool_holder()), name(), signature()); + return name_and_sig_as_C_string(constants()->pool_holder(), name(), signature()); } char* Method::name_and_sig_as_C_string(char* buf, int size) const { - return name_and_sig_as_C_string(Klass::cast(constants()->pool_holder()), name(), signature(), buf, size); + return name_and_sig_as_C_string(constants()->pool_holder(), name(), signature(), buf, size); } char* Method::name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol* signature) { @@ -578,8 +578,8 @@ for (int i = 0; i < length; i++) { CheckedExceptionElement* table = h_this->checked_exceptions_start(); // recompute on each iteration, not gc safe Klass* k = h_this->constants()->klass_at(table[i].class_cp_index, CHECK_(objArrayHandle())); - assert(Klass::cast(k)->is_subclass_of(SystemDictionary::Throwable_klass()), "invalid exception class"); - mirrors->obj_at_put(i, Klass::cast(k)->java_mirror()); + assert(k->is_subclass_of(SystemDictionary::Throwable_klass()), "invalid exception class"); + mirrors->obj_at_put(i, k->java_mirror()); } return mirrors; } @@ -618,7 +618,7 @@ Thread *thread = Thread::current(); Symbol* klass_name = constants()->klass_name_at(klass_index); Handle loader(thread, method_holder()->class_loader()); - Handle prot (thread, Klass::cast(method_holder())->protection_domain()); + Handle prot (thread, method_holder()->protection_domain()); return SystemDictionary::find(klass_name, loader, prot, thread) != NULL; } else { return true; @@ -1067,8 +1067,8 @@ } Klass* Method::check_non_bcp_klass(Klass* klass) { - if (klass != NULL && Klass::cast(klass)->class_loader() != NULL) { - if (Klass::cast(klass)->oop_is_objArray()) + if (klass != NULL && klass->class_loader() != NULL) { + if (klass->oop_is_objArray()) klass = ObjArrayKlass::cast(klass)->bottom_klass(); return klass; } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/oops/objArrayKlass.cpp --- a/src/share/vm/oops/objArrayKlass.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/oops/objArrayKlass.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -81,7 +81,7 @@ Array* element_supers = element_klass->secondary_supers(); for( int i = element_supers->length()-1; i >= 0; i-- ) { Klass* elem_super = element_supers->at(i); - if (Klass::cast(elem_super)->array_klass_or_null() == NULL) { + if (elem_super->array_klass_or_null() == NULL) { supers_exist = false; break; } @@ -172,7 +172,7 @@ } else { bk = element_klass(); } - assert(bk != NULL && (Klass::cast(bk)->oop_is_instance() || Klass::cast(bk)->oop_is_typeArray()), "invalid bottom klass"); + assert(bk != NULL && (bk->oop_is_instance() || bk->oop_is_typeArray()), "invalid bottom klass"); this->set_bottom_klass(bk); this->set_class_loader_data(bk->class_loader_data()); @@ -254,7 +254,7 @@ // We have to make sure all elements conform to the destination array Klass* bound = ObjArrayKlass::cast(d->klass())->element_klass(); Klass* stype = ObjArrayKlass::cast(s->klass())->element_klass(); - if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) { + if (stype == bound || stype->is_subtype_of(bound)) { // elements are guaranteed to be subtypes, so no check necessary bs->write_ref_array_pre(dst, length); Copy::conjoint_oops_atomic(src, dst, length); @@ -271,7 +271,7 @@ oop new_val = element_is_null ? oop(NULL) : oopDesc::decode_heap_oop_not_null(element); if (element_is_null || - Klass::cast((new_val->klass()))->is_subtype_of(bound)) { + (new_val->klass())->is_subtype_of(bound)) { bs->write_ref_field_pre(p, new_val); *p = *from; } else { @@ -381,7 +381,7 @@ GrowableArray* ObjArrayKlass::compute_secondary_supers(int num_extra_slots) { // interfaces = { cloneable_klass, serializable_klass, elemSuper[], ... }; - Array* elem_supers = Klass::cast(element_klass())->secondary_supers(); + Array* elem_supers = element_klass()->secondary_supers(); int num_elem_supers = elem_supers == NULL ? 0 : elem_supers->length(); int num_secondaries = num_extra_slots + 2 + num_elem_supers; if (num_secondaries == 2) { @@ -411,7 +411,7 @@ } void ObjArrayKlass::initialize(TRAPS) { - Klass::cast(bottom_klass())->initialize(THREAD); // dispatches to either InstanceKlass or TypeArrayKlass + bottom_klass()->initialize(THREAD); // dispatches to either InstanceKlass or TypeArrayKlass } #define ObjArrayKlass_SPECIALIZED_OOP_ITERATE(T, a, p, do_oop) \ @@ -607,7 +607,7 @@ return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC; } // Return the flags of the bottom element type. - jint element_flags = Klass::cast(bottom_klass())->compute_modifier_flags(CHECK_0); + jint element_flags = bottom_klass()->compute_modifier_flags(CHECK_0); return (element_flags & (JVM_ACC_PUBLIC | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED)) | (JVM_ACC_ABSTRACT | JVM_ACC_FINAL); @@ -686,7 +686,7 @@ guarantee(element_klass()->is_klass(), "should be klass"); guarantee(bottom_klass()->is_metadata(), "should be in metaspace"); guarantee(bottom_klass()->is_klass(), "should be klass"); - Klass* bk = Klass::cast(bottom_klass()); + Klass* bk = bottom_klass(); guarantee(bk->oop_is_instance() || bk->oop_is_typeArray(), "invalid bottom klass"); } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/oops/objArrayKlass.hpp --- a/src/share/vm/oops/objArrayKlass.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/oops/objArrayKlass.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -74,7 +74,7 @@ void copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS); // Compute protection domain - oop protection_domain() { return Klass::cast(bottom_klass())->protection_domain(); } + oop protection_domain() { return bottom_klass()->protection_domain(); } private: // Either oop or narrowOop depending on UseCompressedOops. diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/oops/symbol.cpp --- a/src/share/vm/oops/symbol.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/oops/symbol.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -153,17 +153,15 @@ void Symbol::print_symbol_on(outputStream* st) const { st = st ? st : tty; - int length = UTF8::unicode_length((const char*)bytes(), utf8_length()); - const char *ptr = (const char *)bytes(); - jchar value; - for (int index = 0; index < length; index++) { - ptr = UTF8::next(ptr, &value); - if (value >= 32 && value < 127 || value == '\'' || value == '\\') { - st->put(value); - } else { - st->print("\\u%04x", value); - } - } + st->print("%s", as_quoted_ascii()); +} + +char* Symbol::as_quoted_ascii() const { + const char *ptr = (const char *)&_body[0]; + int quoted_length = UTF8::quoted_ascii_length(ptr, utf8_length()); + char* result = NEW_RESOURCE_ARRAY(char, quoted_length + 1); + UTF8::as_quoted_ascii(ptr, result, quoted_length + 1); + return result; } jchar* Symbol::as_unicode(int& length) const { diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/oops/symbol.hpp --- a/src/share/vm/oops/symbol.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/oops/symbol.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -189,6 +189,8 @@ // Use buf if needed buffer length is <= size. char* as_C_string_flexible_buffer(Thread* t, char* buf, int size) const; + // Returns an escaped form of a Java string. + char* as_quoted_ascii() const; // Returns a null terminated utf8 string in a resource array char* as_utf8() const { return as_C_string(); } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/opto/bytecodeInfo.cpp --- a/src/share/vm/opto/bytecodeInfo.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/opto/bytecodeInfo.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "ci/ciReplay.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "compiler/compileBroker.hpp" @@ -150,7 +151,7 @@ } else { // Not hot. Check for medium-sized pre-existing nmethod at cold sites. if (callee_method->has_compiled_code() && - callee_method->instructions_size(CompLevel_full_optimization) > inline_small_code_size) + callee_method->instructions_size() > inline_small_code_size) return "already compiled into a medium method"; } if (size > max_inline_size) { @@ -192,7 +193,7 @@ } if (callee_method->has_compiled_code() && - callee_method->instructions_size(CompLevel_full_optimization) > InlineSmallCode) { + callee_method->instructions_size() > InlineSmallCode) { wci_result->set_profit(wci_result->profit() * 0.1); // %%% adjust wci_result->size()? } @@ -216,7 +217,7 @@ // Now perform checks which are heuristic if (callee_method->has_compiled_code() && - callee_method->instructions_size(CompLevel_full_optimization) > InlineSmallCode) { + callee_method->instructions_size() > InlineSmallCode) { return "already compiled into a big method"; } @@ -235,6 +236,12 @@ return "disallowed by CompilerOracle"; } +#ifndef PRODUCT + if (ciReplay::should_not_inline(callee_method)) { + return "disallowed by ciReplay"; + } +#endif + if (UseStringCache) { // Do not inline StringCache::profile() method used only at the beginning. if (callee_method->name() == ciSymbol::profile_name() && diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/opto/doCall.cpp --- a/src/share/vm/opto/doCall.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/opto/doCall.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -334,7 +334,7 @@ return true; } - assert(dest_method->will_link(method()->holder(), klass, bc()), "dest_method: typeflow responsibility"); + assert(dest_method->is_loaded(), "dest_method: typeflow responsibility"); return false; } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/opto/runtime.cpp --- a/src/share/vm/opto/runtime.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/opto/runtime.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -236,7 +236,7 @@ assert(check_compiled_frame(thread), "incorrect caller"); // These checks are cheap to make and support reflective allocation. - int lh = Klass::cast(klass)->layout_helper(); + int lh = klass->layout_helper(); if (Klass::layout_helper_needs_slow_path(lh) || !InstanceKlass::cast(klass)->is_initialized()) { KlassHandle kh(THREAD, klass); @@ -283,7 +283,7 @@ // Scavenge and allocate an instance. oop result; - if (Klass::cast(array_type)->oop_is_typeArray()) { + if (array_type->oop_is_typeArray()) { // The oopFactory likes to work with the element type. // (We could bypass the oopFactory, since it doesn't add much value.) BasicType elem_type = TypeArrayKlass::cast(array_type)->element_type(); @@ -321,7 +321,7 @@ // Scavenge and allocate an instance. oop result; - assert(Klass::cast(array_type)->oop_is_typeArray(), "should be called only for type array"); + assert(array_type->oop_is_typeArray(), "should be called only for type array"); // The oopFactory likes to work with the element type. BasicType elem_type = TypeArrayKlass::cast(array_type)->element_type(); result = oopFactory::new_typeArray_nozero(elem_type, len, THREAD); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/jni.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -24,6 +24,7 @@ */ #include "precompiled.hpp" +#include "ci/ciReplay.hpp" #include "classfile/altHashing.hpp" #include "classfile/classLoader.hpp" #include "classfile/javaClasses.hpp" @@ -233,13 +234,13 @@ intptr_t jfieldIDWorkaround::encode_klass_hash(Klass* k, intptr_t offset) { if (offset <= small_offset_mask) { Klass* field_klass = k; - Klass* super_klass = Klass::cast(field_klass)->super(); + Klass* super_klass = field_klass->super(); // With compressed oops the most super class with nonstatic fields would // be the owner of fields embedded in the header. while (InstanceKlass::cast(super_klass)->has_nonstatic_fields() && InstanceKlass::cast(super_klass)->contains_field_offset(offset)) { field_klass = super_klass; // super contains the field also - super_klass = Klass::cast(field_klass)->super(); + super_klass = field_klass->super(); } debug_only(No_Safepoint_Verifier nosafepoint;) uintptr_t klass_hash = field_klass->identity_hash(); @@ -249,7 +250,7 @@ #ifndef PRODUCT { ResourceMark rm; - warning("VerifyJNIFields: long offset %d in %s", offset, Klass::cast(k)->external_name()); + warning("VerifyJNIFields: long offset %d in %s", offset, k->external_name()); } #endif #endif @@ -265,7 +266,7 @@ // Could use a non-blocking query for identity_hash here... if ((k->identity_hash() & klass_mask) == klass_hash) return true; - k = Klass::cast(k)->super(); + k = k->super(); } while (k != NULL); return false; } @@ -283,7 +284,7 @@ #ifndef PRODUCT if (Verbose) { ResourceMark rm; - warning("VerifyJNIFields: unverified offset %d for %s", offset, Klass::cast(k)->external_name()); + warning("VerifyJNIFields: unverified offset %d for %s", offset, k->external_name()); } #endif #endif @@ -415,7 +416,7 @@ } cls = (jclass)JNIHandles::make_local( - env, Klass::cast(k)->java_mirror()); + env, k->java_mirror()); return cls; JNI_END @@ -536,7 +537,7 @@ KlassHandle k1(THREAD, k); // Make sure class is initialized before handing id's out to methods - Klass::cast(k1())->initialize(CHECK_NULL); + k1()->initialize(CHECK_NULL); Method* m = InstanceKlass::cast(k1())->method_with_idnum(slot); ret = m==NULL? NULL : m->jmethod_id(); // return NULL if reflected method deleted return ret; @@ -569,7 +570,7 @@ KlassHandle k1(THREAD, k); // Make sure class is initialized before handing id's out to fields - Klass::cast(k1())->initialize(CHECK_NULL); + k1()->initialize(CHECK_NULL); // First check if this is a static field if (modifiers & JVM_ACC_STATIC) { @@ -648,17 +649,17 @@ // interfaces return NULL // proper classes return Klass::super() Klass* k = java_lang_Class::as_Klass(mirror); - if (Klass::cast(k)->is_interface()) return NULL; + if (k->is_interface()) return NULL; // return mirror for superclass - Klass* super = Klass::cast(k)->java_super(); + Klass* super = k->java_super(); // super2 is the value computed by the compiler's getSuperClass intrinsic: - debug_only(Klass* super2 = ( Klass::cast(k)->oop_is_array() + debug_only(Klass* super2 = ( k->oop_is_array() ? SystemDictionary::Object_klass() - : Klass::cast(k)->super() ) ); + : k->super() ) ); assert(super == super2, "java_super computation depends on interface, array, other super"); - obj = (super == NULL) ? NULL : (jclass) JNIHandles::make_local(Klass::cast(super)->java_mirror()); + obj = (super == NULL) ? NULL : (jclass) JNIHandles::make_local(super->java_mirror()); return obj; JNI_END @@ -686,7 +687,7 @@ Klass* sub_klass = java_lang_Class::as_Klass(sub_mirror); Klass* super_klass = java_lang_Class::as_Klass(super_mirror); assert(sub_klass != NULL && super_klass != NULL, "invalid arguments to jni_IsAssignableFrom"); - jboolean ret = Klass::cast(sub_klass)->is_subtype_of(super_klass) ? + jboolean ret = sub_klass->is_subtype_of(super_klass) ? JNI_TRUE : JNI_FALSE; #ifndef USDT2 DTRACE_PROBE1(hotspot_jni, IsAssignableFrom__return, ret); @@ -820,7 +821,7 @@ ResourceMark rm(THREAD); jio_fprintf(defaultStream::error_stream(), ". Uncaught exception of type %s.", - Klass::cast(ex->klass())->external_name()); + ex->klass()->external_name()); } } } @@ -1358,7 +1359,7 @@ Method* m = Method::resolve_jmethod_id(method_id); number_of_parameters = m->size_of_parameters(); Klass* holder = m->method_holder(); - if (!(Klass::cast(holder))->is_interface()) { + if (!(holder)->is_interface()) { // non-interface call -- for that little speed boost, don't handlize debug_only(No_Safepoint_Verifier nosafepoint;) if (call_type == JNI_VIRTUAL) { @@ -1423,7 +1424,7 @@ static instanceOop alloc_object(jclass clazz, TRAPS) { KlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz))); - Klass::cast(k())->check_valid_for_instantiation(false, CHECK_NULL); + k()->check_valid_for_instantiation(false, CHECK_NULL); InstanceKlass::cast(k())->initialize(CHECK_NULL); instanceOop ih = InstanceKlass::cast(k())->allocate_instance(THREAD); return ih; @@ -1545,7 +1546,7 @@ #endif /* USDT2 */ Klass* k = JNIHandles::resolve_non_null(obj)->klass(); jclass ret = - (jclass) JNIHandles::make_local(env, Klass::cast(k)->java_mirror()); + (jclass) JNIHandles::make_local(env, k->java_mirror()); #ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetObjectClass__return, ret); #else /* USDT2 */ @@ -1610,7 +1611,7 @@ // Make sure class is linked and initialized before handing id's out to // Method*s. - Klass::cast(klass())->initialize(CHECK_NULL); + klass()->initialize(CHECK_NULL); Method* m; if (name == vmSymbols::object_initializer_name() || @@ -2426,7 +2427,7 @@ JNI_ArgumentPusherVaArg ap(methodID, args); \ /* Make sure class is initialized before trying to invoke its method */ \ KlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls))); \ - Klass::cast(k())->initialize(CHECK_0); \ + k()->initialize(CHECK_0); \ jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \ va_end(args); \ ret = jvalue.get_##ResultType(); \ @@ -2611,10 +2612,10 @@ KlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz))); // Make sure class is initialized before handing id's out to fields - Klass::cast(k())->initialize(CHECK_NULL); + k()->initialize(CHECK_NULL); fieldDescriptor fd; - if (!Klass::cast(k())->oop_is_instance() || + if (!k()->oop_is_instance() || !InstanceKlass::cast(k())->find_field(fieldname, signame, false, &fd)) { THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); } @@ -2976,10 +2977,10 @@ KlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz))); // Make sure class is initialized before handing id's out to static fields - Klass::cast(k())->initialize(CHECK_NULL); + k()->initialize(CHECK_NULL); fieldDescriptor fd; - if (!Klass::cast(k())->oop_is_instance() || + if (!k()->oop_is_instance() || !InstanceKlass::cast(k())->find_field(fieldname, signame, true, &fd)) { THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); } @@ -3439,7 +3440,7 @@ jobjectArray ret = NULL; DT_RETURN_MARK(NewObjectArray, jobjectArray, (const jobjectArray&)ret); KlassHandle ek(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(elementClass))); - Klass* ako = Klass::cast(ek())->array_klass(CHECK_NULL); + Klass* ako = ek()->array_klass(CHECK_NULL); KlassHandle ak = KlassHandle(THREAD, ako); ObjArrayKlass::cast(ak())->initialize(CHECK_NULL); objArrayOop result = ObjArrayKlass::cast(ak())->allocate(length, CHECK_NULL); @@ -3970,7 +3971,7 @@ if (trial_name == NULL) { continue; // no such symbol, so this prefix wasn't used, try the next prefix } - method = Klass::cast(k())->lookup_method(trial_name, signature); + method = k()->lookup_method(trial_name, signature); if (method == NULL) { continue; // signature doesn't match, try the next prefix } @@ -3987,12 +3988,12 @@ } static bool register_native(KlassHandle k, Symbol* name, Symbol* signature, address entry, TRAPS) { - Method* method = Klass::cast(k())->lookup_method(name, signature); + Method* method = k()->lookup_method(name, signature); if (method == NULL) { ResourceMark rm; stringStream st; st.print("Method %s name or signature does not match", - Method::name_and_sig_as_C_string(Klass::cast(k()), name, signature)); + Method::name_and_sig_as_C_string(k(), name, signature)); THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false); } if (!method->is_native()) { @@ -4002,7 +4003,7 @@ ResourceMark rm; stringStream st; st.print("Method %s is not declared as native", - Method::name_and_sig_as_C_string(Klass::cast(k()), name, signature)); + Method::name_and_sig_as_C_string(k(), name, signature)); THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false); } } @@ -4058,7 +4059,7 @@ if (name == NULL || signature == NULL) { ResourceMark rm; stringStream st; - st.print("Method %s.%s%s not found", Klass::cast(h_k())->external_name(), meth_name, meth_sig); + st.print("Method %s.%s%s not found", h_k()->external_name(), meth_name, meth_sig); // Must return negative value on failure THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), -1); } @@ -4084,7 +4085,7 @@ #endif /* USDT2 */ Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)); //%note jni_2 - if (Klass::cast(k)->oop_is_instance()) { + if (k->oop_is_instance()) { for (int index = 0; index < InstanceKlass::cast(k)->methods()->length(); index++) { Method* m = InstanceKlass::cast(k)->methods()->at(index); if (m->is_native()) { @@ -5151,6 +5152,7 @@ // Check if we should compile all classes on bootclasspath NOT_PRODUCT(if (CompileTheWorld) ClassLoader::compile_the_world();) + NOT_PRODUCT(if (ReplayCompiles) ciReplay::replay(thread);) // Since this is not a JVM_ENTRY we have to set the thread state manually before leaving. ThreadStateTransition::transition_and_fence(thread, _thread_in_vm, _thread_in_native); } else { diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/jniCheck.cpp --- a/src/share/vm/prims/jniCheck.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/jniCheck.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -383,7 +383,7 @@ ASSERT_OOPS_ALLOWED; assert(klass != NULL, "klass argument must have a value"); - if (!Klass::cast(klass)->oop_is_instance() || + if (!klass->oop_is_instance() || !InstanceKlass::cast(klass)->is_subclass_of(SystemDictionary::Throwable_klass())) { ReportJNIFatalError(thr, fatal_class_not_a_throwable_class); } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/jvm.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -305,7 +305,7 @@ assert(s->is_oop(), "JVM_ArrayCopy: src not an oop"); assert(d->is_oop(), "JVM_ArrayCopy: dst not an oop"); // Do copy - Klass::cast(s->klass())->copy_array(s, src_pos, d, dst_pos, length, thread); + s->klass()->copy_array(s, src_pos, d, dst_pos, length, thread); JVM_END @@ -675,7 +675,7 @@ JVM_ENTRY(jclass, JVM_GetCallerClass(JNIEnv* env, int depth)) JVMWrapper("JVM_GetCallerClass"); Klass* k = thread->security_get_caller_class(depth); - return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, Klass::cast(k)->java_mirror()); + return (k == NULL) ? NULL : (jclass) JNIHandles::make_local(env, k->java_mirror()); JVM_END @@ -739,7 +739,7 @@ if (TraceClassResolution) { trace_class_resolution(k); } - return (jclass) JNIHandles::make_local(env, Klass::cast(k)->java_mirror()); + return (jclass) JNIHandles::make_local(env, k->java_mirror()); JVM_END JVM_ENTRY(jclass, JVM_FindClassFromClassLoader(JNIEnv* env, const char* name, @@ -785,8 +785,8 @@ oop class_loader = NULL; oop protection_domain = NULL; if (from_class != NULL) { - class_loader = Klass::cast(from_class)->class_loader(); - protection_domain = Klass::cast(from_class)->protection_domain(); + class_loader = from_class->class_loader(); + protection_domain = from_class->protection_domain(); } Handle h_loader(THREAD, class_loader); Handle h_prot (THREAD, protection_domain); @@ -798,11 +798,11 @@ ResourceMark rm; oop from_mirror = JNIHandles::resolve_non_null(from); Klass* from_class = java_lang_Class::as_Klass(from_mirror); - const char * from_name = Klass::cast(from_class)->external_name(); + const char * from_name = from_class->external_name(); oop mirror = JNIHandles::resolve_non_null(result); Klass* to_class = java_lang_Class::as_Klass(mirror); - const char * to = Klass::cast(to_class)->external_name(); + const char * to = to_class->external_name(); tty->print("RESOLVE %s %s (verification)\n", from_name, to); } @@ -875,7 +875,7 @@ trace_class_resolution(k); } - return (jclass) JNIHandles::make_local(env, Klass::cast(k)->java_mirror()); + return (jclass) JNIHandles::make_local(env, k->java_mirror()); } @@ -936,7 +936,7 @@ CHECK_NULL); return (k == NULL) ? NULL : - (jclass) JNIHandles::make_local(env, Klass::cast(k)->java_mirror()); + (jclass) JNIHandles::make_local(env, k->java_mirror()); JVM_END @@ -954,7 +954,7 @@ // Consider caching interned string in Klass Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); assert(k->is_klass(), "just checking"); - name = Klass::cast(k)->external_name(); + name = k->external_name(); } oop result = StringTable::intern((char*) name, CHECK_NULL); return (jstring) JNIHandles::make_local(env, result); @@ -991,12 +991,12 @@ // Regular instance klass, fill in all local interfaces for (int index = 0; index < size; index++) { Klass* k = InstanceKlass::cast(klass())->local_interfaces()->at(index); - result->obj_at_put(index, Klass::cast(k)->java_mirror()); + result->obj_at_put(index, k->java_mirror()); } } else { // All arrays implement java.lang.Cloneable and java.io.Serializable - result->obj_at_put(0, Klass::cast(SystemDictionary::Cloneable_klass())->java_mirror()); - result->obj_at_put(1, Klass::cast(SystemDictionary::Serializable_klass())->java_mirror()); + result->obj_at_put(0, SystemDictionary::Cloneable_klass()->java_mirror()); + result->obj_at_put(1, SystemDictionary::Serializable_klass()->java_mirror()); } return (jobjectArray) JNIHandles::make_local(env, result()); JVM_END @@ -1008,7 +1008,7 @@ return NULL; } Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); - oop loader = Klass::cast(k)->class_loader(); + oop loader = k->class_loader(); return JNIHandles::make_local(env, loader); JVM_END @@ -1020,8 +1020,8 @@ return JNI_FALSE; } Klass* k = java_lang_Class::as_Klass(mirror); - jboolean result = Klass::cast(k)->is_interface(); - assert(!result || Klass::cast(k)->oop_is_instance(), + jboolean result = k->is_interface(); + assert(!result || k->oop_is_instance(), "all interfaces are instance types"); // The compiler intrinsic for isInterface tests the // Klass::_access_flags bits in the same way. @@ -1039,7 +1039,7 @@ Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); objArrayOop signers = NULL; - if (Klass::cast(k)->oop_is_instance()) { + if (k->oop_is_instance()) { signers = InstanceKlass::cast(k)->signers(); } @@ -1066,7 +1066,7 @@ // Signers are only set once, ClassLoader.java, and thus shouldn't // be called with an array. Only the bootstrap loader creates arrays. Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); - if (Klass::cast(k)->oop_is_instance()) { + if (k->oop_is_instance()) { InstanceKlass::cast(k)->set_signers(objArrayOop(JNIHandles::resolve(signers))); } } @@ -1085,7 +1085,7 @@ } Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); - return (jobject) JNIHandles::make_local(env, Klass::cast(k)->protection_domain()); + return (jobject) JNIHandles::make_local(env, k->protection_domain()); JVM_END @@ -1101,7 +1101,7 @@ Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); // cls won't be an array, as this called only from ClassLoader.defineClass - if (Klass::cast(k)->oop_is_instance()) { + if (k->oop_is_instance()) { oop pd = JNIHandles::resolve(protection_domain); assert(pd == NULL || pd->is_oop(), "just checking"); InstanceKlass::cast(k)->set_protection_domain(pd); @@ -1124,7 +1124,7 @@ Handle object (THREAD, JNIHandles::resolve(action)); // get run() method - Method* m_oop = Klass::cast(object->klass())->uncached_lookup_method( + Method* m_oop = object->klass()->uncached_lookup_method( vmSymbols::run_method_name(), vmSymbols::void_object_signature()); methodHandle m (THREAD, m_oop); @@ -1267,7 +1267,7 @@ JVM_QUICK_ENTRY(jboolean, JVM_IsArrayClass(JNIEnv *env, jclass cls)) JVMWrapper("JVM_IsArrayClass"); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); - return (k != NULL) && Klass::cast(k)->oop_is_array() ? true : false; + return (k != NULL) && k->oop_is_array() ? true : false; JVM_END @@ -1293,7 +1293,7 @@ return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC; } - Klass* k = Klass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls))); + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); debug_only(int computed_modifiers = k->compute_modifier_flags(CHECK_0)); assert(k->modifier_flags() == computed_modifiers, "modifiers cache is OK"); return k->modifier_flags(); @@ -1308,7 +1308,7 @@ // of an InstanceKlass if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || - ! Klass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass)))->oop_is_instance()) { + ! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->oop_is_instance()) { oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); return (jobjectArray)JNIHandles::make_local(env, result); } @@ -1372,7 +1372,7 @@ { // ofClass is a reference to a java_lang_Class object. if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || - ! Klass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass)))->oop_is_instance()) { + ! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->oop_is_instance()) { return NULL; } @@ -1382,7 +1382,7 @@ )->compute_enclosing_class(&inner_is_member, CHECK_NULL); if (outer_klass == NULL) return NULL; // already a top-level class if (!inner_is_member) return NULL; // an anonymous class (inside a method) - return (jclass) JNIHandles::make_local(env, Klass::cast(outer_klass)->java_mirror()); + return (jclass) JNIHandles::make_local(env, outer_klass->java_mirror()); } JVM_END @@ -1452,7 +1452,7 @@ // Return null for arrays and primatives if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); - if (Klass::cast(k)->oop_is_instance()) { + if (k->oop_is_instance()) { Symbol* sym = InstanceKlass::cast(k)->generic_signature(); if (sym == NULL) return NULL; Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL); @@ -1470,7 +1470,7 @@ // Return null for arrays and primitives if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); - if (Klass::cast(k)->oop_is_instance()) { + if (k->oop_is_instance()) { typeArrayOop a = Annotations::make_java_array(InstanceKlass::cast(k)->class_annotations(), CHECK_NULL); return (jbyteArray) JNIHandles::make_local(env, a); } @@ -1583,7 +1583,7 @@ // Exclude primitive types and array types if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || - Klass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass)))->oop_is_array()) { + java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->oop_is_array()) { // Return empty array oop res = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), 0, CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, res); @@ -1646,7 +1646,7 @@ // Exclude primitive types and array types if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) - || Klass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass)))->oop_is_array()) { + || java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->oop_is_array()) { // Return empty array oop res = oopFactory::new_objArray(SystemDictionary::reflect_Method_klass(), 0, CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, res); @@ -1698,7 +1698,7 @@ // Exclude primitive types and array types if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) - || Klass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass)))->oop_is_array()) { + || java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->oop_is_array()) { // Return empty array oop res = oopFactory::new_objArray(SystemDictionary::reflect_Constructor_klass(), 0 , CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, res); @@ -1751,7 +1751,7 @@ return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC; } - Klass* k = Klass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls))); + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); return k->access_flags().as_int() & JVM_ACC_WRITTEN_FLAGS; } JVM_END @@ -1767,7 +1767,7 @@ // Return null for primitives and arrays if (!java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); - if (Klass::cast(k)->oop_is_instance()) { + if (k->oop_is_instance()) { instanceKlassHandle k_h(THREAD, k); Handle jcp = sun_reflect_ConstantPool::create(CHECK_NULL); sun_reflect_ConstantPool::set_cp(jcp(), k_h->constants()); @@ -2043,12 +2043,12 @@ if (java_lang_Class::is_primitive(r)) return false; Klass* k = java_lang_Class::as_Klass(r); - assert(Klass::cast(k)->oop_is_instance(), "must be an instance klass"); - if (! Klass::cast(k)->oop_is_instance()) return false; + assert(k->oop_is_instance(), "must be an instance klass"); + if (! k->oop_is_instance()) return false; ResourceMark rm(THREAD); - const char* name = Klass::cast(k)->name()->as_C_string(); - bool system_class = Klass::cast(k)->class_loader() == NULL; + const char* name = k->name()->as_C_string(); + bool system_class = k->class_loader() == NULL; return JavaAssertions::enabled(name, system_class); JVM_END @@ -2079,7 +2079,7 @@ JVMWrapper("JVM_GetClassNameUTF"); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); - return Klass::cast(k)->name()->as_utf8(); + return k->name()->as_utf8(); JVM_END @@ -2089,7 +2089,7 @@ k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); // types will have length zero if this is not an InstanceKlass // (length is determined by call to JVM_GetClassCPEntriesCount) - if (Klass::cast(k)->oop_is_instance()) { + if (k->oop_is_instance()) { ConstantPool* cp = InstanceKlass::cast(k)->constants(); for (int index = cp->length() - 1; index >= 0; index--) { constantTag tag = cp->tag_at(index); @@ -2103,7 +2103,7 @@ JVMWrapper("JVM_GetClassCPEntriesCount"); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); - if (!Klass::cast(k)->oop_is_instance()) + if (!k->oop_is_instance()) return 0; return InstanceKlass::cast(k)->constants()->length(); JVM_END @@ -2113,7 +2113,7 @@ JVMWrapper("JVM_GetClassFieldsCount"); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); - if (!Klass::cast(k)->oop_is_instance()) + if (!k->oop_is_instance()) return 0; return InstanceKlass::cast(k)->java_fields_count(); JVM_END @@ -2123,7 +2123,7 @@ JVMWrapper("JVM_GetClassMethodsCount"); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); - if (!Klass::cast(k)->oop_is_instance()) + if (!k->oop_is_instance()) return 0; return InstanceKlass::cast(k)->methods()->length(); JVM_END @@ -3123,7 +3123,7 @@ // Fill in mirrors corresponding to method holders int index = 0; while (first != NULL) { - result->obj_at_put(index++, Klass::cast(first->klass())->java_mirror()); + result->obj_at_put(index++, first->klass()->java_mirror()); first = first->next; } assert(index == depth, "just checking"); @@ -3217,7 +3217,7 @@ if (access.is_protected()) { // See if current_class is a subclass of field_class - if (Klass::cast(current_class)->is_subclass_of(field_class)) { + if (current_class->is_subclass_of(field_class)) { return true; } } @@ -3241,8 +3241,8 @@ } // Arrays not allowed here, must use JVM_AllocateNewArray - if (Klass::cast(java_lang_Class::as_Klass(curr_mirror))->oop_is_array() || - Klass::cast(java_lang_Class::as_Klass(init_mirror))->oop_is_array()) { + if (java_lang_Class::as_Klass(curr_mirror)->oop_is_array() || + java_lang_Class::as_Klass(init_mirror)->oop_is_array()) { ResourceMark rm(THREAD); THROW_0(vmSymbols::java_lang_InvalidClassException()); } @@ -3264,7 +3264,7 @@ if (m.is_null()) { ResourceMark rm(THREAD); THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), - Method::name_and_sig_as_C_string(Klass::cast(init_klass()), + Method::name_and_sig_as_C_string(init_klass(), vmSymbols::object_initializer_name(), vmSymbols::void_method_signature())); } @@ -4245,7 +4245,7 @@ return NULL; } Klass* k = java_lang_Class::as_Klass(mirror()); - if (!Klass::cast(k)->oop_is_instance()) { + if (!k->oop_is_instance()) { return NULL; } instanceKlassHandle ik_h(THREAD, k); @@ -4256,7 +4256,7 @@ objArrayOop dest_o = oopFactory::new_objArray(SystemDictionary::Object_klass(), 3, CHECK_NULL); objArrayHandle dest(THREAD, dest_o); Klass* enc_k = ik_h->constants()->klass_at(encl_method_class_idx, CHECK_NULL); - dest->obj_at_put(0, Klass::cast(enc_k)->java_mirror()); + dest->obj_at_put(0, enc_k->java_mirror()); int encl_method_method_idx = ik_h->enclosing_method_method_index(); if (encl_method_method_idx != 0) { Symbol* sym = ik_h->constants()->symbol_at( diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/jvmtiClassFileReconstituter.cpp --- a/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -228,7 +228,7 @@ write_attribute_name_index("Code"); write_u4(size); - write_u2(method->max_stack()); + write_u2(method->verifier_max_stack()); write_u2(method->max_locals()); write_u4(code_size); copy_bytecodes(method, (unsigned char*)writeable_address(code_size)); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/jvmtiEnv.cpp --- a/src/share/vm/prims/jvmtiEnv.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/jvmtiEnv.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -2116,7 +2116,7 @@ result[0] = tchar; result[1] = '\0'; } else { - const char* class_sig = Klass::cast(k)->signature_name(); + const char* class_sig = k->signature_name(); result = (char *) jvmtiMalloc(strlen(class_sig)+1); strcpy(result, class_sig); } @@ -2124,7 +2124,7 @@ } if (generic_ptr != NULL) { *generic_ptr = NULL; - if (!isPrimitive && Klass::cast(k)->oop_is_instance()) { + if (!isPrimitive && k->oop_is_instance()) { Symbol* soo = InstanceKlass::cast(k)->generic_signature(); if (soo != NULL) { const char *gen_sig = soo->as_C_string(); @@ -2155,7 +2155,7 @@ } else { Klass* k = java_lang_Class::as_Klass(k_mirror); NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); - result = Klass::cast(k)->jvmti_class_status(); + result = k->jvmti_class_status(); } *status_ptr = result; @@ -2173,7 +2173,7 @@ Klass* k_klass = java_lang_Class::as_Klass(k_mirror); NULL_CHECK(k_klass, JVMTI_ERROR_INVALID_CLASS); - if (!Klass::cast(k_klass)->oop_is_instance()) { + if (!k_klass->oop_is_instance()) { return JVMTI_ERROR_ABSENT_INFORMATION; } @@ -2200,7 +2200,7 @@ if (!java_lang_Class::is_primitive(k_mirror)) { Klass* k = java_lang_Class::as_Klass(k_mirror); NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); - result = Klass::cast(k)->compute_modifier_flags(current_thread); + result = k->compute_modifier_flags(current_thread); JavaThread* THREAD = current_thread; // pass to macros if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; @@ -2208,7 +2208,7 @@ }; // Reset the deleted ACC_SUPER bit ( deleted in compute_modifier_flags()). - if(Klass::cast(k)->is_super()) { + if(k->is_super()) { result |= JVM_ACC_SUPER; } } else { @@ -2237,11 +2237,11 @@ NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); // Return CLASS_NOT_PREPARED error as per JVMTI spec. - if (!(Klass::cast(k)->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) { + if (!(k->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) { return JVMTI_ERROR_CLASS_NOT_PREPARED; } - if (!Klass::cast(k)->oop_is_instance()) { + if (!k->oop_is_instance()) { *method_count_ptr = 0; *methods_ptr = (jmethodID*) jvmtiMalloc(0 * sizeof(jmethodID)); return JVMTI_ERROR_NONE; @@ -2293,11 +2293,11 @@ NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); // Return CLASS_NOT_PREPARED error as per JVMTI spec. - if (!(Klass::cast(k)->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) { + if (!(k->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) { return JVMTI_ERROR_CLASS_NOT_PREPARED; } - if (!Klass::cast(k)->oop_is_instance()) { + if (!k->oop_is_instance()) { *field_count_ptr = 0; *fields_ptr = (jfieldID*) jvmtiMalloc(0 * sizeof(jfieldID)); return JVMTI_ERROR_NONE; @@ -2348,10 +2348,10 @@ NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); // Return CLASS_NOT_PREPARED error as per JVMTI spec. - if (!(Klass::cast(k)->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) + if (!(k->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) return JVMTI_ERROR_CLASS_NOT_PREPARED; - if (!Klass::cast(k)->oop_is_instance()) { + if (!k->oop_is_instance()) { *interface_count_ptr = 0; *interfaces_ptr = (jclass*) jvmtiMalloc(0 * sizeof(jclass)); return JVMTI_ERROR_NONE; @@ -2363,8 +2363,8 @@ for (int i_index = 0; i_index < result_length; i_index += 1) { Klass* klass_at = interface_list->at(i_index); assert(klass_at->is_klass(), "interfaces must be Klass*s"); - assert(Klass::cast(klass_at)->is_interface(), "interfaces must be interfaces"); - oop mirror_at = Klass::cast(klass_at)->java_mirror(); + assert(klass_at->is_interface(), "interfaces must be interfaces"); + oop mirror_at = klass_at->java_mirror(); Handle handle_at = Handle(current_thread, mirror_at); result_list[i_index] = (jclass) jni_reference(handle_at); } @@ -2468,7 +2468,7 @@ bool result = false; if (!java_lang_Class::is_primitive(k_mirror)) { Klass* k = java_lang_Class::as_Klass(k_mirror); - if (k != NULL && Klass::cast(k)->is_interface()) { + if (k != NULL && k->is_interface()) { result = true; } } @@ -2487,7 +2487,7 @@ bool result = false; if (!java_lang_Class::is_primitive(k_mirror)) { Klass* k = java_lang_Class::as_Klass(k_mirror); - if (k != NULL && Klass::cast(k)->oop_is_array()) { + if (k != NULL && k->oop_is_array()) { result = true; } } @@ -2512,7 +2512,7 @@ Klass* k = java_lang_Class::as_Klass(k_mirror); NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); - oop result_oop = Klass::cast(k)->class_loader(); + oop result_oop = k->class_loader(); if (result_oop == NULL) { *classloader_ptr = (jclass) jni_reference(Handle()); return JVMTI_ERROR_NONE; @@ -2535,7 +2535,7 @@ } Klass* k = java_lang_Class::as_Klass(k_mirror); NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); - if (!Klass::cast(k)->oop_is_instance()) { + if (!k->oop_is_instance()) { return JVMTI_ERROR_ABSENT_INFORMATION; } char* sde = InstanceKlass::cast(k)->source_debug_extension(); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/jvmtiEnvBase.cpp --- a/src/share/vm/prims/jvmtiEnvBase.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/jvmtiEnvBase.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -590,7 +590,7 @@ jclass JvmtiEnvBase::get_jni_class_non_null(Klass* k) { assert(k != NULL, "k != NULL"); - return (jclass)jni_reference(Klass::cast(k)->java_mirror()); + return (jclass)jni_reference(k->java_mirror()); } #ifndef JVMTI_KERNEL @@ -1365,7 +1365,7 @@ // Method return type signature. char* ty_sign = 1 + strchr(signature->as_C_string(), ')'); - if (!VM_GetOrSetLocal::is_assignable(ty_sign, Klass::cast(ob_kh()), current_thread)) { + if (!VM_GetOrSetLocal::is_assignable(ty_sign, ob_kh(), current_thread)) { return JVMTI_ERROR_TYPE_MISMATCH; } *ret_ob_h = ob_h; diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/jvmtiExport.cpp --- a/src/share/vm/prims/jvmtiExport.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/jvmtiExport.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -196,7 +196,7 @@ jobject to_jobject(oop obj) { return JNIHandles::make_local(_thread,obj); } #endif - jclass to_jclass(Klass* klass) { return (klass == NULL ? NULL : (jclass)to_jobject(Klass::cast(klass)->java_mirror())); } + jclass to_jclass(Klass* klass) { return (klass == NULL ? NULL : (jclass)to_jobject(klass->java_mirror())); } jmethodID to_jmethodID(methodHandle method) { return method->jmethod_id(); } @@ -920,7 +920,7 @@ if (ets->is_enabled(JVMTI_EVENT_CLASS_LOAD)) { EVT_TRACE(JVMTI_EVENT_CLASS_LOAD, ("JVMTI [%s] Evt Class Load sent %s", JvmtiTrace::safe_get_thread_name(thread), - kh()==NULL? "NULL" : Klass::cast(kh())->external_name() )); + kh()==NULL? "NULL" : kh()->external_name() )); JvmtiEnv *env = ets->get_env(); JvmtiClassEventMark jem(thread, kh()); @@ -949,7 +949,7 @@ if (ets->is_enabled(JVMTI_EVENT_CLASS_PREPARE)) { EVT_TRACE(JVMTI_EVENT_CLASS_PREPARE, ("JVMTI [%s] Evt Class Prepare sent %s", JvmtiTrace::safe_get_thread_name(thread), - kh()==NULL? "NULL" : Klass::cast(kh())->external_name() )); + kh()==NULL? "NULL" : kh()->external_name() )); JvmtiEnv *env = ets->get_env(); JvmtiClassEventMark jem(thread, kh()); @@ -979,12 +979,12 @@ for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) { if (env->is_enabled((jvmtiEvent)EXT_EVENT_CLASS_UNLOAD)) { EVT_TRACE(EXT_EVENT_CLASS_UNLOAD, ("JVMTI [?] Evt Class Unload sent %s", - kh()==NULL? "NULL" : Klass::cast(kh())->external_name() )); + kh()==NULL? "NULL" : kh()->external_name() )); // do everything manually, since this is a proxy - needs special care JNIEnv* jni_env = real_thread->jni_environment(); jthread jt = (jthread)JNIHandles::make_local(real_thread, real_thread->threadObj()); - jclass jk = (jclass)JNIHandles::make_local(real_thread, Klass::cast(kh())->java_mirror()); + jclass jk = (jclass)JNIHandles::make_local(real_thread, kh()->java_mirror()); // Before we call the JVMTI agent, we have to set the state in the // thread for which we are proxying. @@ -2121,7 +2121,7 @@ if (env->is_enabled(JVMTI_EVENT_VM_OBJECT_ALLOC)) { EVT_TRACE(JVMTI_EVENT_VM_OBJECT_ALLOC, ("JVMTI [%s] Evt vmobject alloc sent %s", JvmtiTrace::safe_get_thread_name(thread), - object==NULL? "NULL" : Klass::cast(java_lang_Class::as_Klass(object))->external_name())); + object==NULL? "NULL" : java_lang_Class::as_Klass(object)->external_name())); JvmtiVMObjectAllocEventMark jem(thread, h()); JvmtiJavaThreadEventTransition jet(thread); @@ -2177,7 +2177,7 @@ jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) { char ebuf[1024]; char buffer[JVM_MAXPATHLEN]; - void* library; + void* library = NULL; jint result = JNI_ERR; // get agent name and options @@ -2196,13 +2196,16 @@ library = os::dll_load(agent, ebuf, sizeof ebuf); } else { // Try to load the agent from the standard dll directory - os::dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), agent); - library = os::dll_load(buffer, ebuf, sizeof ebuf); + if (os::dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), + agent)) { + library = os::dll_load(buffer, ebuf, sizeof ebuf); + } if (library == NULL) { // not found - try local path char ns[1] = {0}; - os::dll_build_name(buffer, sizeof(buffer), ns, agent); - library = os::dll_load(buffer, ebuf, sizeof ebuf); + if (os::dll_build_name(buffer, sizeof(buffer), ns, agent)) { + library = os::dll_load(buffer, ebuf, sizeof ebuf); + } } } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/jvmtiExport.hpp --- a/src/share/vm/prims/jvmtiExport.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/jvmtiExport.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -64,6 +64,8 @@ // class JvmtiExport : public AllStatic { friend class VMStructs; + friend class CompileReplay; + private: #if INCLUDE_JVMTI diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/jvmtiGetLoadedClasses.cpp --- a/src/share/vm/prims/jvmtiGetLoadedClasses.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/jvmtiGetLoadedClasses.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -169,7 +169,7 @@ static void increment(Klass* k) { JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); if (that->get_initiatingLoader() == NULL) { - for (Klass* l = k; l != NULL; l = Klass::cast(l)->array_klass_or_null()) { + for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { that->set_count(that->get_count() + 1); } } else if (k != NULL) { @@ -182,7 +182,7 @@ JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); oop class_loader = loader_data->class_loader(); if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) { - for (Klass* l = k; l != NULL; l = Klass::cast(l)->array_klass_or_null()) { + for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { that->set_count(that->get_count() + 1); } } @@ -200,14 +200,14 @@ JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); if (that->available()) { if (that->get_initiatingLoader() == NULL) { - for (Klass* l = k; l != NULL; l = Klass::cast(l)->array_klass_or_null()) { - oop mirror = Klass::cast(l)->java_mirror(); + for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { + oop mirror = l->java_mirror(); that->set_element(that->get_index(), mirror); that->set_index(that->get_index() + 1); } } else if (k != NULL) { // if initiating loader not null, just include the instance with 1 dimension - oop mirror = Klass::cast(k)->java_mirror(); + oop mirror = k->java_mirror(); that->set_element(that->get_index(), mirror); that->set_index(that->get_index() + 1); } @@ -219,8 +219,8 @@ if (that->available()) { oop class_loader = loader_data->class_loader(); if (class_loader == JNIHandles::resolve(that->get_initiatingLoader())) { - for (Klass* l = k; l != NULL; l = Klass::cast(l)->array_klass_or_null()) { - oop mirror = Klass::cast(l)->java_mirror(); + for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { + oop mirror = l->java_mirror(); that->set_element(that->get_index(), mirror); that->set_index(that->get_index() + 1); } @@ -234,7 +234,7 @@ static void increment_for_basic_type_arrays(Klass* k) { JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); assert(that != NULL, "no JvmtiGetLoadedClassesClosure"); - for (Klass* l = k; l != NULL; l = Klass::cast(l)->array_klass_or_null()) { + for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { that->set_count(that->get_count() + 1); } } @@ -244,8 +244,8 @@ JvmtiGetLoadedClassesClosure* that = JvmtiGetLoadedClassesClosure::get_this(); assert(that != NULL, "no JvmtiGetLoadedClassesClosure"); assert(that->available(), "no list"); - for (Klass* l = k; l != NULL; l = Klass::cast(l)->array_klass_or_null()) { - oop mirror = Klass::cast(l)->java_mirror(); + for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { + oop mirror = l->java_mirror(); that->set_element(that->get_index(), mirror); that->set_index(that->get_index() + 1); } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/jvmtiImpl.cpp --- a/src/share/vm/prims/jvmtiImpl.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/jvmtiImpl.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -641,14 +641,14 @@ int super_depth = klass->super_depth(); int idx; for (idx = 0; idx < super_depth; idx++) { - if (Klass::cast(klass->primary_super_of_depth(idx))->name() == ty_sym) { + if (klass->primary_super_of_depth(idx)->name() == ty_sym) { return true; } } // Compare secondary supers Array* sec_supers = klass->secondary_supers(); for (idx = 0; idx < sec_supers->length(); idx++) { - if (Klass::cast((Klass*) sec_supers->at(idx))->name() == ty_sym) { + if (((Klass*) sec_supers->at(idx))->name() == ty_sym) { return true; } } @@ -726,7 +726,7 @@ KlassHandle ob_kh = KlassHandle(cur_thread, obj->klass()); NULL_CHECK(ob_kh, (_result = JVMTI_ERROR_INVALID_OBJECT, false)); - if (!is_assignable(signature, Klass::cast(ob_kh()), cur_thread)) { + if (!is_assignable(signature, ob_kh(), cur_thread)) { _result = JVMTI_ERROR_TYPE_MISMATCH; return false; } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -222,7 +222,7 @@ } Klass* the_class_oop = java_lang_Class::as_Klass(klass_mirror); // classes for arrays cannot be redefined - if (the_class_oop == NULL || !Klass::cast(the_class_oop)->oop_is_instance()) { + if (the_class_oop == NULL || !the_class_oop->oop_is_instance()) { return false; } return true; @@ -573,8 +573,8 @@ // Check for NULL superclass first since this might be java.lang.Object if (the_class->super() != scratch_class->super() && (the_class->super() == NULL || scratch_class->super() == NULL || - Klass::cast(the_class->super())->name() != - Klass::cast(scratch_class->super())->name())) { + the_class->super()->name() != + scratch_class->super()->name())) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED; } @@ -592,8 +592,8 @@ return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED; } for (i = 0; i < n_intfs; i++) { - if (Klass::cast(k_interfaces->at(i))->name() != - Klass::cast(k_new_interfaces->at(i))->name()) { + if (k_interfaces->at(i)->name() != + k_new_interfaces->at(i)->name()) { return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED; } } @@ -2684,7 +2684,7 @@ // interface, then we have to call adjust_method_entries() for // every InstanceKlass that has an itable since there isn't a // subclass relationship between an interface and an InstanceKlass. - if (ik->itable_length() > 0 && (Klass::cast(_the_class_oop)->is_interface() + if (ik->itable_length() > 0 && (_the_class_oop->is_interface() || ik->is_subclass_of(_the_class_oop))) { // ik->itable() creates a wrapper object; rm cleans it up ResourceMark rm(THREAD); @@ -2929,7 +2929,7 @@ Symbol* signature) { TempNewSymbol name_symbol = SymbolTable::probe(name_str, (int)name_len); if (name_symbol != NULL) { - Method* method = Klass::cast(the_class())->lookup_method(name_symbol, signature); + Method* method = the_class()->lookup_method(name_symbol, signature); if (method != NULL) { // Even if prefixed, intermediate methods must exist. if (method->is_native()) { diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/jvmtiTagMap.cpp --- a/src/share/vm/prims/jvmtiTagMap.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/jvmtiTagMap.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -2774,7 +2774,7 @@ // a type array references its class inline bool VM_HeapWalkOperation::iterate_over_type_array(oop o) { Klass* k = o->klass(); - oop mirror = Klass::cast(k)->java_mirror(); + oop mirror = k->java_mirror(); if (!CallbackInvoker::report_class_reference(o, mirror)) { return false; } @@ -2823,7 +2823,7 @@ // super (only if something more interesting than java.lang.Object) Klass* java_super = ik->java_super(); if (java_super != NULL && java_super != SystemDictionary::Object_klass()) { - oop super = Klass::cast(java_super)->java_mirror(); + oop super = java_super->java_mirror(); if (!CallbackInvoker::report_superclass_reference(mirror, super)) { return false; } @@ -2865,7 +2865,7 @@ // If the entry is non-null it is resolved. if (entry == NULL) continue; } else { - entry = Klass::cast(pool->resolved_klass_at(i))->java_mirror(); + entry = pool->resolved_klass_at(i)->java_mirror(); } if (!CallbackInvoker::report_constant_pool_reference(mirror, entry, (jint)i)) { return false; @@ -2879,7 +2879,7 @@ // but are specified by IterateOverReachableObjects and must be reported). Array* interfaces = ik->local_interfaces(); for (i = 0; i < interfaces->length(); i++) { - oop interf = Klass::cast((Klass*)interfaces->at(i))->java_mirror(); + oop interf = ((Klass*)interfaces->at(i))->java_mirror(); if (interf == NULL) { continue; } @@ -2928,7 +2928,7 @@ // references from the class). inline bool VM_HeapWalkOperation::iterate_over_object(oop o) { // reference to the class - if (!CallbackInvoker::report_class_reference(o, Klass::cast(o->klass())->java_mirror())) { + if (!CallbackInvoker::report_class_reference(o, o->klass()->java_mirror())) { return false; } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/jvmtiTrace.cpp --- a/src/share/vm/prims/jvmtiTrace.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/jvmtiTrace.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -292,7 +292,7 @@ if (k_oop == NULL) { return "INVALID"; } - return Klass::cast(k_oop)->external_name(); + return k_oop->external_name(); } #endif /*JVMTI_TRACE */ diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/methodHandles.cpp --- a/src/share/vm/prims/methodHandles.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/methodHandles.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -138,7 +138,7 @@ oop clazz = java_lang_reflect_Method::clazz(target_oop); int slot = java_lang_reflect_Method::slot(target_oop); Klass* k = java_lang_Class::as_Klass(clazz); - if (k != NULL && Klass::cast(k)->oop_is_instance()) { + if (k != NULL && k->oop_is_instance()) { Method* m = InstanceKlass::cast(k)->method_with_idnum(slot); return init_method_MemberName(mname_oop, m, true, k); } @@ -146,7 +146,7 @@ oop clazz = java_lang_reflect_Constructor::clazz(target_oop); int slot = java_lang_reflect_Constructor::slot(target_oop); Klass* k = java_lang_Class::as_Klass(clazz); - if (k != NULL && Klass::cast(k)->oop_is_instance()) { + if (k != NULL && k->oop_is_instance()) { Method* m = InstanceKlass::cast(k)->method_with_idnum(slot); return init_method_MemberName(mname_oop, m, false, k); } @@ -187,14 +187,14 @@ } else if (mods.is_static()) { flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT); } else if (receiver_limit != mklass && - !Klass::cast(receiver_limit)->is_subtype_of(mklass)) { + !receiver_limit->is_subtype_of(mklass)) { return NULL; // bad receiver limit - } else if (Klass::cast(receiver_limit)->is_interface() && - Klass::cast(mklass)->is_interface()) { + } else if (receiver_limit->is_interface() && + mklass->is_interface()) { flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT); receiver_limit = mklass; // ignore passed-in limit; interfaces are interconvertible vmindex = klassItable::compute_itable_index(m); - } else if (mklass != receiver_limit && Klass::cast(mklass)->is_interface()) { + } else if (mklass != receiver_limit && mklass->is_interface()) { flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT); // it is a miranda method, so m->vtable_index is not what we want ResourceMark rm; @@ -210,7 +210,7 @@ java_lang_invoke_MemberName::set_flags(mname_oop, flags); java_lang_invoke_MemberName::set_vmtarget(mname_oop, m); java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex); // vtable/itable index - java_lang_invoke_MemberName::set_clazz(mname_oop, Klass::cast(receiver_limit)->java_mirror()); + java_lang_invoke_MemberName::set_clazz(mname_oop, receiver_limit->java_mirror()); // Note: name and type can be lazily computed by resolve_MemberName, // if Java code needs them as resolved String and MethodType objects. // The clazz must be eagerly stored, because it provides a GC @@ -258,7 +258,7 @@ java_lang_invoke_MemberName::set_flags(mname_oop, flags); java_lang_invoke_MemberName::set_vmtarget(mname_oop, vmtarget); java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex); - java_lang_invoke_MemberName::set_clazz(mname_oop, Klass::cast(field_holder)->java_mirror()); + java_lang_invoke_MemberName::set_clazz(mname_oop, field_holder->java_mirror()); if (name != NULL) java_lang_invoke_MemberName::set_name(mname_oop, name); if (type != NULL) @@ -299,7 +299,7 @@ // The following test will fail spuriously during bootstrap of MethodHandle itself: // if (klass != SystemDictionary::MethodHandle_klass()) // Test the name instead: - if (Klass::cast(klass)->name() != vmSymbols::java_lang_invoke_MethodHandle()) + if (klass->name() != vmSymbols::java_lang_invoke_MethodHandle()) return false; Symbol* poly_sig = vmSymbols::object_array_object_signature(); Method* m = InstanceKlass::cast(klass)->find_method(name, poly_sig); @@ -363,7 +363,7 @@ vmIntrinsics::ID MethodHandles::signature_polymorphic_name_id(Klass* klass, Symbol* name) { if (klass != NULL && - Klass::cast(klass)->name() == vmSymbols::java_lang_invoke_MethodHandle()) { + klass->name() == vmSymbols::java_lang_invoke_MethodHandle()) { vmIntrinsics::ID iid = signature_polymorphic_name_id(name); if (iid != vmIntrinsics::_none) return iid; @@ -539,7 +539,7 @@ static oop object_java_mirror() { - return Klass::cast(SystemDictionary::Object_klass())->java_mirror(); + return SystemDictionary::Object_klass()->java_mirror(); } static oop field_name_or_null(Symbol* s) { @@ -560,9 +560,9 @@ if (s == vmSymbols::object_signature()) { return object_java_mirror(); } else if (s == vmSymbols::class_signature()) { - return Klass::cast(SystemDictionary::Class_klass())->java_mirror(); + return SystemDictionary::Class_klass()->java_mirror(); } else if (s == vmSymbols::string_signature()) { - return Klass::cast(SystemDictionary::String_klass())->java_mirror(); + return SystemDictionary::String_klass()->java_mirror(); } } return NULL; @@ -603,8 +603,8 @@ { Klass* defc_klass = java_lang_Class::as_Klass(defc_oop()); if (defc_klass == NULL) return empty; // a primitive; no resolution possible - if (!Klass::cast(defc_klass)->oop_is_instance()) { - if (!Klass::cast(defc_klass)->oop_is_array()) return empty; + if (!defc_klass->oop_is_instance()) { + if (!defc_klass->oop_is_array()) return empty; defc_klass = SystemDictionary::Object_klass(); } defc = instanceKlassHandle(THREAD, defc_klass); @@ -767,7 +767,7 @@ { // This is taken from LinkResolver::resolve_field, sans access checks. assert(vmtarget->is_klass(), "field vmtarget is Klass*"); - if (!Klass::cast((Klass*) vmtarget)->oop_is_instance()) break; + if (!((Klass*) vmtarget)->oop_is_instance()) break; instanceKlassHandle defc(THREAD, (Klass*) vmtarget); DEBUG_ONLY(vmtarget = NULL); // safety bool is_static = ((flags & JVM_ACC_STATIC) != 0); @@ -805,7 +805,7 @@ // %%% take caller into account! - if (k == NULL || !Klass::cast(k)->oop_is_instance()) return -1; + if (k == NULL || !k->oop_is_instance()) return -1; int rfill = 0, rlimit = results->length(), rskip = skip; // overflow measurement: @@ -1032,7 +1032,7 @@ if (!Reflection::verify_class_access(caller, reference_klass, true)) { - THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), Klass::cast(reference_klass)->external_name()); + THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), reference_klass->external_name()); } } } @@ -1108,7 +1108,7 @@ if (vmtarget == NULL) { x = NULL; } else if (vmtarget->is_klass()) { - x = Klass::cast((Klass*) vmtarget)->java_mirror(); + x = ((Klass*) vmtarget)->java_mirror(); } else if (vmtarget->is_method()) { Handle mname2 = MethodHandles::new_MemberName(CHECK_NULL); x = MethodHandles::init_method_MemberName(mname2(), (Method*)vmtarget, false, NULL); @@ -1237,7 +1237,7 @@ if (SystemDictionary::MethodHandle_klass() == NULL) { enable_MH = false; } else { - oop mirror = Klass::cast(SystemDictionary::MethodHandle_klass())->java_mirror(); + oop mirror = SystemDictionary::MethodHandle_klass()->java_mirror(); MH_class = (jclass) JNIHandles::make_local(env, mirror); } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/nativeLookup.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -349,7 +349,7 @@ TempNewSymbol wrapper_symbol = SymbolTable::probe(wrapper_name, wrapper_name_len); if (wrapper_symbol != NULL) { KlassHandle kh(method->method_holder()); - Method* wrapper_method = Klass::cast(kh())->lookup_method(wrapper_symbol, + Method* wrapper_method = kh()->lookup_method(wrapper_symbol, method->signature()); if (wrapper_method != NULL && !wrapper_method->is_native()) { // we found a wrapper method, use its native entry diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/prims/unsafe.cpp --- a/src/share/vm/prims/unsafe.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/prims/unsafe.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -771,7 +771,7 @@ oop mirror = JNIHandles::resolve_non_null(clazz); Klass* klass = java_lang_Class::as_Klass(mirror); - if (klass != NULL && Klass::cast(klass)->should_be_initialized()) { + if (klass != NULL && klass->should_be_initialized()) { InstanceKlass* k = InstanceKlass::cast(klass); k->initialize(CHECK); } @@ -785,7 +785,7 @@ } oop mirror = JNIHandles::resolve_non_null(clazz); Klass* klass = java_lang_Class::as_Klass(mirror); - if (klass != NULL && Klass::cast(klass)->should_be_initialized()) { + if (klass != NULL && klass->should_be_initialized()) { return true; } return false; diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/runtime/arguments.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/javaAssertions.hpp" +#include "classfile/symbolTable.hpp" #include "compiler/compilerOracle.hpp" #include "memory/allocation.inline.hpp" #include "memory/cardTableRS.hpp" @@ -1844,6 +1845,11 @@ status = status && verify_percentage(MinHeapFreeRatio, "MinHeapFreeRatio"); status = status && verify_percentage(MaxHeapFreeRatio, "MaxHeapFreeRatio"); + // Divide by bucket size to prevent a large size from causing rollover when + // calculating amount of memory needed to be allocated for the String table. + status = status && verify_interval(StringTableSize, defaultStringTableSize, + (max_uintx / StringTable::bucket_size()), "StringTable size"); + if (MinHeapFreeRatio > MaxHeapFreeRatio) { jio_fprintf(defaultStream::error_stream(), "MinHeapFreeRatio (" UINTX_FORMAT ") must be less than or " diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/runtime/biasedLocking.cpp --- a/src/share/vm/runtime/biasedLocking.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/runtime/biasedLocking.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -39,7 +39,7 @@ static GrowableArray* _preserved_mark_stack = NULL; static void enable_biased_locking(Klass* k) { - Klass::cast(k)->set_prototype_header(markOopDesc::biased_locking_prototype()); + k->set_prototype_header(markOopDesc::biased_locking_prototype()); } class VM_EnableBiasedLocking: public VM_Operation { @@ -149,7 +149,7 @@ if (TraceBiasedLocking) { ResourceMark rm; tty->print_cr(" (Skipping revocation of object of type %s because it's no longer biased)", - Klass::cast(obj->klass())->external_name()); + obj->klass()->external_name()); } return BiasedLocking::NOT_BIASED; } @@ -161,7 +161,7 @@ if (TraceBiasedLocking && (Verbose || !is_bulk)) { ResourceMark rm; tty->print_cr("Revoking bias of object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT " , allow rebias %d , requesting thread " INTPTR_FORMAT, - (intptr_t) obj, (intptr_t) mark, Klass::cast(obj->klass())->external_name(), (intptr_t) Klass::cast(obj->klass())->prototype_header(), (allow_rebias ? 1 : 0), (intptr_t) requesting_thread); + (intptr_t) obj, (intptr_t) mark, obj->klass()->external_name(), (intptr_t) obj->klass()->prototype_header(), (allow_rebias ? 1 : 0), (intptr_t) requesting_thread); } JavaThread* biased_thread = mark->biased_locker(); @@ -326,7 +326,7 @@ tty->print_cr("* Beginning bulk revocation (kind == %s) because of object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s", (bulk_rebias ? "rebias" : "revoke"), - (intptr_t) o, (intptr_t) o->mark(), Klass::cast(o->klass())->external_name()); + (intptr_t) o, (intptr_t) o->mark(), o->klass()->external_name()); } jlong cur_time = os::javaTimeMillis(); @@ -334,7 +334,7 @@ Klass* k_o = o->klass(); - Klass* klass = Klass::cast(k_o); + Klass* klass = k_o; if (bulk_rebias) { // Use the epoch in the klass of the object to implicitly revoke @@ -546,7 +546,7 @@ return BIAS_REVOKED; } } else if (mark->has_bias_pattern()) { - Klass* k = Klass::cast(obj->klass()); + Klass* k = obj->klass(); markOop prototype_header = k->prototype_header(); if (!prototype_header->has_bias_pattern()) { // This object has a stale bias from before the bulk revocation @@ -590,7 +590,7 @@ if (heuristics == HR_NOT_BIASED) { return NOT_BIASED; } else if (heuristics == HR_SINGLE_REVOKE) { - Klass *k = Klass::cast(obj->klass()); + Klass *k = obj->klass(); markOop prototype_header = k->prototype_header(); if (mark->biased_locker() == THREAD && prototype_header->bias_epoch() == mark->bias_epoch()) { diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/runtime/compilationPolicy.cpp --- a/src/share/vm/runtime/compilationPolicy.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/runtime/compilationPolicy.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -97,6 +97,9 @@ // This is intended to force compiles for methods (usually for // debugging) that would otherwise be interpreted for some reason. bool CompilationPolicy::must_be_compiled(methodHandle m, int comp_level) { + // Don't allow Xcomp to cause compiles in replay mode + if (ReplayCompiles) return false; + if (m->has_compiled_code()) return false; // already compiled if (!can_be_compiled(m, comp_level)) return false; @@ -322,6 +325,16 @@ return NULL; } } + if (CompileTheWorld || ReplayCompiles) { + // Don't trigger other compiles in testing mode + if (bci == InvocationEntryBci) { + reset_counter_for_invocation_event(method); + } else { + reset_counter_for_back_branch_event(method); + } + return NULL; + } + if (bci == InvocationEntryBci) { // when code cache is full, compilation gets switched off, UseCompiler // is set to false diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/runtime/globals.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -3189,6 +3189,26 @@ product(ccstrlist, CompileCommand, "", \ "Prepend to .hotspot_compiler; e.g. log,java/lang/String.") \ \ + develop(bool, ReplayCompiles, false, \ + "Enable replay of compilations from ReplayDataFile") \ + \ + develop(ccstr, ReplayDataFile, "replay.txt", \ + "file containing compilation replay information") \ + \ + develop(intx, ReplaySuppressInitializers, 2, \ + "Controls handling of class initialization during replay" \ + "0 - don't do anything special" \ + "1 - treat all class initializers as empty" \ + "2 - treat class initializers for application classes as empty" \ + "3 - allow all class initializers to run during bootstrap but" \ + " pretend they are empty after starting replay") \ + \ + develop(bool, ReplayIgnoreInitErrors, false, \ + "Ignore exceptions thrown during initialization for replay") \ + \ + develop(bool, DumpReplayDataOnError, true, \ + "record replay data for crashing compiler threads") \ + \ product(bool, CICompilerCountPerCPU, false, \ "1 compiler thread for log(N CPUs)") \ \ @@ -3593,7 +3613,7 @@ diagnostic(bool, PrintDTraceDOF, false, \ "Print the DTrace DOF passed to the system for JSDT probes") \ \ - product(uintx, StringTableSize, 1009, \ + product(uintx, StringTableSize, defaultStringTableSize, \ "Number of buckets in the interned String table") \ \ develop(bool, TraceDefaultMethods, false, \ diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/runtime/os.cpp --- a/src/share/vm/runtime/os.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/runtime/os.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -397,12 +397,16 @@ // Try to load verify dll first. In 1.3 java dll depends on it and is not // always able to find it when the loading executable is outside the JDK. // In order to keep working with 1.2 we ignore any loading errors. - dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), "verify"); - dll_load(buffer, ebuf, sizeof(ebuf)); + if (dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), + "verify")) { + dll_load(buffer, ebuf, sizeof(ebuf)); + } // Load java dll - dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), "java"); - _native_java_library = dll_load(buffer, ebuf, sizeof(ebuf)); + if (dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), + "java")) { + _native_java_library = dll_load(buffer, ebuf, sizeof(ebuf)); + } if (_native_java_library == NULL) { vm_exit_during_initialization("Unable to load native library", ebuf); } @@ -410,8 +414,10 @@ #if defined(__OpenBSD__) // Work-around OpenBSD's lack of $ORIGIN support by pre-loading libnet.so // ignore errors - dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), "net"); - dll_load(buffer, ebuf, sizeof(ebuf)); + if (dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), + "net")) { + dll_load(buffer, ebuf, sizeof(ebuf)); + } #endif } static jboolean onLoaded = JNI_FALSE; @@ -576,7 +582,9 @@ // if NULL is returned the calling functions assume out of memory. size = 1; } - + if (size > size + space_before + space_after) { // Check for rollover. + return NULL; + } NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); u_char* ptr = (u_char*)::malloc(size + space_before + space_after); @@ -1156,7 +1164,7 @@ if (inpath == NULL) { return NULL; } - strncpy(inpath, path, strlen(path)); + strcpy(inpath, path); int count = 1; char* p = strchr(inpath, psepchar); // Get a count of elements to allocate memory diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/runtime/os.hpp --- a/src/share/vm/runtime/os.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/runtime/os.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -479,7 +479,8 @@ static const char* get_current_directory(char *buf, int buflen); // Builds a platform-specific full library path given a ld path and lib name - static void dll_build_name(char* buffer, size_t size, + // Returns true if buffer contains full path to existing file, false otherwise + static bool dll_build_name(char* buffer, size_t size, const char* pathname, const char* fname); // Symbol lookup, find nearest function name; basically it implements diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/runtime/reflection.cpp --- a/src/share/vm/runtime/reflection.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/runtime/reflection.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -70,8 +70,8 @@ } } if (caller != NULL) { - const char * from = Klass::cast(caller)->external_name(); - const char * to = Klass::cast(to_class)->external_name(); + const char * from = caller->external_name(); + const char * to = to_class->external_name(); // print in a single call to reduce interleaving between threads if (source_file != NULL) { tty->print("RESOLVE %s %s %s:%d (reflection)\n", from, to, source_file, line_number); @@ -330,7 +330,7 @@ return TypeArrayKlass::cast(tak)->allocate(length, THREAD); } else { Klass* k = java_lang_Class::as_Klass(element_mirror); - if (Klass::cast(k)->oop_is_array() && ArrayKlass::cast(k)->dimension() >= MAX_DIM) { + if (k->oop_is_array() && ArrayKlass::cast(k)->dimension() >= MAX_DIM) { THROW_0(vmSymbols::java_lang_IllegalArgumentException()); } return oopFactory::new_objArray(k, length, THREAD); @@ -366,7 +366,7 @@ klass = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL); } else { klass = java_lang_Class::as_Klass(element_mirror); - if (Klass::cast(klass)->oop_is_array()) { + if (klass->oop_is_array()) { int k_dim = ArrayKlass::cast(klass)->dimension(); if (k_dim + len > MAX_DIM) { THROW_0(vmSymbols::java_lang_IllegalArgumentException()); @@ -374,7 +374,7 @@ dim += k_dim; } } - klass = Klass::cast(klass)->array_klass(dim, CHECK_NULL); + klass = klass->array_klass(dim, CHECK_NULL); oop obj = ArrayKlass::cast(klass)->multi_allocate(len, dimensions, THREAD); assert(obj->is_array(), "just checking"); return arrayOop(obj); @@ -387,7 +387,7 @@ } Klass* klass = java_lang_Class::as_Klass(mirror); - if (!Klass::cast(klass)->oop_is_array()) { + if (!klass->oop_is_array()) { return NULL; } @@ -395,15 +395,15 @@ #ifdef ASSERT oop result2 = NULL; if (ArrayKlass::cast(klass)->dimension() == 1) { - if (Klass::cast(klass)->oop_is_typeArray()) { + if (klass->oop_is_typeArray()) { result2 = basic_type_arrayklass_to_mirror(klass, CHECK_NULL); } else { - result2 = Klass::cast(ObjArrayKlass::cast(klass)->element_klass())->java_mirror(); + result2 = ObjArrayKlass::cast(klass)->element_klass()->java_mirror(); } } else { Klass* lower_dim = ArrayKlass::cast(klass)->lower_dimension(); - assert(Klass::cast(lower_dim)->oop_is_array(), "just checking"); - result2 = Klass::cast(lower_dim)->java_mirror(); + assert(lower_dim->oop_is_array(), "just checking"); + result2 = lower_dim->java_mirror(); } assert(result == result2, "results must be consistent"); #endif //ASSERT @@ -442,7 +442,7 @@ if (acc.is_protected()) { if (target_class != client_class) { if (!is_same_class_package(client_class, field_class)) { - if (!Klass::cast(target_class)->is_subclass_of(client_class)) { + if (!target_class->is_subclass_of(client_class)) { THROW_(vmSymbols::java_lang_IllegalAccessException(), false); } } @@ -468,7 +468,7 @@ // sun/reflect/MagicAccessorImpl subclasses to succeed trivially. if ( JDK_Version::is_gte_jdk14x_version() && UseNewReflection - && Klass::cast(current_class)->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) { + && current_class->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) { return true; } @@ -546,12 +546,12 @@ if (access.is_protected()) { if (!protected_restriction) { // See if current_class is a subclass of field_class - if (Klass::cast(current_class)->is_subclass_of(field_class)) { + if (current_class->is_subclass_of(field_class)) { if (access.is_static() || // static fields are ok, see 6622385 current_class == resolved_class || field_class == resolved_class || - Klass::cast(current_class)->is_subclass_of(resolved_class) || - Klass::cast(resolved_class)->is_subclass_of(current_class)) { + current_class->is_subclass_of(resolved_class) || + resolved_class->is_subclass_of(current_class)) { return true; } } @@ -566,7 +566,7 @@ // sun/reflect/MagicAccessorImpl subclasses to succeed trivially. if ( JDK_Version::is_gte_jdk14x_version() && UseNewReflection - && Klass::cast(current_class)->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) { + && current_class->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) { return true; } @@ -693,7 +693,7 @@ } oop loader = InstanceKlass::cast(k())->class_loader(); - oop protection_domain = Klass::cast(k())->protection_domain(); + oop protection_domain = k()->protection_domain(); Klass* result = SystemDictionary::resolve_or_fail(signature, Handle(THREAD, loader), Handle(THREAD, protection_domain), @@ -703,7 +703,7 @@ trace_class_resolution(result); } - oop nt = Klass::cast(result)->java_mirror(); + oop nt = result->java_mirror(); return Handle(THREAD, nt); } @@ -937,7 +937,7 @@ ResourceMark rm(THREAD); Handle h_origexception = Exceptions::new_exception(THREAD, vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(Klass::cast(target_klass()), + Method::name_and_sig_as_C_string(target_klass(), method->name(), method->signature())); JavaCallArguments args(h_origexception); @@ -947,7 +947,7 @@ } else { ResourceMark rm(THREAD); THROW_MSG_0(vmSymbols::java_lang_AbstractMethodError(), - Method::name_and_sig_as_C_string(Klass::cast(target_klass()), + Method::name_and_sig_as_C_string(target_klass(), method->name(), method->signature())); } @@ -962,7 +962,7 @@ if (method.is_null()) { ResourceMark rm(THREAD); THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), - Method::name_and_sig_as_C_string(Klass::cast(klass()), + Method::name_and_sig_as_C_string(klass(), reflected_method->name(), reflected_method->signature())); } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/runtime/sharedRuntime.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -1775,7 +1775,7 @@ // The copy_array mechanism is awkward and could be removed, but // the compilers don't call this function except as a last resort, // so it probably doesn't matter. - Klass::cast(src->klass())->copy_array((arrayOopDesc*)src, src_pos, + src->klass()->copy_array((arrayOopDesc*)src, src_pos, (arrayOopDesc*)dest, dest_pos, length, thread); } @@ -1788,8 +1788,8 @@ vframeStream vfst(thread, true); assert(!vfst.at_end(), "Java frame must exist"); Bytecode_checkcast cc(vfst.method(), vfst.method()->bcp_from(vfst.bci())); - Klass* targetKlass = Klass::cast(vfst.method()->constants()->klass_at( - cc.index(), thread)); + Klass* targetKlass = vfst.method()->constants()->klass_at( + cc.index(), thread); return generate_class_cast_message(objName, targetKlass->external_name()); } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/runtime/signature.cpp --- a/src/share/vm/runtime/signature.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/runtime/signature.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -354,7 +354,7 @@ return Universe::java_mirror(type()); Klass* klass = as_klass(class_loader, protection_domain, failure_mode, CHECK_NULL); if (klass == NULL) return NULL; - return Klass::cast(klass)->java_mirror(); + return klass->java_mirror(); } Symbol* SignatureStream::as_symbol_or_null() { diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/runtime/synchronizer.cpp --- a/src/share/vm/runtime/synchronizer.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/runtime/synchronizer.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -1323,7 +1323,7 @@ ResourceMark rm; tty->print_cr("Inflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s", (intptr_t) object, (intptr_t) object->mark(), - Klass::cast(object->klass())->external_name()); + object->klass()->external_name()); } } return m ; @@ -1373,7 +1373,7 @@ ResourceMark rm; tty->print_cr("Inflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s", (intptr_t) object, (intptr_t) object->mark(), - Klass::cast(object->klass())->external_name()); + object->klass()->external_name()); } } return m ; @@ -1440,7 +1440,7 @@ if (obj->is_instance()) { ResourceMark rm; tty->print_cr("Deflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s", - (intptr_t) obj, (intptr_t) obj->mark(), Klass::cast(obj->klass())->external_name()); + (intptr_t) obj, (intptr_t) obj->mark(), obj->klass()->external_name()); } } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/runtime/thread.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -1785,7 +1785,7 @@ jio_fprintf(defaultStream::error_stream(), "\nException: %s thrown from the UncaughtExceptionHandler" " in thread \"%s\"\n", - Klass::cast(pending_exception()->klass())->external_name(), + pending_exception()->klass()->external_name(), get_thread_name()); CLEAR_PENDING_EXCEPTION; } @@ -3753,8 +3753,10 @@ } } else { // Try to load the agent from the standard dll directory - os::dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), name); - library = os::dll_load(buffer, ebuf, sizeof ebuf); + if (os::dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), + name)) { + library = os::dll_load(buffer, ebuf, sizeof ebuf); + } #ifdef KERNEL // Download instrument dll if (library == NULL && strcmp(name, "instrument") == 0) { @@ -3779,8 +3781,9 @@ #endif // KERNEL if (library == NULL) { // Try the local directory char ns[1] = {0}; - os::dll_build_name(buffer, sizeof(buffer), ns, name); - library = os::dll_load(buffer, ebuf, sizeof ebuf); + if (os::dll_build_name(buffer, sizeof(buffer), ns, name)) { + library = os::dll_load(buffer, ebuf, sizeof ebuf); + } if (library == NULL) { const char *sub_msg = " on the library path, with error: "; size_t len = strlen(msg) + strlen(name) + strlen(sub_msg) + strlen(ebuf) + 1; diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/runtime/vframe.cpp --- a/src/share/vm/runtime/vframe.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/runtime/vframe.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -149,7 +149,7 @@ Klass* target_klass = java_lang_Class::as_Klass(obj()); st->print_cr("(a java.lang.Class for %s)", InstanceKlass::cast(target_klass)->external_name()); } else { - Klass* k = Klass::cast(obj->klass()); + Klass* k = obj->klass(); st->print_cr("(a %s)", k->external_name()); } } @@ -172,7 +172,7 @@ } } else if (thread()->current_park_blocker() != NULL) { oop obj = thread()->current_park_blocker(); - Klass* k = Klass::cast(obj->klass()); + Klass* k = obj->klass(); st->print_cr("\t- %s <" INTPTR_FORMAT "> (a %s)", "parking to wait for ", (address)obj, k->external_name()); } } @@ -550,7 +550,7 @@ InstanceKlass* k = m->method_holder(); tty->print_cr("frame( sp=" INTPTR_FORMAT ", unextended_sp=" INTPTR_FORMAT ", fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT ")", _fr.sp(), _fr.unextended_sp(), _fr.fp(), _fr.pc()); - tty->print("%s.%s", Klass::cast(k)->internal_name(), m->name()->as_C_string()); + tty->print("%s.%s", k->internal_name(), m->name()->as_C_string()); if (!m->is_native()) { Symbol* source_name = k->source_file_name(); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/runtime/vmStructs.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -993,6 +993,7 @@ \ nonstatic_field(ciMethod, _interpreter_invocation_count, int) \ nonstatic_field(ciMethod, _interpreter_throwout_count, int) \ + nonstatic_field(ciMethod, _instructions_size, int) \ \ nonstatic_field(ciMethodData, _data_size, int) \ nonstatic_field(ciMethodData, _state, u_char) \ diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/services/classLoadingService.hpp --- a/src/share/vm/services/classLoadingService.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/services/classLoadingService.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -135,7 +135,7 @@ // The spec is unclear at this point to count array klasses or not // and also indirect creation of array of super class and secondaries // - // for (Klass* l = k; l != NULL; l = Klass::cast(l)->array_klass_or_null()) { + // for (Klass* l = k; l != NULL; l = l->array_klass_or_null()) { // KlassHandle h(_current_thread, l); // _loaded_classes->append(h); // } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/services/heapDumper.cpp --- a/src/share/vm/services/heapDumper.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/services/heapDumper.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -879,7 +879,7 @@ writer->write_u4(STACK_TRACE_ID); // class ID - writer->write_classID(Klass::cast(k)); + writer->write_classID(k); // number of bytes that follow writer->write_u4(instance_size(k) ); @@ -891,7 +891,7 @@ // creates HPROF_GC_CLASS_DUMP record for the given class and each of // its array classes void DumperSupport::dump_class_and_array_classes(DumpWriter* writer, Klass* k) { - Klass* klass = Klass::cast(k); + Klass* klass = k; assert(klass->oop_is_instance(), "not an InstanceKlass"); InstanceKlass* ik = (InstanceKlass*)klass; @@ -906,7 +906,7 @@ if (java_super == NULL) { writer->write_objectID(oop(NULL)); } else { - writer->write_classID(Klass::cast(java_super)); + writer->write_classID(java_super); } writer->write_objectID(ik->class_loader()); @@ -932,7 +932,7 @@ // array classes k = klass->array_klass_or_null(); while (k != NULL) { - Klass* klass = Klass::cast(k); + Klass* klass = k; assert(klass->oop_is_objArray(), "not an ObjArrayKlass"); writer->write_u1(HPROF_GC_CLASS_DUMP); @@ -942,7 +942,7 @@ // super class of array classes is java.lang.Object java_super = klass->java_super(); assert(java_super != NULL, "checking"); - writer->write_classID(Klass::cast(java_super)); + writer->write_classID(java_super); writer->write_objectID(ik->class_loader()); writer->write_objectID(ik->signers()); @@ -965,7 +965,7 @@ void DumperSupport::dump_basic_type_array_class(DumpWriter* writer, Klass* k) { // array classes while (k != NULL) { - Klass* klass = Klass::cast(k); + Klass* klass = k; writer->write_u1(HPROF_GC_CLASS_DUMP); writer->write_classID(klass); @@ -974,7 +974,7 @@ // super class of array classes is java.lang.Object Klass* java_super = klass->java_super(); assert(java_super != NULL, "checking"); - writer->write_classID(Klass::cast(java_super)); + writer->write_classID(java_super); writer->write_objectID(oop(NULL)); // loader writer->write_objectID(oop(NULL)); // signers @@ -1001,7 +1001,7 @@ writer->write_u4((u4)array->length()); // array class ID - writer->write_classID(Klass::cast(array->klass())); + writer->write_classID(array->klass()); // [id]* elements for (int index=0; indexlength(); index++) { @@ -1525,7 +1525,7 @@ writer()->write_u4(++class_serial_num); // class ID - Klass* klass = Klass::cast(k); + Klass* klass = k; writer()->write_classID(klass); // add the Klass* and class serial number pair @@ -1796,7 +1796,7 @@ // write fake frame that makes it look like the thread, which caused OOME, // is in the OutOfMemoryError zero-parameter constructor if (thread == _oome_thread && _oome_constructor != NULL) { - int oome_serial_num = _klass_map->find(Klass::cast(_oome_constructor->method_holder())); + int oome_serial_num = _klass_map->find(_oome_constructor->method_holder()); // the class serial number starts from 1 assert(oome_serial_num > 0, "OutOfMemoryError class not found"); DumperSupport::dump_stack_frame(writer(), ++frame_serial_num, oome_serial_num, @@ -1806,7 +1806,7 @@ for (int j=0; j < depth; j++) { StackFrameInfo* frame = stack_trace->stack_frame_at(j); Method* m = frame->method(); - int class_serial_num = _klass_map->find(Klass::cast(m->method_holder())); + int class_serial_num = _klass_map->find(m->method_holder()); // the class serial number starts from 1 assert(class_serial_num > 0, "class not found"); DumperSupport::dump_stack_frame(writer(), ++frame_serial_num, class_serial_num, m, frame->bci()); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/services/management.cpp --- a/src/share/vm/services/management.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/services/management.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -1417,7 +1417,7 @@ for (int i = 0; i < num_classes; i++) { KlassHandle kh = lce.get_klass(i); - oop mirror = Klass::cast(kh())->java_mirror(); + oop mirror = kh()->java_mirror(); classes_ah->obj_at_put(i, mirror); } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/services/memBaseline.cpp --- a/src/share/vm/services/memBaseline.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/services/memBaseline.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -115,17 +115,25 @@ while (malloc_ptr != NULL) { index = flag2index(FLAGS_TO_MEMORY_TYPE(malloc_ptr->flags())); size_t size = malloc_ptr->size(); - _total_malloced += size; - _malloc_data[index].inc(size); - if (MemPointerRecord::is_arena_record(malloc_ptr->flags())) { - // see if arena size record present - MemPointerRecord* next_malloc_ptr = (MemPointerRecordEx*)malloc_itr.peek_next(); - if (MemPointerRecord::is_arena_size_record(next_malloc_ptr->flags())) { - assert(next_malloc_ptr->is_size_record_of_arena(malloc_ptr), "arena records do not match"); - size = next_malloc_ptr->size(); - _arena_data[index].inc(size); - used_arena_size += size; - malloc_itr.next(); + if (malloc_ptr->is_arena_memory_record()) { + // We do have anonymous arenas, they are either used as value objects, + // which are embedded inside other objects, or used as stack objects. + _arena_data[index].inc(size); + used_arena_size += size; + } else { + _total_malloced += size; + _malloc_data[index].inc(size); + if (malloc_ptr->is_arena_record()) { + // see if arena memory record present + MemPointerRecord* next_malloc_ptr = (MemPointerRecordEx*)malloc_itr.peek_next(); + if (next_malloc_ptr->is_arena_memory_record()) { + assert(next_malloc_ptr->is_memory_record_of_arena(malloc_ptr), + "Arena records do not match"); + size = next_malloc_ptr->size(); + _arena_data[index].inc(size); + used_arena_size += size; + malloc_itr.next(); + } } } malloc_ptr = (MemPointerRecordEx*)malloc_itr.next(); @@ -193,7 +201,7 @@ // baseline memory that is totaled over 1 KB while (malloc_ptr != NULL) { - if (!MemPointerRecord::is_arena_size_record(malloc_ptr->flags())) { + if (!MemPointerRecord::is_arena_memory_record(malloc_ptr->flags())) { // skip thread stacks if (!IS_MEMORY_TYPE(malloc_ptr->flags(), mtThreadStack)) { if (malloc_callsite.addr() != malloc_ptr->pc()) { diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/services/memPtr.hpp --- a/src/share/vm/services/memPtr.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/services/memPtr.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -165,7 +165,7 @@ return (flags & (otArena | tag_size)) == otArena; } - inline static bool is_arena_size_record(MEMFLAGS flags) { + inline static bool is_arena_memory_record(MEMFLAGS flags) { return (flags & (otArena | tag_size)) == (otArena | tag_size); } @@ -256,8 +256,8 @@ } // if this record records a size information of an arena - inline bool is_arena_size_record() const { - return is_arena_size_record(_flags); + inline bool is_arena_memory_record() const { + return is_arena_memory_record(_flags); } // if this pointer represents an address to an arena object @@ -266,8 +266,8 @@ } // if this record represents a size information of specific arena - inline bool is_size_record_of_arena(const MemPointerRecord* arena_rc) { - assert(is_arena_size_record(), "not size record"); + inline bool is_memory_record_of_arena(const MemPointerRecord* arena_rc) { + assert(is_arena_memory_record(), "not size record"); assert(arena_rc->is_arena_record(), "not arena record"); return (arena_rc->addr() + sizeof(void*)) == addr(); } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/services/memSnapshot.cpp --- a/src/share/vm/services/memSnapshot.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/services/memSnapshot.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -50,7 +50,7 @@ tty->print_cr(" (tag)"); } } else { - if (rec->is_arena_size_record()) { + if (rec->is_arena_memory_record()) { tty->print_cr(" (arena size)"); } else if (rec->is_allocation_record()) { tty->print_cr(" (malloc)"); @@ -123,20 +123,31 @@ // in different types. bool VMMemPointerIterator::add_reserved_region(MemPointerRecord* rec) { assert(rec->is_allocation_record(), "Sanity check"); - VMMemRegion* cur = (VMMemRegion*)current(); + VMMemRegion* reserved_region = (VMMemRegion*)current(); // we don't have anything yet - if (cur == NULL) { + if (reserved_region == NULL) { return insert_record(rec); } - assert(cur->is_reserved_region(), "Sanity check"); + assert(reserved_region->is_reserved_region(), "Sanity check"); // duplicated records - if (cur->is_same_region(rec)) { + if (reserved_region->is_same_region(rec)) { return true; } - assert(cur->base() > rec->addr(), "Just check: locate()"); - assert(!cur->overlaps_region(rec), "overlapping reserved regions"); + // Overlapping stack regions indicate that a JNI thread failed to + // detach from the VM before exiting. This leaks the JavaThread object. + if (CheckJNICalls) { + guarantee(FLAGS_TO_MEMORY_TYPE(reserved_region->flags()) != mtThreadStack || + !reserved_region->overlaps_region(rec), + "Attached JNI thread exited without being detached"); + } + // otherwise, we should not have overlapping reserved regions + assert(FLAGS_TO_MEMORY_TYPE(reserved_region->flags()) == mtThreadStack || + reserved_region->base() > rec->addr(), "Just check: locate()"); + assert(FLAGS_TO_MEMORY_TYPE(reserved_region->flags()) == mtThreadStack || + !reserved_region->overlaps_region(rec), "overlapping reserved regions"); + return insert_record(rec); } @@ -390,21 +401,31 @@ } } -void MemSnapshot::copy_pointer(MemPointerRecord* dest, const MemPointerRecord* src) { + +void MemSnapshot::copy_seq_pointer(MemPointerRecord* dest, const MemPointerRecord* src) { assert(dest != NULL && src != NULL, "Just check"); assert(dest->addr() == src->addr(), "Just check"); + assert(dest->seq() > 0 && src->seq() > 0, "not sequenced"); - MEMFLAGS flags = dest->flags(); + if (MemTracker::track_callsite()) { + *(SeqMemPointerRecordEx*)dest = *(SeqMemPointerRecordEx*)src; + } else { + *(SeqMemPointerRecord*)dest = *(SeqMemPointerRecord*)src; + } +} + +void MemSnapshot::assign_pointer(MemPointerRecord*dest, const MemPointerRecord* src) { + assert(src != NULL && dest != NULL, "Just check"); + assert(dest->seq() == 0 && src->seq() >0, "cast away sequence"); if (MemTracker::track_callsite()) { *(MemPointerRecordEx*)dest = *(MemPointerRecordEx*)src; } else { - *dest = *src; + *(MemPointerRecord*)dest = *(MemPointerRecord*)src; } } - -// merge a per-thread memory recorder to the staging area +// merge a recorder to the staging area bool MemSnapshot::merge(MemRecorder* rec) { assert(rec != NULL && !rec->out_of_memory(), "Just check"); @@ -412,71 +433,45 @@ MutexLockerEx lock(_lock, true); MemPointerIterator malloc_staging_itr(_staging_area.malloc_data()); - MemPointerRecord *p1, *p2; - p1 = (MemPointerRecord*) itr.current(); - while (p1 != NULL) { - if (p1->is_vm_pointer()) { + MemPointerRecord* incoming_rec = (MemPointerRecord*) itr.current(); + MemPointerRecord* matched_rec; + + while (incoming_rec != NULL) { + if (incoming_rec->is_vm_pointer()) { // we don't do anything with virtual memory records during merge - if (!_staging_area.vm_data()->append(p1)) { + if (!_staging_area.vm_data()->append(incoming_rec)) { return false; } } else { // locate matched record and/or also position the iterator to proper // location for this incoming record. - p2 = (MemPointerRecord*)malloc_staging_itr.locate(p1->addr()); - // we have not seen this memory block, so just add to staging area - if (p2 == NULL) { - if (!malloc_staging_itr.insert(p1)) { + matched_rec = (MemPointerRecord*)malloc_staging_itr.locate(incoming_rec->addr()); + // we have not seen this memory block in this generation, + // so just add to staging area + if (matched_rec == NULL) { + if (!malloc_staging_itr.insert(incoming_rec)) { return false; } - } else if (p1->addr() == p2->addr()) { - MemPointerRecord* staging_next = (MemPointerRecord*)malloc_staging_itr.peek_next(); - // a memory block can have many tagging records, find right one to replace or - // right position to insert - while (staging_next != NULL && staging_next->addr() == p1->addr()) { - if ((staging_next->flags() & MemPointerRecord::tag_masks) <= - (p1->flags() & MemPointerRecord::tag_masks)) { - p2 = (MemPointerRecord*)malloc_staging_itr.next(); - staging_next = (MemPointerRecord*)malloc_staging_itr.peek_next(); - } else { - break; - } + } else if (incoming_rec->addr() == matched_rec->addr()) { + // whoever has higher sequence number wins + if (incoming_rec->seq() > matched_rec->seq()) { + copy_seq_pointer(matched_rec, incoming_rec); } - int df = (p1->flags() & MemPointerRecord::tag_masks) - - (p2->flags() & MemPointerRecord::tag_masks); - if (df == 0) { - assert(p1->seq() > 0, "not sequenced"); - assert(p2->seq() > 0, "not sequenced"); - if (p1->seq() > p2->seq()) { - copy_pointer(p2, p1); - } - } else if (df < 0) { - if (!malloc_staging_itr.insert(p1)) { - return false; - } - } else { - if (!malloc_staging_itr.insert_after(p1)) { - return false; - } - } - } else if (p1->addr() < p2->addr()) { - if (!malloc_staging_itr.insert(p1)) { + } else if (incoming_rec->addr() < matched_rec->addr()) { + if (!malloc_staging_itr.insert(incoming_rec)) { return false; } } else { - if (!malloc_staging_itr.insert_after(p1)) { - return false; - } + ShouldNotReachHere(); } } - p1 = (MemPointerRecord*)itr.next(); + incoming_rec = (MemPointerRecord*)itr.next(); } NOT_PRODUCT(void check_staging_data();) return true; } - // promote data to next generation bool MemSnapshot::promote() { assert(_alloc_ptrs != NULL && _vm_ptrs != NULL, "Just check"); @@ -507,20 +502,25 @@ // found matched memory block if (matched_rec != NULL && new_rec->addr() == matched_rec->addr()) { // snapshot already contains 'live' records - assert(matched_rec->is_allocation_record() || matched_rec->is_arena_size_record(), + assert(matched_rec->is_allocation_record() || matched_rec->is_arena_memory_record(), "Sanity check"); // update block states - if (new_rec->is_allocation_record() || new_rec->is_arena_size_record()) { - copy_pointer(matched_rec, new_rec); + if (new_rec->is_allocation_record()) { + assign_pointer(matched_rec, new_rec); + } else if (new_rec->is_arena_memory_record()) { + if (new_rec->size() == 0) { + // remove size record once size drops to 0 + malloc_snapshot_itr.remove(); + } else { + assign_pointer(matched_rec, new_rec); + } } else { // a deallocation record assert(new_rec->is_deallocation_record(), "Sanity check"); // an arena record can be followed by a size record, we need to remove both if (matched_rec->is_arena_record()) { MemPointerRecord* next = (MemPointerRecord*)malloc_snapshot_itr.peek_next(); - if (next->is_arena_size_record()) { - // it has to match the arena record - assert(next->is_size_record_of_arena(matched_rec), "Sanity check"); + if (next->is_arena_memory_record() && next->is_memory_record_of_arena(matched_rec)) { malloc_snapshot_itr.remove(); } } @@ -528,17 +528,13 @@ malloc_snapshot_itr.remove(); } } else { - // it is a new record, insert into snapshot - if (new_rec->is_arena_size_record()) { - MemPointerRecord* prev = (MemPointerRecord*)malloc_snapshot_itr.peek_prev(); - if (prev == NULL || !prev->is_arena_record() || !new_rec->is_size_record_of_arena(prev)) { - // no matched arena record, ignore the size record - new_rec = NULL; - } + // don't insert size 0 record + if (new_rec->is_arena_memory_record() && new_rec->size() == 0) { + new_rec = NULL; } - // only 'live' record can go into snapshot + if (new_rec != NULL) { - if (new_rec->is_allocation_record() || new_rec->is_arena_size_record()) { + if (new_rec->is_allocation_record() || new_rec->is_arena_memory_record()) { if (matched_rec != NULL && new_rec->addr() > matched_rec->addr()) { if (!malloc_snapshot_itr.insert_after(new_rec)) { return false; diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/services/memSnapshot.hpp --- a/src/share/vm/services/memSnapshot.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/services/memSnapshot.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -31,7 +31,6 @@ #include "services/memBaseline.hpp" #include "services/memPtrArray.hpp" - // Snapshot pointer array iterator // The pointer array contains malloc-ed pointers @@ -165,39 +164,58 @@ }; class MallocRecordIterator : public MemPointerArrayIterator { - protected: + private: MemPointerArrayIteratorImpl _itr; + + public: MallocRecordIterator(MemPointerArray* arr) : _itr(arr) { } virtual MemPointer* current() const { - MemPointerRecord* cur = (MemPointerRecord*)_itr.current(); - assert(cur == NULL || !cur->is_vm_pointer(), "seek error"); - MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next(); - if (next == NULL || next->addr() != cur->addr()) { - return cur; - } else { - assert(!cur->is_vm_pointer(), "Sanity check"); - assert(cur->is_allocation_record() && next->is_deallocation_record(), - "sorting order"); - assert(cur->seq() != next->seq(), "Sanity check"); - return cur->seq() > next->seq() ? cur : next; +#ifdef ASSERT + MemPointer* cur_rec = _itr.current(); + if (cur_rec != NULL) { + MemPointer* prev_rec = _itr.peek_prev(); + MemPointer* next_rec = _itr.peek_next(); + assert(prev_rec == NULL || prev_rec->addr() < cur_rec->addr(), "Sorting order"); + assert(next_rec == NULL || next_rec->addr() > cur_rec->addr(), "Sorting order"); } +#endif + return _itr.current(); } - virtual MemPointer* next() { - MemPointerRecord* cur = (MemPointerRecord*)_itr.current(); - assert(cur == NULL || !cur->is_vm_pointer(), "Sanity check"); - MemPointerRecord* next = (MemPointerRecord*)_itr.next(); - if (next == NULL) { - return NULL; + MemPointerRecord* next_rec = (MemPointerRecord*)_itr.next(); + // arena memory record is a special case, which we have to compare + // sequence number against its associated arena record. + if (next_rec != NULL && next_rec->is_arena_memory_record()) { + MemPointerRecord* prev_rec = (MemPointerRecord*)_itr.peek_prev(); + // if there is an associated arena record, it has to be previous + // record because of sorting order (by address) - NMT generates a pseudo address + // for arena's size record by offsetting arena's address, that guarantees + // the order of arena record and it's size record. + if (prev_rec != NULL && prev_rec->is_arena_record() && + next_rec->is_memory_record_of_arena(prev_rec)) { + if (prev_rec->seq() > next_rec->seq()) { + // Skip this arena memory record + // Two scenarios: + // - if the arena record is an allocation record, this early + // size record must be leftover by previous arena, + // and the last size record should have size = 0. + // - if the arena record is a deallocation record, this + // size record should be its cleanup record, which should + // also have size = 0. In other world, arena alway reset + // its size before gone (see Arena's destructor) + assert(next_rec->size() == 0, "size not reset"); + return _itr.next(); + } else { + assert(prev_rec->is_allocation_record(), + "Arena size record ahead of allocation record"); + } + } } - if (cur->addr() == next->addr()) { - next = (MemPointerRecord*)_itr.next(); - } - return current(); + return next_rec; } MemPointer* peek_next() const { ShouldNotReachHere(); return NULL; } @@ -213,9 +231,12 @@ // still chances seeing duplicated records during promotion. // We want to use the record with higher sequence number, because it has // more accurate callsite pc. -class VMRecordIterator : public MallocRecordIterator { +class VMRecordIterator : public MemPointerArrayIterator { + private: + MemPointerArrayIteratorImpl _itr; + public: - VMRecordIterator(MemPointerArray* arr) : MallocRecordIterator(arr) { + VMRecordIterator(MemPointerArray* arr) : _itr(arr) { MemPointerRecord* cur = (MemPointerRecord*)_itr.current(); MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next(); while (next != NULL) { @@ -256,6 +277,12 @@ return cur; } + MemPointer* peek_next() const { ShouldNotReachHere(); return NULL; } + MemPointer* peek_prev() const { ShouldNotReachHere(); return NULL; } + void remove() { ShouldNotReachHere(); } + bool insert(MemPointer* ptr) { ShouldNotReachHere(); return false; } + bool insert_after(MemPointer* ptr) { ShouldNotReachHere(); return false; } + private: bool is_duplicated_record(MemPointerRecord* p1, MemPointerRecord* p2) const { bool ret = (p1->addr() == p2->addr() && p1->size() == p2->size() && p1->flags() == p2->flags()); @@ -348,8 +375,10 @@ DEBUG_ONLY( void dump_all_vm_pointers();) private: - // copy pointer data from src to dest - void copy_pointer(MemPointerRecord* dest, const MemPointerRecord* src); + // copy sequenced pointer from src to dest + void copy_seq_pointer(MemPointerRecord* dest, const MemPointerRecord* src); + // assign a sequenced pointer to non-sequenced pointer + void assign_pointer(MemPointerRecord*dest, const MemPointerRecord* src); bool promote_malloc_records(MemPointerArrayIterator* itr); bool promote_virtual_memory_records(MemPointerArrayIterator* itr); diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/services/memTracker.hpp --- a/src/share/vm/services/memTracker.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/services/memTracker.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -284,14 +284,14 @@ } } - // record arena size + // record arena memory size static inline void record_arena_size(address addr, size_t size) { - // we add a positive offset to arena address, so we can have arena size record + // we add a positive offset to arena address, so we can have arena memory record // sorted after arena record if (is_on() && !UseMallocOnly) { assert(addr != NULL, "Sanity check"); create_memory_record((addr + sizeof(void*)), MemPointerRecord::arena_size_tag(), size, - 0, NULL); + DEBUG_CALLER_PC, NULL); } } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/services/serviceUtil.hpp --- a/src/share/vm/services/serviceUtil.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/services/serviceUtil.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -57,14 +57,13 @@ if (k->is_klass()) { // if it's a class for an object, an object array, or // primitive (type) array then it's visible. - Klass* klass = k; - if (Klass::cast(klass)->oop_is_instance()) { + if (k->oop_is_instance()) { return true; } - if (Klass::cast(klass)->oop_is_objArray()) { + if (k->oop_is_objArray()) { return true; } - if (Klass::cast(klass)->oop_is_typeArray()) { + if (k->oop_is_typeArray()) { return true; } } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/utilities/array.hpp --- a/src/share/vm/utilities/array.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/utilities/array.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -353,9 +353,9 @@ // sort the array. bool contains(const T& x) const { return index_of(x) >= 0; } - T at(int i) const { return _data[i]; } - void at_put(const int i, const T& x) { _data[i] = x; } - T* adr_at(const int i) { return &_data[i]; } + T at(int i) const { assert(i >= 0 && i< _length, err_msg_res("oob: 0 <= %d < %d", i, _length)); return _data[i]; } + void at_put(const int i, const T& x) { assert(i >= 0 && i< _length, err_msg_res("oob: 0 <= %d < %d", i, _length)); _data[i] = x; } + T* adr_at(const int i) { assert(i >= 0 && i< _length, err_msg_res("oob: 0 <= %d < %d", i, _length)); return &_data[i]; } int find(const T& x) { return index_of(x); } T at_acquire(const int which) { return OrderAccess::load_acquire(adr_at(which)); } diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/utilities/globalDefinitions.hpp --- a/src/share/vm/utilities/globalDefinitions.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/utilities/globalDefinitions.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -328,6 +328,12 @@ //---------------------------------------------------------------------------------------------------- +// Minimum StringTableSize value + +const int defaultStringTableSize=1009; + + +//---------------------------------------------------------------------------------------------------- // HotSwap - for JVMTI aka Class File Replacement and PopFrame // // Determines whether on-the-fly class replacement and frame popping are enabled. diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/utilities/utf8.cpp --- a/src/share/vm/utilities/utf8.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/utilities/utf8.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -147,7 +147,7 @@ void UTF8::convert_to_unicode(const char* utf8_str, jchar* unicode_str, int unicode_length) { unsigned char ch; - const char *ptr = (const char *)utf8_str; + const char *ptr = utf8_str; int index = 0; /* ASCII case loop optimization */ @@ -162,6 +162,119 @@ } } +// returns the quoted ascii length of a 0-terminated utf8 string +int UTF8::quoted_ascii_length(const char* utf8_str, int utf8_length) { + const char *ptr = utf8_str; + const char* end = ptr + utf8_length; + int result = 0; + while (ptr < end) { + jchar c; + ptr = UTF8::next(ptr, &c); + if (c >= 32 && c < 127) { + result++; + } else { + result += 6; + } + } + return result; +} + +// converts a utf8 string to quoted ascii +void UTF8::as_quoted_ascii(const char* utf8_str, char* buf, int buflen) { + const char *ptr = utf8_str; + char* p = buf; + char* end = buf + buflen; + while (*ptr != '\0') { + jchar c; + ptr = UTF8::next(ptr, &c); + if (c >= 32 && c < 127) { + if (p + 1 >= end) break; // string is truncated + *p++ = (char)c; + } else { + if (p + 6 >= end) break; // string is truncated + sprintf(p, "\\u%04x", c); + p += 6; + } + } + *p = '\0'; +} + + +const char* UTF8::from_quoted_ascii(const char* quoted_ascii_str) { + const char *ptr = quoted_ascii_str; + char* result = NULL; + while (*ptr != '\0') { + char c = *ptr; + if (c < 32 || c >= 127) break; + } + if (*ptr == '\0') { + // nothing to do so return original string + return quoted_ascii_str; + } + // everything up to this point was ok. + int length = ptr - quoted_ascii_str; + char* buffer = NULL; + for (int round = 0; round < 2; round++) { + while (*ptr != '\0') { + if (*ptr != '\\') { + if (buffer != NULL) { + buffer[length] = *ptr; + } + length++; + } else { + switch (ptr[1]) { + case 'u': { + ptr += 2; + jchar value=0; + for (int i=0; i<4; i++) { + char c = *ptr++; + switch (c) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + value = (value << 4) + c - '0'; + break; + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': + value = (value << 4) + 10 + c - 'a'; + break; + case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': + value = (value << 4) + 10 + c - 'A'; + break; + default: + ShouldNotReachHere(); + } + } + if (buffer == NULL) { + char utf8_buffer[4]; + char* next = (char*)utf8_write((u_char*)utf8_buffer, value); + length += next - utf8_buffer; + } else { + char* next = (char*)utf8_write((u_char*)&buffer[length], value); + length += next - &buffer[length]; + } + break; + } + case 't': if (buffer != NULL) buffer[length] = '\t'; ptr += 2; length++; break; + case 'n': if (buffer != NULL) buffer[length] = '\n'; ptr += 2; length++; break; + case 'r': if (buffer != NULL) buffer[length] = '\r'; ptr += 2; length++; break; + case 'f': if (buffer != NULL) buffer[length] = '\f'; ptr += 2; length++; break; + default: + ShouldNotReachHere(); + } + } + } + if (round == 0) { + buffer = NEW_RESOURCE_ARRAY(char, length + 1); + ptr = quoted_ascii_str; + } else { + buffer[length] = '\0'; + } + } + return buffer; +} + + // Returns NULL if 'c' it not found. This only works as long // as 'c' is an ASCII character const jbyte* UTF8::strrchr(const jbyte* base, int length, jbyte c) { @@ -242,3 +355,35 @@ } *utf8_buffer = '\0'; } + +// returns the quoted ascii length of a unicode string +int UNICODE::quoted_ascii_length(jchar* base, int length) { + int result = 0; + for (int i = 0; i < length; i++) { + jchar c = base[i]; + if (c >= 32 && c < 127) { + result++; + } else { + result += 6; + } + } + return result; +} + +// converts a utf8 string to quoted ascii +void UNICODE::as_quoted_ascii(const jchar* base, int length, char* buf, int buflen) { + char* p = buf; + char* end = buf + buflen; + for (int index = 0; index < length; index++) { + jchar c = base[index]; + if (c >= 32 && c < 127) { + if (p + 1 >= end) break; // string is truncated + *p++ = (char)c; + } else { + if (p + 6 >= end) break; // string is truncated + sprintf(p, "\\u%04x", c); + p += 6; + } + } + *p = '\0'; +} diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/utilities/utf8.hpp --- a/src/share/vm/utilities/utf8.hpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/utilities/utf8.hpp Fri Nov 16 09:36:40 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,22 +32,32 @@ class UTF8 : AllStatic { public: - // returns the unicode length of a 0-terminated uft8 string - static int unicode_length(const char* uft8_str); + // returns the unicode length of a 0-terminated utf8 string + static int unicode_length(const char* utf8_str); - // returns the unicode length of a non-0-terminated uft8 string - static int unicode_length(const char* uft8_str, int len); + // returns the unicode length of a non-0-terminated utf8 string + static int unicode_length(const char* utf8_str, int len); - // converts a uft8 string to a unicode string + // converts a utf8 string to a unicode string static void convert_to_unicode(const char* utf8_str, jchar* unicode_buffer, int unicode_length); + // returns the quoted ascii length of a utf8 string + static int quoted_ascii_length(const char* utf8_str, int utf8_length); + + // converts a utf8 string to quoted ascii + static void as_quoted_ascii(const char* utf8_str, char* buf, int buflen); + + // converts a quoted ascii string to utf8 string. returns the original + // string unchanged if nothing needs to be done. + static const char* from_quoted_ascii(const char* quoted_ascii_string); + // decodes the current utf8 character, stores the result in value, - // and returns the end of the current uft8 chararacter. + // and returns the end of the current utf8 chararacter. static char* next(const char* str, jchar* value); // decodes the current utf8 character, gets the supplementary character instead of // the surrogate pair when seeing a supplementary character in string, - // stores the result in value, and returns the end of the current uft8 chararacter. + // stores the result in value, and returns the end of the current utf8 chararacter. static char* next_character(const char* str, jint* value); // Utility methods @@ -79,6 +89,12 @@ // in resource area unless a buffer is provided. static char* as_utf8(jchar* base, int length); static char* as_utf8(jchar* base, int length, char* buf, int buflen); + + // returns the quoted ascii length of a unicode string + static int quoted_ascii_length(jchar* base, int length); + + // converts a utf8 string to quoted ascii + static void as_quoted_ascii(const jchar* base, int length, char* buf, int buflen); }; #endif // SHARE_VM_UTILITIES_UTF8_HPP diff -r 4e3e685dbc9d -r cfc5309f03b7 src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Thu Nov 15 15:39:02 2012 -0800 +++ b/src/share/vm/utilities/vmError.cpp Fri Nov 16 09:36:40 2012 -0800 @@ -1009,6 +1009,15 @@ OnError = NULL; } + static bool skip_replay = false; + if (DumpReplayDataOnError && _thread && _thread->is_Compiler_thread() && !skip_replay) { + skip_replay = true; + ciEnv* env = ciEnv::current(); + if (env != NULL) { + env->dump_replay_data(); + } + } + static bool skip_bug_url = !should_report_bug(first_error->_id); if (!skip_bug_url) { skip_bug_url = true;