Mercurial > hg > graal-jvmci-8
changeset 6690:a14a452cf154
Automated merge with https://lafo.ssw.uni-linz.ac.at/hg/graalvm
author | Laurent Daynes <Laurent.Daynes@oracle.com> |
---|---|
date | Fri, 09 Nov 2012 13:35:26 +0100 |
parents | 363968be1018 (diff) 7e77e6359cde (current diff) |
children | 9611d0ccb4ec |
files | |
diffstat | 281 files changed, 19426 insertions(+), 8549 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Fri Nov 09 13:32:53 2012 +0100 +++ b/.hgtags Fri Nov 09 13:35:26 2012 +0100 @@ -269,3 +269,8 @@ 3b3ad16429701b2eb6712851c2f7c5a726eb2cbe hs24-b19 663fc23da8d51c4c0552cbcb17ffc85f5869d4fd jdk8-b51 4c8f2a12e757e7a808aa85827573e09f75d7459f hs24-b20 +6d0436885201db3f581523344a734793bb989549 jdk8-b52 +54240c1b8e87758f28da2c6a569a926fd9e0910a jdk8-b53 +9e3ae661284dc04185b029d85440fe7811f1ed07 hs24-b21 +e8fb566b94667f88462164defa654203f0ab6820 jdk8-b54 +09ea7e0752b306b8ae74713aeb4eb6263e1c6836 hs24-b22
--- a/agent/make/saenv.sh Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/make/saenv.sh Fri Nov 09 13:35:26 2012 +0100 @@ -26,7 +26,7 @@ # This file sets common environment variables for all SA scripts OS=`uname` -STARTDIR=`dirname $0` +STARTDIR=`(cd \`dirname $0 \`; pwd)` ARCH=`uname -m` if [ "x$SA_JAVA" = "x" ]; then
--- a/agent/make/start-debug-server-proc.sh Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/make/start-debug-server-proc.sh Fri Nov 09 13:35:26 2012 +0100 @@ -25,10 +25,11 @@ . `dirname $0`/saenv.sh -if [ -f $STARTDIR/sa.jar ] ; then - CP=$STARTDIR/sa.jar +if [ -f $STARTDIR/../lib/sa-jdi.jar ] ; then + CP=$STARTDIR/../lib/sa-jdi.jar else CP=$STARTDIR/../build/classes fi -$SA_JAVA -classpath $CP ${OPTIONS} -Djava.rmi.server.codebase=file:/$CP -Djava.security.policy=$STARTDIR\/grantAll.policy sun.jvm.hotspot.DebugServer $* +$STARTDIR/java -classpath $CP ${OPTIONS} -Djava.rmi.server.codebase=file://$CP -Djava.security.policy=${STARTDIR}/grantAll.policy sun.jvm.hotspot.DebugServer $* +
--- a/agent/src/os/linux/LinuxDebuggerLocal.c Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/os/linux/LinuxDebuggerLocal.c Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,11 +55,11 @@ #define THROW_NEW_DEBUGGER_EXCEPTION_(str, value) { throw_new_debugger_exception(env, str); return value; } #define THROW_NEW_DEBUGGER_EXCEPTION(str) { throw_new_debugger_exception(env, str); return;} -static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) { +void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) { (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg); } -static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) { +struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) { jlong ptr = (*env)->GetLongField(env, this_obj, p_ps_prochandle_ID); return (struct ps_prochandle*)(intptr_t)ptr; } @@ -280,6 +280,7 @@ return (err == PS_OK)? array : 0; } +#if defined(i386) || defined(ia64) || defined(amd64) || defined(sparc) || defined(sparcv9) JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0 (JNIEnv *env, jobject this_obj, jint lwp_id) { @@ -410,3 +411,4 @@ (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT); return array; } +#endif
--- a/agent/src/os/linux/libproc.h Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/os/linux/libproc.h Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,15 @@ #ifndef _LIBPROC_H_ #define _LIBPROC_H_ +#include <jni.h> #include <unistd.h> #include <stdint.h> #include "proc_service.h" +#if defined(arm) || defined(ppc) +#include "libproc_md.h" +#endif + #if defined(sparc) || defined(sparcv9) /* If _LP64 is defined ptrace.h should be taken from /usr/include/asm-sparc64 @@ -139,4 +144,8 @@ // address->nearest symbol lookup. return NULL for no symbol const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset); +struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj); + +void throw_new_debugger_exception(JNIEnv* env, const char* errMsg); + #endif //__LIBPROC_H_
--- a/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -549,7 +549,13 @@ machDesc = new MachineDescriptionSPARC32Bit(); } } else { - throw new DebuggerException("Linux only supported on x86/ia64/amd64/sparc/sparc64"); + try { + machDesc = (MachineDescription) + Class.forName("sun.jvm.hotspot.debugger.MachineDescription" + + cpu.toUpperCase()).newInstance(); + } catch (Exception e) { + throw new DebuggerException("Linux not supported on machine type " + cpu); + } } LinuxDebuggerLocal dbg =
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -737,9 +737,16 @@ machDesc = new MachineDescriptionSPARC32Bit(); } } else { - throw new DebuggerException("Linux only supported on x86/ia64/amd64/sparc/sparc64"); + try { + machDesc = (MachineDescription) + Class.forName("sun.jvm.hotspot.debugger.MachineDescription" + + cpu.toUpperCase()).newInstance(); + } catch (Exception e) { + throw new DebuggerException("unsupported machine type"); + } } + // Note we do not use a cache for the local debugger in server // mode; it will be taken care of on the client side (once remote // debugging is implemented).
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/ThreadContext.java Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/ThreadContext.java Fri Nov 09 13:35:26 2012 +0100 @@ -24,6 +24,8 @@ package sun.jvm.hotspot.debugger; +import sun.jvm.hotspot.debugger.cdbg.*; + /** This is a placeholder interface for a thread's context, containing only integer registers (no floating-point ones). What it contains is platform-dependent. Not all registers are guaranteed to be @@ -54,4 +56,6 @@ /** Set the value of the specified register (0..getNumRegisters() - 1) as an Address */ public void setRegisterAsAddress(int index, Address value); + + public CFrame getTopFrame(Debugger dbg); }
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/amd64/AMD64ThreadContext.java Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/amd64/AMD64ThreadContext.java Fri Nov 09 13:35:26 2012 +0100 @@ -25,6 +25,7 @@ package sun.jvm.hotspot.debugger.amd64; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.cdbg.*; /** Specifies the thread context on amd64 platforms; only a sub-portion * of the context is guaranteed to be present on all operating @@ -98,6 +99,10 @@ return data[index]; } + public CFrame getTopFrame(Debugger dbg) { + return null; + } + /** This can't be implemented in this class since we would have to * tie the implementation to, for example, the debugging system */ public abstract void setRegisterAsAddress(int index, Address value);
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/ia64/IA64ThreadContext.java Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/ia64/IA64ThreadContext.java Fri Nov 09 13:35:26 2012 +0100 @@ -25,6 +25,7 @@ package sun.jvm.hotspot.debugger.ia64; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.cdbg.*; /** Specifies the thread context on ia64 platform; only a sub-portion of the context is guaranteed to be present on all operating @@ -172,6 +173,10 @@ return data[index]; } + public CFrame getTopFrame(Debugger dbg) { + return null; + } + /** This can't be implemented in this class since we would have to tie the implementation to, for example, the debugging system */ public abstract void setRegisterAsAddress(int index, Address value);
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,7 +107,9 @@ if (pc == null) return null; return new LinuxSPARCCFrame(dbg, sp, pc, LinuxDebuggerLocal.getAddressSize()); } else { - throw new DebuggerException(cpu + " is not yet supported"); + // Runtime exception thrown by LinuxThreadContextFactory if unknown cpu + ThreadContext context = (ThreadContext) thread.getContext(); + return context.getTopFrame(dbg); } }
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ package sun.jvm.hotspot.debugger.linux; +import java.lang.reflect.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.linux.amd64.*; import sun.jvm.hotspot.debugger.linux.ia64.*; @@ -41,8 +42,16 @@ return new LinuxIA64ThreadContext(dbg); } else if (cpu.equals("sparc")) { return new LinuxSPARCThreadContext(dbg); - } else { - throw new RuntimeException("cpu " + cpu + " is not yet supported"); + } else { + try { + Class tcc = Class.forName("sun.jvm.hotspot.debugger.linux." + + cpu.toLowerCase() + ".Linux" + cpu.toUpperCase() + + "ThreadContext"); + Constructor[] ctcc = tcc.getConstructors(); + return (ThreadContext)ctcc[0].newInstance(dbg); + } catch (Exception e) { + throw new RuntimeException("cpu " + cpu + " is not yet supported"); + } } } }
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import java.io.*; import java.net.*; import java.util.*; +import java.lang.reflect.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.cdbg.*; import sun.jvm.hotspot.debugger.proc.amd64.*; @@ -86,7 +87,16 @@ pcRegIndex = AMD64ThreadContext.RIP; fpRegIndex = AMD64ThreadContext.RBP; } else { + try { + Class tfc = Class.forName("sun.jvm.hotspot.debugger.proc." + + cpu.toLowerCase() + ".Proc" + cpu.toUpperCase() + + "ThreadFactory"); + Constructor[] ctfc = tfc.getConstructors(); + threadFactory = (ProcThreadFactory)ctfc[0].newInstance(this); + } catch (Exception e) { throw new RuntimeException("Thread access for CPU architecture " + PlatformInfo.getCPU() + " not yet supported"); + // Note: pcRegIndex and fpRegIndex do not appear to be referenced + } } if (useCache) { // Cache portion of the remote process's address space. @@ -375,7 +385,11 @@ int pagesize = getPageSize0(); if (pagesize == -1) { // return the hard coded default value. - pagesize = (PlatformInfo.getCPU().equals("x86"))? 4096 : 8192; + if (PlatformInfo.getCPU().equals("sparc") || + PlatformInfo.getCPU().equals("amd64") ) + pagesize = 8196; + else + pagesize = 4096; } return pagesize; }
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ import java.rmi.*; import java.util.*; +import java.lang.reflect.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.cdbg.*; @@ -70,7 +71,18 @@ cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize); unalignedAccessesOkay = true; } else { - throw new DebuggerException("Thread access for CPU architecture " + cpu + " not yet supported"); + try { + Class tf = Class.forName("sun.jvm.hotspot.debugger.remote." + + cpu.toLowerCase() + ".Remote" + cpu.toUpperCase() + + "ThreadFactory"); + Constructor[] ctf = tf.getConstructors(); + threadFactory = (RemoteThreadFactory)ctf[0].newInstance(this); + } catch (Exception e) { + throw new DebuggerException("Thread access for CPU architecture " + cpu + " not yet supported"); + } + cachePageSize = 4096; + cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize); + unalignedAccessesOkay = false; } // Cache portion of the remote process's address space.
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/sparc/SPARCThreadContext.java Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/sparc/SPARCThreadContext.java Fri Nov 09 13:35:26 2012 +0100 @@ -25,6 +25,7 @@ package sun.jvm.hotspot.debugger.sparc; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.cdbg.*; /** Currently provides just the minimal information necessary to get stack traces working. FIXME: currently hardwired for v9 -- will @@ -124,6 +125,10 @@ return data[index]; } + public CFrame getTopFrame(Debugger dbg) { + return null; + } + /** This can't be implemented in this class since we would have to tie the implementation to, for example, the debugging system */ public abstract void setRegisterAsAddress(int index, Address value);
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/x86/X86ThreadContext.java Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/x86/X86ThreadContext.java Fri Nov 09 13:35:26 2012 +0100 @@ -25,6 +25,7 @@ package sun.jvm.hotspot.debugger.x86; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.debugger.cdbg.*; /** Specifies the thread context on x86 platforms; only a sub-portion of the context is guaranteed to be present on all operating @@ -109,6 +110,10 @@ return data[index]; } + public CFrame getTopFrame(Debugger dbg) { + return null; + } + /** This can't be implemented in this class since we would have to tie the implementation to, for example, the debugging system */ public abstract void setRegisterAsAddress(int index, Address value);
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -91,6 +91,16 @@ access = new LinuxAMD64JavaThreadPDAccess(); } else if (cpu.equals("sparc")) { access = new LinuxSPARCJavaThreadPDAccess(); + } else { + try { + access = (JavaThreadPDAccess) + Class.forName("sun.jvm.hotspot.runtime.linux_" + + cpu.toLowerCase() + ".Linux" + cpu.toUpperCase() + + "JavaThreadPDAccess").newInstance(); + } catch (Exception e) { + throw new RuntimeException("OS/CPU combination " + os + "/" + cpu + + " not yet supported"); + } } } else if (os.equals("bsd")) { if (cpu.equals("x86")) {
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Fri Nov 09 13:35:26 2012 +0100 @@ -92,6 +92,8 @@ private boolean usingServerCompiler; /** Flag indicating whether UseTLAB is turned on */ private boolean useTLAB; + /** Flag indicating whether invokedynamic support is on */ + private boolean enableInvokeDynamic; /** alignment constants */ private boolean isLP64; private int bytesPerLong; @@ -317,6 +319,7 @@ } useTLAB = (db.lookupIntConstant("UseTLAB").intValue() != 0); + enableInvokeDynamic = (db.lookupIntConstant("EnableInvokeDynamic").intValue() != 0); if (debugger != null) { isLP64 = debugger.getMachineDescription().isLP64(); @@ -552,6 +555,10 @@ return useTLAB; } + public boolean getEnableInvokeDynamic() { + return enableInvokeDynamic; + } + public TypeDataBase getTypeDataBase() { return db; }
--- a/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Fri Nov 09 13:35:26 2012 +0100 @@ -204,7 +204,13 @@ } else if (cpu.equals("ia64")) { cpuHelper = new IA64Helper(); } else { + try { + cpuHelper = (CPUHelper)Class.forName("sun.jvm.hotspot.asm." + + cpu.toLowerCase() + "." + cpu.toUpperCase() + + "Helper").newInstance(); + } catch (Exception e) { throw new RuntimeException("cpu '" + cpu + "' is not yet supported!"); + } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/AltPlatformInfo.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.utilities; + +public interface AltPlatformInfo { + // Additional cpu types can be tested via this interface + + public boolean knownCPU(String cpu); +} \ No newline at end of file
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java Fri Nov 09 13:32:53 2012 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java Fri Nov 09 13:35:26 2012 +0100 @@ -64,6 +64,13 @@ } else if (cpu.equals("ia64") || cpu.equals("amd64") || cpu.equals("x86_64")) { return cpu; } else { + try { + Class pic = Class.forName("sun.jvm.hotspot.utilities.PlatformInfoClosed"); + AltPlatformInfo api = (AltPlatformInfo)pic.newInstance(); + if (api.knownCPU(cpu)) { + return cpu; + } + } catch (Exception e) {} throw new UnsupportedPlatformException("CPU type " + cpu + " not yet supported"); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.amd64; + +import static com.oracle.graal.api.code.MemoryBarriers.*; +import static com.oracle.graal.api.code.Register.RegisterFlag.*; +import static com.oracle.graal.api.meta.Kind.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.Register.*; + +/** + * Represents the AMD64 architecture. + */ +public class AMD64 extends Architecture { + + // General purpose CPU registers + public static final Register rax = new Register(0, 0, 8, "rax", CPU, RegisterFlag.Byte); + public static final Register rcx = new Register(1, 1, 8, "rcx", CPU, RegisterFlag.Byte); + public static final Register rdx = new Register(2, 2, 8, "rdx", CPU, RegisterFlag.Byte); + public static final Register rbx = new Register(3, 3, 8, "rbx", CPU, RegisterFlag.Byte); + public static final Register rsp = new Register(4, 4, 8, "rsp", CPU, RegisterFlag.Byte); + public static final Register rbp = new Register(5, 5, 8, "rbp", CPU, RegisterFlag.Byte); + public static final Register rsi = new Register(6, 6, 8, "rsi", CPU, RegisterFlag.Byte); + public static final Register rdi = new Register(7, 7, 8, "rdi", CPU, RegisterFlag.Byte); + + public static final Register r8 = new Register(8, 8, 8, "r8", CPU, RegisterFlag.Byte); + public static final Register r9 = new Register(9, 9, 8, "r9", CPU, RegisterFlag.Byte); + public static final Register r10 = new Register(10, 10, 8, "r10", CPU, RegisterFlag.Byte); + public static final Register r11 = new Register(11, 11, 8, "r11", CPU, RegisterFlag.Byte); + public static final Register r12 = new Register(12, 12, 8, "r12", CPU, RegisterFlag.Byte); + public static final Register r13 = new Register(13, 13, 8, "r13", CPU, RegisterFlag.Byte); + public static final Register r14 = new Register(14, 14, 8, "r14", CPU, RegisterFlag.Byte); + public static final Register r15 = new Register(15, 15, 8, "r15", CPU, RegisterFlag.Byte); + + public static final Register[] cpuRegisters = { + rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, + r8, r9, r10, r11, r12, r13, r14, r15 + }; + + // XMM registers + public static final Register xmm0 = new Register(16, 0, 8, "xmm0", FPU); + public static final Register xmm1 = new Register(17, 1, 8, "xmm1", FPU); + public static final Register xmm2 = new Register(18, 2, 8, "xmm2", FPU); + public static final Register xmm3 = new Register(19, 3, 8, "xmm3", FPU); + public static final Register xmm4 = new Register(20, 4, 8, "xmm4", FPU); + public static final Register xmm5 = new Register(21, 5, 8, "xmm5", FPU); + public static final Register xmm6 = new Register(22, 6, 8, "xmm6", FPU); + public static final Register xmm7 = new Register(23, 7, 8, "xmm7", FPU); + + public static final Register xmm8 = new Register(24, 8, 8, "xmm8", FPU); + public static final Register xmm9 = new Register(25, 9, 8, "xmm9", FPU); + public static final Register xmm10 = new Register(26, 10, 8, "xmm10", FPU); + public static final Register xmm11 = new Register(27, 11, 8, "xmm11", FPU); + public static final Register xmm12 = new Register(28, 12, 8, "xmm12", FPU); + public static final Register xmm13 = new Register(29, 13, 8, "xmm13", FPU); + public static final Register xmm14 = new Register(30, 14, 8, "xmm14", FPU); + public static final Register xmm15 = new Register(31, 15, 8, "xmm15", FPU); + + public static final Register[] xmmRegisters = { + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, + xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 + }; + + public static final Register[] cpuxmmRegisters = { + rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, + r8, r9, r10, r11, r12, r13, r14, r15, + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, + xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 + }; + + /** + * Register used to construct an instruction-relative address. + */ + public static final Register rip = new Register(32, -1, 0, "rip"); + + public static final Register[] allRegisters = { + rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, + r8, r9, r10, r11, r12, r13, r14, r15, + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, + xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, + rip + }; + + public static final RegisterValue RSP = rsp.asValue(Long); + + public AMD64() { + super("AMD64", + 8, + ByteOrder.LittleEndian, + allRegisters, + LOAD_STORE | STORE_STORE, + 1, + r15.encoding + 1, + 8); + } +}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Fri Nov 09 13:35:26 2012 +0100 @@ -45,60 +45,45 @@ * The number of bits required in a bit map covering all the registers that may store references. * The bit position of a register in the map is the register's {@linkplain Register#number number}. */ - public final int registerReferenceMapBitCount; + private final int registerReferenceMapBitCount; /** * Represents the natural size of words (typically registers and pointers) of this architecture, in bytes. */ - public final int wordSize; + private final int wordSize; /** * The name of this architecture (e.g. "AMD64", "SPARCv9"). */ - public final String name; + private final String name; /** * Array of all available registers on this architecture. The index of each register in this * array is equal to its {@linkplain Register#number number}. */ - public final Register[] registers; - - /** - * Map of all registers keyed by their {@linkplain Register#name names}. - */ - public final HashMap<String, Register> registersByName; + private final Register[] registers; /** * The byte ordering can be either little or big endian. */ - public final ByteOrder byteOrder; + private final ByteOrder byteOrder; /** * Mask of the barrier constants denoting the barriers that * are not required to be explicitly inserted under this architecture. */ - public final int implicitMemoryBarriers; - - /** - * Determines the barriers in a given barrier mask that are explicitly required on this architecture. - * - * @param barriers a mask of the barrier constants - * @return the value of {@code barriers} minus the barriers unnecessary on this architecture - */ - public final int requiredBarriers(int barriers) { - return barriers & ~implicitMemoryBarriers; - } + private final int implicitMemoryBarriers; /** * Offset in bytes from the beginning of a call instruction to the displacement. */ - public final int machineCodeCallDisplacementOffset; + private final int machineCodeCallDisplacementOffset; /** * The size of the return address pushed to the stack by a call instruction. * A value of 0 denotes that call linkage uses registers instead (e.g. SPARC). */ - public final int returnAddressSize; + private final int returnAddressSize; private final EnumMap<RegisterFlag, Register[]> registersByTypeAndEncoding; @@ -133,12 +118,6 @@ this.registerReferenceMapBitCount = registerReferenceMapBitCount; this.returnAddressSize = returnAddressSize; - registersByName = new HashMap<>(registers.length); - for (Register register : registers) { - registersByName.put(register.name, register); - assert registers[register.number] == register; - } - registersByTypeAndEncoding = new EnumMap<>(RegisterFlag.class); EnumMap<RegisterFlag, Register[]> categorizedRegs = Register.categorize(registers); for (RegisterFlag type : RegisterFlag.values()) { @@ -158,54 +137,69 @@ */ @Override public final String toString() { - return name.toLowerCase(); + return getName().toLowerCase(); + } + + public int getRegisterReferenceMapBitCount() { + return registerReferenceMapBitCount; } /** - * Checks whether this is a 32-bit architecture. - * @return {@code true} if this architecture is 32-bit + * Gets the natural size of words (typically registers and pointers) of this architecture, in bytes. */ - public final boolean is32bit() { - return wordSize == 4; + public int getWordSize() { + return wordSize; + } + + /** + * Gets the name of this architecture. + */ + public String getName() { + return name; } /** - * Checks whether this is a 64-bit architecture. - * @return {@code true} if this architecture is 64-bit + * Gets an array of all available registers on this architecture. The index of each register in this + * array is equal to its {@linkplain Register#number number}. */ - public final boolean is64bit() { - return wordSize == 8; + public Register[] getRegisters() { + return registers.clone(); } - // The following methods are architecture specific and not dependent on state - // stored in this class. They have convenient default implementations. + public ByteOrder getByteOrder() { + return byteOrder; + } /** - * Checks whether this architecture's normal arithmetic instructions use a two-operand form - * (e.g. x86 which overwrites one operand register with the result when adding). - * @return {@code true} if this architecture uses two-operand mode + * Gets a mask of the barrier constants denoting the barriers that + * are not required to be explicitly inserted under this architecture. */ - public boolean twoOperandMode() { - return false; - } - - // TODO: Why enumerate the concrete subclasses here rather - // than use instanceof comparisons in code that cares? - - /** - * Checks whether the architecture is x86. - * @return {@code true} if the architecture is x86 - */ - public boolean isX86() { - return false; + public int getImplicitMemoryBarriers() { + return implicitMemoryBarriers; } /** - * Checks whether the architecture is SPARC. - * @return {@code true} if the architecture is SPARC + * Gets the size of the return address pushed to the stack by a call instruction. + * A value of 0 denotes that call linkage uses registers instead. */ - public boolean isSPARC() { - return false; + public int getReturnAddressSize() { + return returnAddressSize; } + /** + * Gets the offset in bytes from the beginning of a call instruction to the displacement. + */ + public int getMachineCodeCallDisplacementOffset() { + return machineCodeCallDisplacementOffset; + } + + /** + * Determines the barriers in a given barrier mask that are explicitly required on this architecture. + * + * @param barriers a mask of the barrier constants + * @return the value of {@code barriers} minus the barriers unnecessary on this architecture + */ + public final int requiredBarriers(int barriers) { + return barriers & ~implicitMemoryBarriers; + } }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java Fri Nov 09 13:35:26 2012 +0100 @@ -240,6 +240,8 @@ public final Architecture arch; + private final Register[] registers; + /** * The offset (in bytes) from the slot pointed to by {@link #fp} to the slot corresponding to bit 0 in the frame * reference map. @@ -251,6 +253,7 @@ this.slotSize = slotSize; this.fp = fp; this.refMapToFPOffset = refMapToFPOffset; + this.registers = arch.getRegisters(); } public String formatStackSlot(int frameRefMapIndex) { @@ -263,7 +266,7 @@ } public String formatRegister(int regRefMapIndex) { - return arch.registers[regRefMapIndex].toString(); + return registers[regRefMapIndex].toString(); } }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Fri Nov 09 13:35:26 2012 +0100 @@ -57,7 +57,7 @@ private static final long serialVersionUID = 2479806696381720162L; public final DebugInfo debugInfo; - Safepoint(int pcOffset, DebugInfo debugInfo) { + public Safepoint(int pcOffset, DebugInfo debugInfo) { super(pcOffset); this.debugInfo = debugInfo; } @@ -105,7 +105,7 @@ */ public final boolean direct; - Call(Object target, int pcOffset, int size, boolean direct, DebugInfo debugInfo) { + public Call(Object target, int pcOffset, int size, boolean direct, DebugInfo debugInfo) { super(pcOffset, debugInfo); this.size = size; this.target = target; @@ -300,7 +300,7 @@ public final Object id; public final Mark[] references; - Mark(int pcOffset, Object id, Mark[] references) { + public Mark(int pcOffset, Object id, Mark[] references) { super(pcOffset); this.id = id; this.references = references;
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TargetDescription.java Fri Nov 09 13:35:26 2012 +0100 @@ -101,7 +101,7 @@ this.arch = arch; this.pageSize = pageSize; this.isMP = isMP; - this.wordSize = arch.wordSize; + this.wordSize = arch.getWordSize(); if (wordSize == 8) { this.wordKind = Kind.Long; } else { @@ -145,7 +145,7 @@ * @return the aligned frame size */ public int alignFrameSize(int frameSize) { - int x = frameSize + arch.returnAddressSize + (stackAlignment - 1); - return (x / stackAlignment) * stackAlignment - arch.returnAddressSize; + int x = frameSize + arch.getReturnAddressSize() + (stackAlignment - 1); + return (x / stackAlignment) * stackAlignment - arch.getReturnAddressSize(); } }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantPool.java Fri Nov 09 13:35:26 2012 +0100 @@ -29,9 +29,9 @@ public interface ConstantPool { /** - * Makes sure that the type referenced by the specified constant pool entry is loaded and initialized. This can be + * Ensures that the type referenced by the specified constant pool entry is loaded and initialized. This can be * used to compile time resolve a type. It works for field, method, or type constant pool entries. - * + * * @param cpi the index of the constant pool entry that references the type * @param opcode the opcode of the instruction that references the type */ @@ -41,7 +41,7 @@ * Looks up a reference to a field. If {@code opcode} is non-negative, then resolution checks specific to the * bytecode it denotes are performed if the field is already resolved. Should any of these checks fail, an * unresolved field reference is returned. - * + * * @param cpi the constant pool index * @param opcode the opcode of the instruction for which the lookup is being performed or {@code -1} * @return a reference to the field at {@code cpi} in this pool @@ -53,7 +53,7 @@ * Looks up a reference to a method. If {@code opcode} is non-negative, then resolution checks specific to the * bytecode it denotes are performed if the method is already resolved. Should any of these checks fail, an * unresolved method reference is returned. - * + * * @param cpi the constant pool index * @param opcode the opcode of the instruction for which the lookup is being performed or {@code -1} * @return a reference to the method at {@code cpi} in this pool @@ -65,7 +65,7 @@ * Looks up a reference to a type. If {@code opcode} is non-negative, then resolution checks specific to the * bytecode it denotes are performed if the type is already resolved. Should any of these checks fail, an unresolved * type reference is returned. - * + * * @param cpi the constant pool index * @param opcode the opcode of the instruction for which the lookup is being performed or {@code -1} * @return a reference to the compiler interface type @@ -74,7 +74,7 @@ /** * Looks up a method signature. - * + * * @param cpi the constant pool index * @return the method signature at index {@code cpi} in this constant pool */ @@ -82,7 +82,7 @@ /** * Looks up a constant at the specified index. - * + * * @param cpi the constant pool index * @return the {@code Constant} or {@code JavaType} instance representing the constant pool entry */
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64.java Fri Nov 09 13:32:53 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.asm.amd64; - -import static com.oracle.graal.api.code.MemoryBarriers.*; -import static com.oracle.graal.api.code.Register.RegisterFlag.*; -import static com.oracle.graal.api.meta.Kind.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.Register.*; - -/** - * Represents the AMD64 architecture. - */ -public class AMD64 extends Architecture { - - // General purpose CPU registers - public static final Register rax = new Register(0, 0, 8, "rax", CPU, RegisterFlag.Byte); - public static final Register rcx = new Register(1, 1, 8, "rcx", CPU, RegisterFlag.Byte); - public static final Register rdx = new Register(2, 2, 8, "rdx", CPU, RegisterFlag.Byte); - public static final Register rbx = new Register(3, 3, 8, "rbx", CPU, RegisterFlag.Byte); - public static final Register rsp = new Register(4, 4, 8, "rsp", CPU, RegisterFlag.Byte); - public static final Register rbp = new Register(5, 5, 8, "rbp", CPU, RegisterFlag.Byte); - public static final Register rsi = new Register(6, 6, 8, "rsi", CPU, RegisterFlag.Byte); - public static final Register rdi = new Register(7, 7, 8, "rdi", CPU, RegisterFlag.Byte); - - public static final Register r8 = new Register(8, 8, 8, "r8", CPU, RegisterFlag.Byte); - public static final Register r9 = new Register(9, 9, 8, "r9", CPU, RegisterFlag.Byte); - public static final Register r10 = new Register(10, 10, 8, "r10", CPU, RegisterFlag.Byte); - public static final Register r11 = new Register(11, 11, 8, "r11", CPU, RegisterFlag.Byte); - public static final Register r12 = new Register(12, 12, 8, "r12", CPU, RegisterFlag.Byte); - public static final Register r13 = new Register(13, 13, 8, "r13", CPU, RegisterFlag.Byte); - public static final Register r14 = new Register(14, 14, 8, "r14", CPU, RegisterFlag.Byte); - public static final Register r15 = new Register(15, 15, 8, "r15", CPU, RegisterFlag.Byte); - - public static final Register[] cpuRegisters = { - rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, - r8, r9, r10, r11, r12, r13, r14, r15 - }; - - // XMM registers - public static final Register xmm0 = new Register(16, 0, 8, "xmm0", FPU); - public static final Register xmm1 = new Register(17, 1, 8, "xmm1", FPU); - public static final Register xmm2 = new Register(18, 2, 8, "xmm2", FPU); - public static final Register xmm3 = new Register(19, 3, 8, "xmm3", FPU); - public static final Register xmm4 = new Register(20, 4, 8, "xmm4", FPU); - public static final Register xmm5 = new Register(21, 5, 8, "xmm5", FPU); - public static final Register xmm6 = new Register(22, 6, 8, "xmm6", FPU); - public static final Register xmm7 = new Register(23, 7, 8, "xmm7", FPU); - - public static final Register xmm8 = new Register(24, 8, 8, "xmm8", FPU); - public static final Register xmm9 = new Register(25, 9, 8, "xmm9", FPU); - public static final Register xmm10 = new Register(26, 10, 8, "xmm10", FPU); - public static final Register xmm11 = new Register(27, 11, 8, "xmm11", FPU); - public static final Register xmm12 = new Register(28, 12, 8, "xmm12", FPU); - public static final Register xmm13 = new Register(29, 13, 8, "xmm13", FPU); - public static final Register xmm14 = new Register(30, 14, 8, "xmm14", FPU); - public static final Register xmm15 = new Register(31, 15, 8, "xmm15", FPU); - - public static final Register[] xmmRegisters = { - xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, - xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 - }; - - public static final Register[] cpuxmmRegisters = { - rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, - r8, r9, r10, r11, r12, r13, r14, r15, - xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, - xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 - }; - - /** - * Register used to construct an instruction-relative address. - */ - public static final Register rip = new Register(32, -1, 0, "rip"); - - public static final Register[] allRegisters = { - rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, - r8, r9, r10, r11, r12, r13, r14, r15, - xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, - xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, - rip - }; - - public static final RegisterValue RSP = rsp.asValue(Long); - - public AMD64() { - super("AMD64", - 8, - ByteOrder.LittleEndian, - allRegisters, - LOAD_STORE | STORE_STORE, - 1, - r15.encoding + 1, - 8); - } - - @Override - public boolean isX86() { - return true; - } - - @Override - public boolean twoOperandMode() { - return true; - } - -}
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Fri Nov 09 13:35:26 2012 +0100 @@ -22,12 +22,13 @@ */ package com.oracle.graal.asm.amd64; +import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.MemoryBarriers.*; import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.asm.NumUtil.*; -import static com.oracle.graal.asm.amd64.AMD64.*; import static com.oracle.graal.asm.amd64.AMD64AsmOptions.*; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*;
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java Fri Nov 09 13:35:26 2012 +0100 @@ -24,6 +24,7 @@ import static com.oracle.graal.asm.amd64.AMD64AsmOptions.*; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*;
--- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java Fri Nov 09 13:35:26 2012 +0100 @@ -35,7 +35,7 @@ public AbstractAssembler(TargetDescription target) { this.target = target; - if (target.arch.byteOrder == ByteOrder.BigEndian) { + if (target.arch.getByteOrder() == ByteOrder.BigEndian) { this.codeBuffer = new Buffer.BigEndian(); } else { this.codeBuffer = new Buffer.LittleEndian();
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Fri Nov 09 13:35:26 2012 +0100 @@ -27,12 +27,12 @@ import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*; import static com.oracle.graal.lir.amd64.AMD64Compare.*; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.*; +import com.oracle.graal.api.code.RuntimeCall.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; -import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.asm.amd64.AMD64Assembler.*; +import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.graph.*; @@ -100,7 +100,7 @@ } } - public AMD64LIRGenerator(Graph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { + public AMD64LIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { super(graph, runtime, target, frameMap, method, lir); lir.spillMoveFactory = new AMD64SpillMoveFactory(); }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Fri Nov 09 13:35:26 2012 +0100 @@ -44,8 +44,9 @@ import com.oracle.graal.phases.schedule.*; /** - * Base class for Graal compiler unit tests. These are white box tests - * for Graal compiler transformations. The general pattern for a test is: + * Base class for Graal compiler unit tests. + * <p> + * White box tests for Graal compiler transformations use this pattern: * <ol> * <li>Create a graph by {@linkplain #parse(String) parsing} a method.</li> * <li>Manually modify the graph (e.g. replace a parameter node with a constant).</li> @@ -53,11 +54,13 @@ * <li>Assert that the transformed graph is equal to an expected graph.</li> * </ol> * <p> - * See {@link InvokeHintsTest} as an example. + * See {@link InvokeHintsTest} as an example of a white box test. * <p> - * The tests can be run in Eclipse with the "Compiler Unit Test" Eclipse - * launch configuration found in the top level of this project or by - * running {@code mx unittest} on the command line. + * Black box tests use the {@link #test(String, Object...)} or {@link #testN(int, String, Object...)} + * to execute some method in the interpreter and compare its result against that produced + * by a Graal compiled version of the method. + * <p> + * These tests will be run by the {@code mx unittest} command. */ public abstract class GraalCompilerTest { @@ -295,7 +298,7 @@ GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); editPhasePlan(method, graph, phasePlan); - CompilationResult compResult = graalCompiler.compileMethod(method, graph, -1, null, phasePlan, OptimisticOptimizations.ALL); + CompilationResult compResult = graalCompiler.compileMethod(method, graph, null, phasePlan, OptimisticOptimizations.ALL); return addMethod(method, compResult); } });
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Fri Nov 09 13:35:26 2012 +0100 @@ -165,7 +165,7 @@ Debug.dump(graph, "Graph"); // TypeSystemTest.outputGraph(graph); new CanonicalizerPhase(null, runtime(), null).apply(graph); - new CheckCastEliminationPhase().apply(graph); + new ConditionalEliminationPhase().apply(graph); new CanonicalizerPhase(null, runtime(), null).apply(graph); StructuredGraph referenceGraph = parse(referenceSnippet); assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Fri Nov 09 13:35:26 2012 +0100 @@ -190,7 +190,7 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); new CanonicalizerPhase(null, runtime(), null).apply(graph); - new CheckCastEliminationPhase().apply(graph); + new ConditionalEliminationPhase().apply(graph); new CanonicalizerPhase(null, runtime(), null).apply(graph); new GlobalValueNumberingPhase().apply(graph); StructuredGraph referenceGraph = parse(referenceSnippet); @@ -254,7 +254,7 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); new CanonicalizerPhase(null, runtime(), null).apply(graph); - new CheckCastEliminationPhase().apply(graph); + new ConditionalEliminationPhase().apply(graph); new CanonicalizerPhase(null, runtime(), null).apply(graph); Debug.dump(graph, "Graph"); Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext());
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Fri Nov 09 13:35:26 2012 +0100 @@ -40,11 +40,10 @@ import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.*; +import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.virtual.phases.ea.*; -import com.oracle.graal.virtual.phases.ea.experimental.*; public class GraalCompiler { @@ -69,12 +68,9 @@ this.backend = backend; } - public CompilationResult compileMethod(final ResolvedJavaMethod method, final StructuredGraph graph, int osrBCI, final GraphCache cache, final PhasePlan plan, + public CompilationResult compileMethod(final ResolvedJavaMethod method, final StructuredGraph graph, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts) { assert (method.getModifiers() & Modifier.NATIVE) == 0 : "compiling native methods is not supported"; - if (osrBCI != -1) { - throw new BailoutException("No OSR supported"); - } return Debug.scope("GraalCompiler", new Object[]{graph, method, this}, new Callable<CompilationResult>() { @@ -134,7 +130,7 @@ } if (GraalOptions.CheckCastElimination && GraalOptions.OptCanonicalizer) { - new IterativeCheckCastEliminationPhase(target, runtime, assumptions).apply(graph); + new IterativeConditionalEliminationPhase(target, runtime, assumptions).apply(graph); } } @@ -157,7 +153,7 @@ } if (GraalOptions.PartialEscapeAnalysis && !plan.isPhaseDisabled(PartialEscapeAnalysisPhase.class)) { - new SplitPartialEscapeAnalysisPhase(runtime).apply(graph); + new PartialEscapeAnalysisPhase(target, runtime, assumptions).apply(graph); } if (GraalOptions.OptLoopTransform) { new LoopTransformHighPhase().apply(graph); @@ -172,7 +168,7 @@ new CullFrameStatesPhase().apply(graph); } - if (GraalOptions.FloatingReads) { + if (GraalOptions.OptFloatingReads) { int mark = graph.getMark(); new FloatingReadPhase().apply(graph); new CanonicalizerPhase(target, runtime, assumptions, mark, null).apply(graph); @@ -190,8 +186,16 @@ new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } + if (GraalOptions.OptEliminatePartiallyRedundantGuards) { + new EliminatePartiallyRedundantGuardsPhase(false, true).apply(graph); + } + if (GraalOptions.CheckCastElimination && GraalOptions.OptCanonicalizer) { - new IterativeCheckCastEliminationPhase(target, runtime, assumptions).apply(graph); + new IterativeConditionalEliminationPhase(target, runtime, assumptions).apply(graph); + } + + if (GraalOptions.OptEliminatePartiallyRedundantGuards) { + new EliminatePartiallyRedundantGuardsPhase(true, true).apply(graph); } plan.runPhases(PhasePosition.MID_LEVEL, graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Fri Nov 09 13:35:26 2012 +0100 @@ -163,7 +163,7 @@ this.sortedBlocks = ir.linearScanOrder().toArray(new Block[ir.linearScanOrder().size()]); this.registerAttributes = frameMap.registerConfig.getAttributesMap(); - this.registers = target.arch.registers; + this.registers = target.arch.getRegisters(); this.firstVariableNumber = registers.length; this.variables = new ArrayList<>(ir.numVariables() * 3 / 2); this.blockData = new BlockMap<>(ir.cfg); @@ -1417,7 +1417,7 @@ notPrecoloredIntervals = result.second; // allocate cpu registers - LinearScanWalker lsw = new LinearScanWalker(this, precoloredIntervals, notPrecoloredIntervals, !target.arch.isX86()); + LinearScanWalker lsw = new LinearScanWalker(this, precoloredIntervals, notPrecoloredIntervals); lsw.walk(); lsw.finishAllocation(); } @@ -1594,49 +1594,6 @@ // * Phase 7: assign register numbers back to LIR // (includes computation of debug information and oop maps) - boolean verifyAssignedLocation(Interval interval, Value location) { - Kind kind = interval.kind(); - - assert isRegister(location) || isStackSlot(location); - - if (isRegister(location)) { - Register reg = asRegister(location); - - // register - switch (kind) { - case Byte: - case Char: - case Short: - case Jsr: - case Object: - case Int: { - assert reg.isCpu() : "not cpu register"; - break; - } - - case Long: { - assert reg.isCpu() : "not cpu register"; - break; - } - - case Float: { - assert !target.arch.isX86() || reg.isFpu() : "not xmm register: " + reg; - break; - } - - case Double: { - assert !target.arch.isX86() || reg.isFpu() : "not xmm register: " + reg; - break; - } - - default: { - throw GraalInternalError.shouldNotReachHere(); - } - } - } - return true; - } - static StackSlot canonicalSpillOpr(Interval interval) { assert interval.spillSlot() != null : "canonical spill slot not set"; return interval.spillSlot();
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Fri Nov 09 13:35:26 2012 +0100 @@ -29,7 +29,7 @@ import java.util.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.Register.*; +import com.oracle.graal.api.code.Register.RegisterFlag; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.alloc.Interval.RegisterBinding; import com.oracle.graal.compiler.alloc.Interval.RegisterPriority; @@ -37,7 +37,7 @@ import com.oracle.graal.compiler.alloc.Interval.State; import com.oracle.graal.debug.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.util.*; @@ -46,7 +46,7 @@ */ final class LinearScanWalker extends IntervalWalker { - private final boolean hasCalleeSavedRegisters; + private final boolean callKillsRegisters; private Register[] availableRegs; @@ -71,9 +71,15 @@ return allocator.blockForId(opId); } - LinearScanWalker(LinearScan allocator, Interval unhandledFixedFirst, Interval unhandledAnyFirst, boolean hasCalleeSavedRegisters) { + LinearScanWalker(LinearScan allocator, Interval unhandledFixedFirst, Interval unhandledAnyFirst) { super(allocator, unhandledFixedFirst, unhandledAnyFirst); - this.hasCalleeSavedRegisters = hasCalleeSavedRegisters; + + // If all allocatable registers are caller saved, then no registers are live across a call site. + // The register allocator can save time not trying to find a register at a call site. + HashSet<Register> registers = new HashSet<>(Arrays.asList(allocator.frameMap.registerConfig.getAllocatableRegisters())); + registers.removeAll(Arrays.asList(allocator.frameMap.registerConfig.getCallerSaveRegisters())); + callKillsRegisters = registers.size() == 0; + moveResolver = new MoveResolver(allocator); spillIntervals = Util.uncheckedCast(new List[allocator.registers.length]); for (int i = 0; i < allocator.registers.length; i++) { @@ -676,32 +682,6 @@ return true; } - Register findLockedRegister(int regNeededUntil, int intervalTo, Value ignoreReg, boolean[] needSplit) { - int maxReg = -1; - Register ignore = isRegister(ignoreReg) ? asRegister(ignoreReg) : null; - - for (Register reg : availableRegs) { - int i = reg.number; - if (reg == ignore) { - // this register must be ignored - - } else if (usePos[i] > regNeededUntil) { - if (maxReg == -1 || (usePos[i] > usePos[maxReg])) { - maxReg = i; - } - } - } - - if (maxReg != -1) { - if (blockPos[maxReg] <= intervalTo) { - needSplit[0] = true; - } - return availableRegs[maxReg]; - } - - return null; - } - void splitAndSpillIntersectingIntervals(Register reg) { assert reg != null : "no register assigned"; @@ -797,10 +777,10 @@ boolean noAllocationPossible(Interval interval) { - if (!hasCalleeSavedRegisters) { + if (callKillsRegisters) { // fast calculation of intervals that can never get a register because the // the next instruction is a call that blocks all registers - // Note: this does not work if callee-saved registers are available (e.g. on Sparc) + // Note: this only works if a call kills all registers // check if this interval is the result of a split operation // (an interval got a register until this position) @@ -816,7 +796,6 @@ assert !allocFreeRegister(interval) : "found a register for this interval"; return true; } - } } return false;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Nov 09 13:35:26 2012 +0100 @@ -54,7 +54,7 @@ * This class traverses the HIR instructions and generates LIR instructions from them. */ public abstract class LIRGenerator extends LIRGeneratorTool { - protected final Graph graph; + protected final StructuredGraph graph; protected final CodeCacheProvider runtime; protected final TargetDescription target; protected final ResolvedJavaMethod method; @@ -89,7 +89,7 @@ */ private final ArrayList<StackSlot> lockDataSlots; - public LIRGenerator(Graph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { + public LIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { this.graph = graph; this.runtime = runtime; this.target = target; @@ -448,8 +448,12 @@ return !(location instanceof IndexedLocationNode) && location.displacement() < 4096; } + protected CallingConvention createCallingConvention() { + return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnKind(), MetaUtil.signatureToKinds(method), target, false); + } + protected void emitPrologue() { - CallingConvention incomingArguments = frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnKind(), MetaUtil.signatureToKinds(method), target, false); + CallingConvention incomingArguments = createCallingConvention(); Value[] params = new Value[incomingArguments.getArgumentCount()]; for (int i = 0; i < params.length; i++) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Fri Nov 09 13:35:26 2012 +0100 @@ -25,9 +25,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; /** @@ -51,7 +51,7 @@ return new FrameMap(runtime, target, registerConfig); } - public abstract LIRGenerator newLIRGenerator(Graph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir); + public abstract LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir); public abstract TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir);
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Fri Nov 09 13:35:26 2012 +0100 @@ -189,7 +189,7 @@ } } - public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isTimerEnabled, final Collection<? extends DebugDumpHandler> dumpHandlers, final PrintStream output) { + public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isTimerEnabled, final Collection<DebugDumpHandler> dumpHandlers, final PrintStream output) { return new DebugConfig() { @Override @@ -218,7 +218,7 @@ } @Override - public Collection< ? extends DebugDumpHandler> dumpHandlers() { + public Collection<DebugDumpHandler> dumpHandlers() { return dumpHandlers; }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java Fri Nov 09 13:35:26 2012 +0100 @@ -65,9 +65,18 @@ */ boolean isTimeEnabled(); + /** + * Handles notification of an exception occurring within a debug scope. + * + * @return the exception object that is to be propagated to parent scope. A value of {@code null} indicates that + * {@code e} is to be propagated. + */ RuntimeException interceptException(Throwable e); - Collection<? extends DebugDumpHandler> dumpHandlers(); + /** + * Gets the modifiable collection dump handlers registered with this configuration. + */ + Collection<DebugDumpHandler> dumpHandlers(); PrintStream output(); }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Fri Nov 09 13:35:26 2012 +0100 @@ -126,6 +126,18 @@ } } + /** + * This method exists mainly to allow a debugger (e.g., Eclipse) to force dump a graph. + */ + public static void dump(Object object, String message) { + DebugConfig config = getConfig(); + if (config != null) { + for (DebugDumpHandler dumpHandler : config.dumpHandlers()) { + dumpHandler.dump(object, message); + } + } + } + public <T> T scope(String newName, Runnable runnable, Callable<T> callable, boolean sandbox, Object[] newContext) { DebugScope oldContext = getInstance(); DebugConfig oldConfig = getConfig();
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Fri Nov 09 13:35:26 2012 +0100 @@ -410,11 +410,14 @@ if (canGVN) { number = startGVNNumber; for (int i = 0; i < dataOffsets.length; ++i) { - Class<?> type = dataTypes[i]; + Class< ? > type = dataTypes[i]; if (type.isPrimitive()) { if (type == Integer.TYPE) { int intValue = unsafe.getInt(n, dataOffsets[i]); number += intValue; + } else if (type == Long.TYPE) { + long longValue = unsafe.getLong(n, dataOffsets[i]); + number += longValue ^ (longValue >>> 32); } else if (type == Boolean.TYPE) { boolean booleanValue = unsafe.getBoolean(n, dataOffsets[i]); if (booleanValue) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java Fri Nov 09 13:35:26 2012 +0100 @@ -24,6 +24,7 @@ import static com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind.*; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.CompilationResult.Mark; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Nov 09 13:35:26 2012 +0100 @@ -22,12 +22,13 @@ */ package com.oracle.graal.hotspot.amd64; +import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.CallingConvention.Type.*; import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.asm.amd64.AMD64.*; import java.lang.reflect.*; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; @@ -35,7 +36,6 @@ import com.oracle.graal.asm.amd64.AMD64Assembler.*; import com.oracle.graal.compiler.amd64.*; import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; @@ -58,7 +58,7 @@ } @Override - public LIRGenerator newLIRGenerator(Graph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { + public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { return new HotSpotAMD64LIRGenerator(graph, runtime(), target, frameMap, method, lir); } @@ -68,11 +68,20 @@ return (HotSpotRuntime) runtime; } - private HotSpotAMD64LIRGenerator(Graph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { + private HotSpotAMD64LIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { super(graph, runtime, target, frameMap, method, lir); } @Override + protected CallingConvention createCallingConvention() { + if (graph.getEntryBCI() == StructuredGraph.INVOCATION_ENTRY_BCI) { + return super.createCallingConvention(); + } else { + return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnKind(), new Kind[]{Kind.Long}, target, false); + } + } + + @Override public void visitSafepointNode(SafepointNode i) { LIRFrameState info = state(); append(new AMD64SafepointOp(info, runtime().config)); @@ -245,7 +254,6 @@ Label unverifiedStub = new Label(); // Emit the prefix - tasm.recordMark(Marks.MARK_OSR_ENTRY); boolean isStatic = Modifier.isStatic(method.getModifiers()); if (!isStatic) { @@ -260,6 +268,7 @@ } asm.align(config.codeEntryAlignment); + tasm.recordMark(Marks.MARK_OSR_ENTRY); tasm.recordMark(Marks.MARK_VERIFIED_ENTRY); // Emit code for the LIR
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java Fri Nov 09 13:35:26 2012 +0100 @@ -22,8 +22,8 @@ */ package com.oracle.graal.hotspot.amd64; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Fri Nov 09 13:35:26 2012 +0100 @@ -22,15 +22,15 @@ */ package com.oracle.graal.hotspot.amd64; -import static com.oracle.graal.asm.amd64.AMD64.*; +import static com.oracle.graal.amd64.AMD64.*; import java.util.*; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CallingConvention.*; -import com.oracle.graal.api.code.Register.*; +import com.oracle.graal.api.code.CallingConvention.Type; +import com.oracle.graal.api.code.Register.RegisterFlag; import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.amd64.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Fri Nov 09 13:35:26 2012 +0100 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.amd64; -import static com.oracle.graal.asm.amd64.AMD64.*; +import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.compiler.amd64.AMD64DeoptimizationStub.*; import static com.oracle.graal.compiler.amd64.AMD64LIRGenerator.*; import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Fri Nov 09 13:35:26 2012 +0100 @@ -25,6 +25,7 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java Fri Nov 09 13:35:26 2012 +0100 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.amd64; -import static com.oracle.graal.asm.amd64.AMD64.*; +import static com.oracle.graal.amd64.AMD64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.asm.amd64.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Fri Nov 09 13:35:26 2012 +0100 @@ -42,27 +42,38 @@ } }; + public static final ThreadLocal<Long> withinCompilation = new ThreadLocal<Long>() { + @Override + protected Long initialValue() { + return 0L; + } + }; + private volatile boolean cancelled; private final HotSpotGraalRuntime graalRuntime; private final PhasePlan plan; + private final OptimisticOptimizations optimisticOpts; private final HotSpotResolvedJavaMethod method; - private final OptimisticOptimizations optimisticOpts; + private final int entryBCI; private final int id; private final int priority; + private final Runnable callback; - public static CompilationTask create(HotSpotGraalRuntime graalRuntime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int id, int priority) { - return new CompilationTask(graalRuntime, plan, optimisticOpts, method, id, priority); + public static CompilationTask create(HotSpotGraalRuntime graalRuntime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int entryBCI, int id, int priority, Runnable callback) { + return new CompilationTask(graalRuntime, plan, optimisticOpts, method, entryBCI, id, priority, callback); } - private CompilationTask(HotSpotGraalRuntime graalRuntime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int id, int priority) { + private CompilationTask(HotSpotGraalRuntime graalRuntime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int entryBCI, int id, int priority, Runnable callback) { this.graalRuntime = graalRuntime; this.plan = plan; this.method = method; this.optimisticOpts = optimisticOpts; + this.entryBCI = entryBCI; this.id = id; this.priority = priority; + this.callback = callback; } public ResolvedJavaMethod method() { @@ -90,7 +101,7 @@ } } runCompilation(); - if (method.currentTask() == this) { + if (method.currentTask() == this && entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI) { method.setCurrentTask(null); } } finally { @@ -99,29 +110,31 @@ } public void runCompilation() { + withinCompilation.set(withinCompilation.get() + 1); CompilationStatistics stats = CompilationStatistics.create(method); try { final boolean printCompilation = GraalOptions.PrintCompilation && !TTY.isSuppressed(); if (printCompilation) { - TTY.println(String.format("%-6d Graal %-70s %-45s %-50s ...", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature())); + TTY.println(String.format("%-6d Graal %-70s %-45s %-50s %s...", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature(), entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "(OSR) ")); } CompilationResult result = null; TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method); + long start = System.currentTimeMillis(); try { result = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true), new Callable<CompilationResult>() { @Override public CompilationResult call() throws Exception { graalRuntime.evictDeoptedGraphs(); - StructuredGraph graph = new StructuredGraph(method); - return graalRuntime.getCompiler().compileMethod(method, graph, -1, graalRuntime.getCache(), plan, optimisticOpts); + StructuredGraph graph = new StructuredGraph(method, entryBCI); + return graalRuntime.getCompiler().compileMethod(method, graph, graalRuntime.getCache(), plan, optimisticOpts); } }); } finally { filter.remove(); if (printCompilation) { - TTY.println(String.format("%-6d Graal %-70s %-45s %-50s | %4dnodes %5dB", id, "", "", "", 0, (result != null ? result.getTargetCodeSize() : -1))); + TTY.println(String.format("%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, (result != null ? result.getTargetCodeSize() : -1))); } } @@ -143,6 +156,10 @@ } } stats.finish(method); + if (callback != null) { + callback.run(); + } + withinCompilation.set(withinCompilation.get() - 1); } private void installMethod(final CompilationResult tm) { @@ -150,7 +167,7 @@ @Override public void run() { final CodeInfo[] info = Debug.isDumpEnabled() ? new CodeInfo[1] : null; - graalRuntime.getRuntime().installMethod(method, tm, info); + graalRuntime.getRuntime().installMethod(method, entryBCI, tm, info); if (info != null) { Debug.dump(new Object[] {tm, info[0]}, "After code installation"); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java Fri Nov 09 13:35:26 2012 +0100 @@ -36,14 +36,16 @@ private static final long serialVersionUID = 7807321392203253218L; public final CompilationResult comp; public final HotSpotResolvedJavaMethod method; // used only for methods + public final int entryBCI; // used only for methods public final String name; // used only for stubs public final Site[] sites; public final ExceptionHandler[] exceptionHandlers; - public HotSpotCompilationResult(HotSpotResolvedJavaMethod method, CompilationResult comp) { + public HotSpotCompilationResult(HotSpotResolvedJavaMethod method, int entryBCI, CompilationResult comp) { this.method = method; this.comp = comp; + this.entryBCI = entryBCI; this.name = null; sites = getSortedSites(comp); @@ -54,6 +56,15 @@ } } + static class SiteComparator implements Comparator<Site> { + public int compare(Site s1, Site s2) { + if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) { + return s1 instanceof Mark ? -1 : 1; + } + return s1.pcOffset - s2.pcOffset; + } + } + private static Site[] getSortedSites(CompilationResult target) { List<?>[] lists = new List<?>[] {target.getSafepoints(), target.getDataReferences(), target.getMarks()}; int count = 0; @@ -67,15 +78,7 @@ result[pos++] = (Site) elem; } } - Arrays.sort(result, new Comparator<Site>() { - - public int compare(Site s1, Site s2) { - if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) { - return s1 instanceof Mark ? -1 : 1; - } - return s1.pcOffset - s2.pcOffset; - } - }); + Arrays.sort(result, new SiteComparator()); return result; } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java Fri Nov 09 13:35:26 2012 +0100 @@ -177,7 +177,7 @@ } @Override - public Collection<? extends DebugDumpHandler> dumpHandlers() { + public Collection<DebugDumpHandler> dumpHandlers() { return dumpHandlers; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Fri Nov 09 13:35:26 2012 +0100 @@ -159,10 +159,10 @@ return vmToCompiler; } - public JavaType lookupType(String returnType, HotSpotResolvedJavaType accessingClass, boolean eagerResolve) { - if (returnType.length() == 1 && vmToCompiler instanceof VMToCompilerImpl) { + public JavaType lookupType(String name, HotSpotResolvedJavaType accessingClass, boolean eagerResolve) { + if (name.length() == 1 && vmToCompiler instanceof VMToCompilerImpl) { VMToCompilerImpl exitsNative = (VMToCompilerImpl) vmToCompiler; - Kind kind = Kind.fromPrimitiveOrVoidTypeChar(returnType.charAt(0)); + Kind kind = Kind.fromPrimitiveOrVoidTypeChar(name.charAt(0)); switch(kind) { case Boolean: return exitsNative.typeBoolean; @@ -190,7 +190,7 @@ return exitsNative.typeVoid; } } - return compilerToVm.Signature_lookupType(returnType, accessingClass, eagerResolve); + return compilerToVm.lookupType(name, accessingClass, eagerResolve); } public HotSpotRuntimeInterpreterInterface getRuntimeInterpreterInterface() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Nov 09 13:35:26 2012 +0100 @@ -179,6 +179,7 @@ public long vmErrorStub; public long deoptimizeStub; public long unwindExceptionStub; + public long osrMigrationEndStub; public long registerFinalizerStub; public long setDeoptInfoStub; public long createNullPointerExceptionStub;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Nov 09 13:35:26 2012 +0100 @@ -34,59 +34,57 @@ */ public interface CompilerToVM { - // Checkstyle: stop + byte[] getBytecode(HotSpotResolvedJavaMethod method); - byte[] JavaMethod_code(HotSpotResolvedJavaMethod method); + String getSignature(HotSpotResolvedJavaMethod method); - String JavaMethod_signature(HotSpotResolvedJavaMethod method); + ExceptionHandler[] getExceptionHandlers(HotSpotResolvedJavaMethod method); - ExceptionHandler[] JavaMethod_exceptionHandlers(HotSpotResolvedJavaMethod method); - - boolean JavaMethod_hasBalancedMonitors(HotSpotResolvedJavaMethod method); + boolean hasBalancedMonitors(HotSpotResolvedJavaMethod method); - JavaMethod JavaMethod_uniqueConcreteMethod(HotSpotResolvedJavaMethod method); + JavaMethod getUniqueConcreteMethod(HotSpotResolvedJavaMethod method); - int JavaMethod_invocationCount(HotSpotResolvedJavaMethod method); + int getInvocationCount(HotSpotResolvedJavaMethod method); - HotSpotMethodData JavaMethod_methodData(HotSpotResolvedJavaMethod method); + HotSpotMethodData getMethodData(HotSpotResolvedJavaMethod method); - JavaType Signature_lookupType(String returnType, HotSpotResolvedJavaType accessingClass, boolean eagerResolve); + JavaType lookupType(String name, HotSpotResolvedJavaType accessingClass, boolean eagerResolve); - Object ConstantPool_lookupConstant(HotSpotResolvedJavaType pool, int cpi); + Object lookupConstantInPool(HotSpotResolvedJavaType pool, int cpi); - JavaMethod ConstantPool_lookupMethod(HotSpotResolvedJavaType pool, int cpi, byte byteCode); + JavaMethod lookupMethodInPool(HotSpotResolvedJavaType pool, int cpi, byte opcode); - JavaType ConstantPool_lookupType(HotSpotResolvedJavaType pool, int cpi); + JavaType lookupTypeInPool(HotSpotResolvedJavaType pool, int cpi); - JavaField ConstantPool_lookupField(HotSpotResolvedJavaType pool, int cpi, byte byteCode); + JavaField lookupFieldInPool(HotSpotResolvedJavaType pool, int cpi, byte opcode); - void ConstantPool_loadReferencedType(HotSpotResolvedJavaType pool, int cpi, byte byteCode); + void lookupReferencedTypeInPool(HotSpotResolvedJavaType pool, int cpi, byte opcode); HotSpotCompiledMethod installMethod(HotSpotCompilationResult compResult, boolean makeDefault, HotSpotCodeInfo info); void initializeConfiguration(HotSpotVMConfig config); - JavaMethod JavaType_resolveMethodImpl(HotSpotResolvedJavaType klass, String name, String signature); + JavaMethod resolveMethod(HotSpotResolvedJavaType klass, String name, String signature); - boolean JavaType_isSubtypeOf(HotSpotResolvedJavaType klass, JavaType other); + boolean isSubtypeOf(HotSpotResolvedJavaType klass, JavaType other); - JavaType JavaType_leastCommonAncestor(HotSpotResolvedJavaType thisType, HotSpotResolvedJavaType otherType); + JavaType getLeastCommonAncestor(HotSpotResolvedJavaType thisType, HotSpotResolvedJavaType otherType); JavaType getPrimitiveArrayType(Kind kind); - JavaType JavaType_arrayOf(HotSpotResolvedJavaType klass); + JavaType getArrayOf(HotSpotResolvedJavaType klass); - JavaType JavaType_componentType(HotSpotResolvedJavaType klass); + JavaType getComponentType(HotSpotResolvedJavaType klass); - boolean JavaType_isInitialized(HotSpotResolvedJavaType klass); + boolean isTypeInitialized(HotSpotResolvedJavaType klass); - void JavaType_initialize(HotSpotResolvedJavaType klass); + void initializeType(HotSpotResolvedJavaType klass); JavaType getType(Class<?> javaClass); - JavaType JavaType_uniqueConcreteSubtype(HotSpotResolvedJavaType klass); + JavaType getUniqueConcreteSubtype(HotSpotResolvedJavaType klass); - JavaType JavaType_superType(HotSpotResolvedJavaType klass); + JavaType getSuperType(HotSpotResolvedJavaType klass); int getArrayLength(Constant array); @@ -94,11 +92,9 @@ JavaType getJavaType(Constant constant); - ResolvedJavaField[] JavaType_fields(HotSpotResolvedJavaType klass); + ResolvedJavaField[] getFields(HotSpotResolvedJavaType klass); - boolean JavaMethod_hasCompiledCode(HotSpotResolvedJavaMethod method); - - int JavaMethod_getCompiledCodeSize(HotSpotResolvedJavaMethod method); + int getCompiledCodeSize(HotSpotResolvedJavaMethod method); JavaMethod getJavaMethod(Method reflectionMethod); @@ -108,19 +104,17 @@ String disassembleNative(byte[] code, long address); - StackTraceElement JavaMethod_toStackTraceElement(HotSpotResolvedJavaMethod method, int bci); + StackTraceElement getStackTraceElement(HotSpotResolvedJavaMethod method, int bci); Object executeCompiledMethod(HotSpotCompiledMethod method, Object arg1, Object arg2, Object arg3); Object executeCompiledMethodVarargs(HotSpotCompiledMethod method, Object... args); - int JavaMethod_vtableEntryOffset(HotSpotResolvedJavaMethod method); + int getVtableEntryOffset(HotSpotResolvedJavaMethod method); long[] getDeoptedLeafGraphIds(); String decodePC(long pc); - long JavaType_prototypeMarkWord(HotSpotResolvedJavaType hotSpotResolvedJavaType); - - // Checkstyle: resume + long getPrototypeMarkWord(HotSpotResolvedJavaType hotSpotResolvedJavaType); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri Nov 09 13:35:26 2012 +0100 @@ -34,8 +34,6 @@ */ public class CompilerToVMImpl implements CompilerToVM { - // Checkstyle: stop - @Override public native JavaMethod getJavaMethod(Method reflectionMethod); @@ -43,40 +41,40 @@ public native ResolvedJavaField getJavaField(Field reflectionMethod); @Override - public native byte[] JavaMethod_code(HotSpotResolvedJavaMethod method); + public native byte[] getBytecode(HotSpotResolvedJavaMethod method); @Override - public native String JavaMethod_signature(HotSpotResolvedJavaMethod method); + public native String getSignature(HotSpotResolvedJavaMethod method); @Override - public native ExceptionHandler[] JavaMethod_exceptionHandlers(HotSpotResolvedJavaMethod method); + public native ExceptionHandler[] getExceptionHandlers(HotSpotResolvedJavaMethod method); @Override - public native boolean JavaMethod_hasBalancedMonitors(HotSpotResolvedJavaMethod method); + public native boolean hasBalancedMonitors(HotSpotResolvedJavaMethod method); @Override - public native JavaMethod JavaMethod_uniqueConcreteMethod(HotSpotResolvedJavaMethod method); + public native JavaMethod getUniqueConcreteMethod(HotSpotResolvedJavaMethod method); @Override - public native int JavaMethod_invocationCount(HotSpotResolvedJavaMethod method); + public native int getInvocationCount(HotSpotResolvedJavaMethod method); @Override - public native JavaType Signature_lookupType(String returnType, HotSpotResolvedJavaType accessingClass, boolean eagerResolve); + public native JavaType lookupType(String name, HotSpotResolvedJavaType accessingClass, boolean eagerResolve); @Override - public native Object ConstantPool_lookupConstant(HotSpotResolvedJavaType pool, int cpi); + public native Object lookupConstantInPool(HotSpotResolvedJavaType pool, int cpi); @Override - public native JavaMethod ConstantPool_lookupMethod(HotSpotResolvedJavaType pool, int cpi, byte byteCode); + public native JavaMethod lookupMethodInPool(HotSpotResolvedJavaType pool, int cpi, byte opcode); @Override - public native JavaType ConstantPool_lookupType(HotSpotResolvedJavaType pool, int cpi); + public native JavaType lookupTypeInPool(HotSpotResolvedJavaType pool, int cpi); @Override - public native void ConstantPool_loadReferencedType(HotSpotResolvedJavaType pool, int cpi, byte byteCode); + public native void lookupReferencedTypeInPool(HotSpotResolvedJavaType pool, int cpi, byte opcode); @Override - public native JavaField ConstantPool_lookupField(HotSpotResolvedJavaType pool, int cpi, byte byteCode); + public native JavaField lookupFieldInPool(HotSpotResolvedJavaType pool, int cpi, byte opcode); @Override public native HotSpotCompiledMethod installMethod(HotSpotCompilationResult comp, boolean makeDefault, HotSpotCodeInfo info); @@ -85,37 +83,37 @@ public native void initializeConfiguration(HotSpotVMConfig config); @Override - public native JavaMethod JavaType_resolveMethodImpl(HotSpotResolvedJavaType klass, String name, String signature); + public native JavaMethod resolveMethod(HotSpotResolvedJavaType klass, String name, String signature); @Override - public native boolean JavaType_isSubtypeOf(HotSpotResolvedJavaType klass, JavaType other); + public native boolean isSubtypeOf(HotSpotResolvedJavaType klass, JavaType other); @Override - public native JavaType JavaType_leastCommonAncestor(HotSpotResolvedJavaType thisType, HotSpotResolvedJavaType otherType); + public native JavaType getLeastCommonAncestor(HotSpotResolvedJavaType thisType, HotSpotResolvedJavaType otherType); @Override public native JavaType getPrimitiveArrayType(Kind kind); @Override - public native JavaType JavaType_arrayOf(HotSpotResolvedJavaType klass); + public native JavaType getArrayOf(HotSpotResolvedJavaType klass); @Override - public native JavaType JavaType_componentType(HotSpotResolvedJavaType klass); + public native JavaType getComponentType(HotSpotResolvedJavaType klass); @Override - public native JavaType JavaType_uniqueConcreteSubtype(HotSpotResolvedJavaType klass); + public native JavaType getUniqueConcreteSubtype(HotSpotResolvedJavaType klass); @Override - public native JavaType JavaType_superType(HotSpotResolvedJavaType klass); + public native JavaType getSuperType(HotSpotResolvedJavaType klass); @Override - public native boolean JavaType_isInitialized(HotSpotResolvedJavaType klass); + public native boolean isTypeInitialized(HotSpotResolvedJavaType klass); @Override - public native void JavaType_initialize(HotSpotResolvedJavaType klass); + public native void initializeType(HotSpotResolvedJavaType klass); @Override - public native HotSpotMethodData JavaMethod_methodData(HotSpotResolvedJavaMethod method); + public native HotSpotMethodData getMethodData(HotSpotResolvedJavaMethod method); @Override public native JavaType getType(Class<?> javaClass); @@ -140,13 +138,10 @@ } @Override - public native ResolvedJavaField[] JavaType_fields(HotSpotResolvedJavaType klass); + public native ResolvedJavaField[] getFields(HotSpotResolvedJavaType klass); @Override - public native boolean JavaMethod_hasCompiledCode(HotSpotResolvedJavaMethod method); - - @Override - public native int JavaMethod_getCompiledCodeSize(HotSpotResolvedJavaMethod method); + public native int getCompiledCodeSize(HotSpotResolvedJavaMethod method); @Override public native long getMaxCallTargetOffset(long stub); @@ -155,7 +150,7 @@ public native String disassembleNative(byte[] code, long address); @Override - public native StackTraceElement JavaMethod_toStackTraceElement(HotSpotResolvedJavaMethod method, int bci); + public native StackTraceElement getStackTraceElement(HotSpotResolvedJavaMethod method, int bci); @Override public native Object executeCompiledMethod(HotSpotCompiledMethod method, Object arg1, Object arg2, Object arg3); @@ -164,7 +159,7 @@ public native Object executeCompiledMethodVarargs(HotSpotCompiledMethod method, Object... args); @Override - public native int JavaMethod_vtableEntryOffset(HotSpotResolvedJavaMethod method); + public native int getVtableEntryOffset(HotSpotResolvedJavaMethod method); @Override public native long[] getDeoptedLeafGraphIds(); @@ -173,7 +168,5 @@ public native String decodePC(long pc); @Override - public native long JavaType_prototypeMarkWord(HotSpotResolvedJavaType type); - - // Checkstyle: resume + public native long getPrototypeMarkWord(HotSpotResolvedJavaType type); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java Fri Nov 09 13:35:26 2012 +0100 @@ -27,7 +27,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.phases.*; /** * Calls from HotSpot into Java. @@ -61,6 +60,4 @@ Constant createConstantDouble(double value); Constant createConstantObject(Object object); - - PhasePlan createPhasePlan(OptimisticOptimizations optimisticOpts); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Fri Nov 09 13:35:26 2012 +0100 @@ -35,10 +35,12 @@ import com.oracle.graal.debug.internal.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.hotspot.snippets.*; import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.*; +import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.snippets.*; /** @@ -223,7 +225,7 @@ private void enqueue(Method m) throws Throwable { JavaMethod javaMethod = graalRuntime.getRuntime().lookupJavaMethod(m); assert !Modifier.isAbstract(((HotSpotResolvedJavaMethod) javaMethod).getModifiers()) && !Modifier.isNative(((HotSpotResolvedJavaMethod) javaMethod).getModifiers()) : javaMethod; - compileMethod((HotSpotResolvedJavaMethod) javaMethod, 0, false, 10); + compileMethod((HotSpotResolvedJavaMethod) javaMethod, StructuredGraph.INVOCATION_ENTRY_BCI, false, 10); } private static void shutdownCompileQueue(ThreadPoolExecutor queue) throws InterruptedException { @@ -370,7 +372,7 @@ final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(method); int id = compileTaskIds.incrementAndGet(); - CompilationTask task = CompilationTask.create(graalRuntime, createPhasePlan(optimisticOpts), optimisticOpts, method, id, priority); + CompilationTask task = CompilationTask.create(graalRuntime, createPhasePlan(optimisticOpts, false), optimisticOpts, method, StructuredGraph.INVOCATION_ENTRY_BCI, id, priority, null); if (blocking) { task.runCompilation(); } else { @@ -386,6 +388,21 @@ return false; } } + if (entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI && CompilationTask.withinCompilation.get() == 0) { + final OptimisticOptimizations osrOptimisticOpts = new OptimisticOptimizations(method); + int osrId = compileTaskIds.incrementAndGet(); + Debug.log("OSR compilation %s@%d", method, entryBCI); + final CountDownLatch latch = new CountDownLatch(1); + Runnable callback = new Runnable() { + @Override + public void run() { + latch.countDown(); + } + }; + CompilationTask osrTask = CompilationTask.create(graalRuntime, createPhasePlan(osrOptimisticOpts, true), osrOptimisticOpts, method, entryBCI, osrId, Integer.MAX_VALUE, callback); + compileQueue.execute(osrTask); + latch.await(); + } return true; } finally { CompilationTask.withinEnqueue.set(Boolean.FALSE); @@ -476,11 +493,12 @@ return Constant.forObject(object); } - - public PhasePlan createPhasePlan(OptimisticOptimizations optimisticOpts) { + public PhasePlan createPhasePlan(OptimisticOptimizations optimisticOpts, boolean onStackReplacement) { PhasePlan phasePlan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(graalRuntime.getRuntime(), GraphBuilderConfiguration.getDefault(), optimisticOpts); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(graalRuntime.getRuntime(), GraphBuilderConfiguration.getDefault(), optimisticOpts)); + if (onStackReplacement) { + phasePlan.addPhase(PhasePosition.AFTER_PARSING, new OnStackReplacementPhase()); + } if (GraalOptions.Intrinsify) { phasePlan.addPhase(PhasePosition.HIGH_LEVEL, intrinsifyArrayCopy); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java Fri Nov 09 13:35:26 2012 +0100 @@ -40,7 +40,7 @@ @Override public Object lookupConstant(int cpi) { - Object constant = HotSpotGraalRuntime.getInstance().getCompilerToVM().ConstantPool_lookupConstant(type, cpi); + Object constant = HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupConstantInPool(type, cpi); return constant; } @@ -50,22 +50,22 @@ } @Override - public JavaMethod lookupMethod(int cpi, int byteCode) { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().ConstantPool_lookupMethod(type, cpi, (byte) byteCode); + public JavaMethod lookupMethod(int cpi, int opcode) { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupMethodInPool(type, cpi, (byte) opcode); } @Override public JavaType lookupType(int cpi, int opcode) { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().ConstantPool_lookupType(type, cpi); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupTypeInPool(type, cpi); } @Override public JavaField lookupField(int cpi, int opcode) { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().ConstantPool_lookupField(type, cpi, (byte) opcode); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupFieldInPool(type, cpi, (byte) opcode); } @Override - public void loadReferencedType(int cpi, int bytecode) { - HotSpotGraalRuntime.getInstance().getCompilerToVM().ConstantPool_loadReferencedType(type, cpi, (byte) bytecode); + public void loadReferencedType(int cpi, int opcode) { + HotSpotGraalRuntime.getInstance().getCompilerToVM().lookupReferencedTypeInPool(type, cpi, (byte) opcode); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Fri Nov 09 13:35:26 2012 +0100 @@ -83,7 +83,7 @@ @Override public byte[] getCode() { if (code == null) { - code = HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaMethod_code(this); + code = HotSpotGraalRuntime.getInstance().getCompilerToVM().getBytecode(this); assert code.length == codeSize : "expected: " + codeSize + ", actual: " + code.length; } return code; @@ -96,12 +96,12 @@ @Override public ExceptionHandler[] getExceptionHandlers() { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaMethod_exceptionHandlers(this); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().getExceptionHandlers(this); } public boolean hasBalancedMonitors() { if (hasBalancedMonitors == null) { - hasBalancedMonitors = HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaMethod_hasBalancedMonitors(this); + hasBalancedMonitors = HotSpotGraalRuntime.getInstance().getCompilerToVM().hasBalancedMonitors(this); } return hasBalancedMonitors; } @@ -130,20 +130,20 @@ public StackTraceElement asStackTraceElement(int bci) { if (bci < 0 || bci >= codeSize) { // HotSpot code can only construct stack trace elements for valid bcis - StackTraceElement ste = HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaMethod_toStackTraceElement(this, 0); + StackTraceElement ste = HotSpotGraalRuntime.getInstance().getCompilerToVM().getStackTraceElement(this, 0); return new StackTraceElement(ste.getClassName(), ste.getMethodName(), ste.getFileName(), -1); } - return HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaMethod_toStackTraceElement(this, bci); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().getStackTraceElement(this, bci); } public ResolvedJavaMethod uniqueConcreteMethod() { - return (ResolvedJavaMethod) HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaMethod_uniqueConcreteMethod(this); + return (ResolvedJavaMethod) HotSpotGraalRuntime.getInstance().getCompilerToVM().getUniqueConcreteMethod(this); } @Override public Signature getSignature() { if (signature == null) { - signature = new HotSpotSignature(HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaMethod_signature(this)); + signature = new HotSpotSignature(HotSpotGraalRuntime.getInstance().getCompilerToVM().getSignature(this)); } return signature; } @@ -153,16 +153,12 @@ return "HotSpotMethod<" + MetaUtil.format("%h.%n", this) + ">"; } - public boolean hasCompiledCode() { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaMethod_hasCompiledCode(this); - } - public int getCompiledCodeSize() { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaMethod_getCompiledCodeSize(this); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().getCompiledCodeSize(this); } public int invocationCount() { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaMethod_invocationCount(this); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().getInvocationCount(this); } @Override @@ -186,7 +182,7 @@ ProfilingInfo info; if (GraalOptions.UseProfilingInformation && methodData == null) { - methodData = HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaMethod_methodData(this); + methodData = HotSpotGraalRuntime.getInstance().getCompilerToVM().getMethodData(this); } if (methodData == null || (!methodData.hasNormalData() && !methodData.hasExtraData())) { @@ -271,7 +267,7 @@ if (!holder.isInitialized()) { return -1; } - return HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaMethod_vtableEntryOffset(this); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().getVtableEntryOffset(this); } public void setCurrentTask(CompilationTask task) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Fri Nov 09 13:35:26 2012 +0100 @@ -67,7 +67,7 @@ @Override public ResolvedJavaType getArrayClass() { if (arrayOfType == null) { - arrayOfType = (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaType_arrayOf(this); + arrayOfType = (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().getArrayOf(this); } return arrayOfType; } @@ -75,7 +75,7 @@ @Override public ResolvedJavaType getComponentType() { if (isArrayClass) { - return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaType_componentType(this); + return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().getComponentType(this); } return null; } @@ -85,7 +85,7 @@ if (isArrayClass()) { return Modifier.isFinal(getComponentType().getModifiers()) ? this : null; } else { - ResolvedJavaType subtype = (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaType_uniqueConcreteSubtype(this); + ResolvedJavaType subtype = (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().getUniqueConcreteSubtype(this); assert subtype == null || !subtype.isInterface(); return subtype; } @@ -94,7 +94,7 @@ @Override public ResolvedJavaType getSuperclass() { if (!superTypeSet) { - superType = (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaType_superType(this); + superType = (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().getSuperType(this); superTypeSet = true; } return superType; @@ -105,7 +105,7 @@ if (otherType instanceof HotSpotTypePrimitive) { return null; } else { - return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaType_leastCommonAncestor(this, (HotSpotResolvedJavaType) otherType); + return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().getLeastCommonAncestor(this, (HotSpotResolvedJavaType) otherType); } } @@ -151,15 +151,15 @@ @Override public boolean isInitialized() { if (!isInitialized) { - isInitialized = HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaType_isInitialized(this); + isInitialized = HotSpotGraalRuntime.getInstance().getCompilerToVM().isTypeInitialized(this); } return isInitialized; } @Override public void initialize() { - if (!HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaType_isInitialized(this)) { - HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaType_initialize(this); + if (!isInitialized) { + HotSpotGraalRuntime.getInstance().getCompilerToVM().initializeType(this); } isInitialized = true; } @@ -182,7 +182,7 @@ @Override public boolean isSubtypeOf(ResolvedJavaType other) { if (other instanceof HotSpotResolvedJavaType) { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaType_isSubtypeOf(this, other); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().isSubtypeOf(this, other); } // No resolved type is a subtype of an unresolved type. return false; @@ -196,7 +196,7 @@ @Override public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method) { assert method instanceof HotSpotMethod; - return (ResolvedJavaMethod) HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaType_resolveMethodImpl(this, method.getName(), ((HotSpotSignature) method.getSignature()).asString()); + return (ResolvedJavaMethod) HotSpotGraalRuntime.getInstance().getCompilerToVM().resolveMethod(this, method.getName(), ((HotSpotSignature) method.getSignature()).asString()); } @Override @@ -254,7 +254,7 @@ if (isArrayClass) { fields = new ResolvedJavaField[0]; } else { - fields = HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaType_fields(this); + fields = HotSpotGraalRuntime.getInstance().getCompilerToVM().getFields(this); } } return fields; @@ -295,6 +295,6 @@ } public long prototypeMarkWord() { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().JavaType_prototypeMarkWord(this); + return HotSpotGraalRuntime.getInstance().getCompilerToVM().getPrototypeMarkWord(this); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Nov 09 13:35:26 2012 +0100 @@ -43,11 +43,11 @@ import com.oracle.graal.api.code.Register.RegisterFlag; import com.oracle.graal.api.code.RuntimeCall.Descriptor; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.ResolvedJavaType.Representation; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.hotspot.snippets.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -105,6 +105,11 @@ /* ret */ ret(Kind.Void), /* arg0: exception */ arg(0, Kind.Object)); + addRuntimeCall(OnStackReplacementPhase.OSR_MIGRATION_END, config.osrMigrationEndStub, + /* temps */ null, + /* ret */ ret(Kind.Void), + /* arg0: long */ arg(0, Kind.Long)); + addRuntimeCall(REGISTER_FINALIZER, config.registerFinalizerStub, /* temps */ null, /* ret */ ret(Kind.Void), @@ -228,7 +233,7 @@ public String disassemble(CodeInfo info, CompilationResult tm) { byte[] code = info.getCode(); TargetDescription target = graalRuntime.getTarget(); - HexCodeFile hcf = new HexCodeFile(code, info.getStart(), target.arch.name, target.wordSize * 8); + HexCodeFile hcf = new HexCodeFile(code, info.getStart(), target.arch.getName(), target.wordSize * 8); if (tm != null) { HexCodeFile.addAnnotations(hcf, tm.getAnnotations()); addExceptionHandlersComment(tm, hcf); @@ -381,21 +386,22 @@ HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); if (!hsMethod.getDeclaringClass().isInterface()) { - // We use LocationNode.ANY_LOCATION for the reads that access the vtable entry and the compiled code entry - // as HotSpot does not guarantee they are final values. int vtableEntryOffset = hsMethod.vtableEntryOffset(); - assert vtableEntryOffset > 0; - LoadHubNode hub = graph.add(new LoadHubNode(receiver)); - Kind wordKind = graalRuntime.getTarget().wordKind; - Stamp nonNullWordStamp = StampFactory.forWord(wordKind, true); - ReadNode methodOop = graph.add(new ReadNode(hub, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, vtableEntryOffset, graph), nonNullWordStamp)); - ReadNode compiledEntry = graph.add(new ReadNode(methodOop, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), nonNullWordStamp)); + if (vtableEntryOffset > 0) { + // We use LocationNode.ANY_LOCATION for the reads that access the vtable entry and the compiled code entry + // as HotSpot does not guarantee they are final values. + LoadHubNode hub = graph.add(new LoadHubNode(receiver)); + Kind wordKind = graalRuntime.getTarget().wordKind; + Stamp nonNullWordStamp = StampFactory.forWord(wordKind, true); + ReadNode methodOop = graph.add(new ReadNode(hub, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, vtableEntryOffset, graph), nonNullWordStamp)); + ReadNode compiledEntry = graph.add(new ReadNode(methodOop, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), nonNullWordStamp)); - loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(methodOop, compiledEntry, parameters, invoke.node().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall)); + loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(methodOop, compiledEntry, parameters, invoke.node().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall)); - graph.addBeforeFixed(invoke.node(), hub); - graph.addAfterFixed(hub, methodOop); - graph.addAfterFixed(methodOop, compiledEntry); + graph.addBeforeFixed(invoke.node(), hub); + graph.addAfterFixed(hub, methodOop); + graph.addAfterFixed(methodOop, compiledEntry); + } } } @@ -470,7 +476,6 @@ Kind elementKind = storeIndexed.elementKind(); LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index()); ValueNode value = storeIndexed.value(); - CheckCastNode checkcast = null; ValueNode array = storeIndexed.array(); if (elementKind == Kind.Object && !value.objectStamp().alwaysNull()) { // Store check! @@ -478,8 +483,7 @@ if (arrayType != null && array.objectStamp().isExactType()) { ResolvedJavaType elementType = arrayType.getComponentType(); if (elementType.getSuperclass() != null) { - ConstantNode type = ConstantNode.forConstant(elementType.getEncoding(Representation.ObjectHub), this, graph); - checkcast = graph.add(new CheckCastNode(type, elementType, value)); + CheckCastNode checkcast = graph.add(new CheckCastNode(elementType, value, null)); graph.addBeforeFixed(storeIndexed, checkcast); value = checkcast; } else { @@ -488,7 +492,7 @@ } else { LoadHubNode arrayClass = graph.add(new LoadHubNode(array)); FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Object, config.arrayClassElementOffset, graph), null, StampFactory.objectNonNull())); - checkcast = graph.add(new CheckCastNode(arrayElementKlass, null, value)); + CheckCastDynamicNode checkcast = graph.add(new CheckCastDynamicNode(arrayElementKlass, value)); graph.addBeforeFixed(storeIndexed, checkcast); graph.addBeforeFixed(checkcast, arrayClass); value = checkcast; @@ -541,6 +545,8 @@ graph.replaceFixed(loadHub, hub); } else if (n instanceof CheckCastNode) { checkcastSnippets.lower((CheckCastNode) n, tool); + } else if (n instanceof CheckCastDynamicNode) { + checkcastSnippets.lower((CheckCastDynamicNode) n); } else if (n instanceof InstanceOfNode) { instanceofSnippets.lower((InstanceOfNode) n, tool); } else if (n instanceof NewInstanceNode) { @@ -668,15 +674,15 @@ return hsInfo; } - public void installMethod(ResolvedJavaMethod method, CompilationResult compResult, CodeInfo[] info) { + public void installMethod(ResolvedJavaMethod method, int entryBCI, CompilationResult compResult, CodeInfo[] info) { HotSpotCodeInfo hsInfo = makeInfo(method, compResult, info); - graalRuntime.getCompilerToVM().installMethod(new HotSpotCompilationResult((HotSpotResolvedJavaMethod) method, compResult), true, hsInfo); + graalRuntime.getCompilerToVM().installMethod(new HotSpotCompilationResult((HotSpotResolvedJavaMethod) method, entryBCI, compResult), true, hsInfo); } @Override public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, CodeInfo[] info) { HotSpotCodeInfo hsInfo = makeInfo(method, compResult, info); - return graalRuntime.getCompilerToVM().installMethod(new HotSpotCompilationResult((HotSpotResolvedJavaMethod) method, compResult), false, hsInfo); + return graalRuntime.getCompilerToVM().installMethod(new HotSpotCompilationResult((HotSpotResolvedJavaMethod) method, -1, compResult), false, hsInfo); } @Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.phases; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCall.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.loop.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; + +public class OnStackReplacementPhase extends Phase { + + public static final Descriptor OSR_MIGRATION_END = new Descriptor("OSR_migration_end", true, Kind.Void, Kind.Long); + + @Override + protected void run(StructuredGraph graph) { + if (graph.getEntryBCI() == StructuredGraph.INVOCATION_ENTRY_BCI) { + // This happens during inlining in a OSR method, because the same phase plan will be used. + return; + } + Debug.dump(graph, "OnStackReplacement initial"); + EntryMarkerNode osr; + do { + NodeIterable<EntryMarkerNode> osrNodes = graph.getNodes(EntryMarkerNode.class); + osr = osrNodes.first(); + if (osr == null) { + throw new BailoutException("no OnStackReplacementNode generated"); + } + if (osrNodes.count() > 1) { + throw new GraalInternalError("multiple OnStackReplacementNodes generated"); + } + if (osr.stateAfter().locksSize() != 0) { + throw new BailoutException("osr with locks not supported"); + } + if (osr.stateAfter().stackSize() != 0) { + throw new GraalInternalError("osr with stack entries not supported"); + } + LoopEx osrLoop = null; + LoopsData loops = new LoopsData(graph); + for (LoopEx loop : loops.loops()) { + if (loop.inside().contains(osr)) { + osrLoop = loop; + break; + } + } + if (osrLoop == null) { + break; + } + + LoopTransformations.peel(osrLoop); + for (Node usage : osr.usages().snapshot()) { + ValueProxyNode proxy = (ValueProxyNode) usage; + proxy.replaceAndDelete(proxy.value()); + } + FixedNode next = osr.next(); + osr.setNext(null); + ((FixedWithNextNode) osr.predecessor()).setNext(next); + GraphUtil.killWithUnusedFloatingInputs(osr); + Debug.dump(graph, "OnStackReplacement loop peeling result"); + } while (true); + + + LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(Kind.Long))); + RuntimeCallNode migrationEnd = graph.add(new RuntimeCallNode(OSR_MIGRATION_END, buffer)); + FrameState osrState = osr.stateAfter(); + migrationEnd.setStateAfter(osrState); + osr.setStateAfter(null); + + StartNode start = graph.start(); + FixedNode rest = start.next(); + start.setNext(migrationEnd); + FixedNode next = osr.next(); + osr.setNext(null); + migrationEnd.setNext(next); + + FrameState oldStartState = start.stateAfter(); + start.setStateAfter(null); + GraphUtil.killWithUnusedFloatingInputs(oldStartState); + + int localsOffset = (graph.method().getMaxLocals() - 1) * 8; + for (int i = 0; i < osrState.localsSize(); i++) { + ValueNode value = osrState.localAt(i); + if (value != null) { + ValueProxyNode proxy = (ValueProxyNode) value; + int size = (value.kind() == Kind.Long || value.kind() == Kind.Double) ? 2 : 1; + int offset = localsOffset - (i + size - 1) * 8; + UnsafeLoadNode load = graph.add(new UnsafeLoadNode(buffer, offset, ConstantNode.forInt(0, graph), value.kind())); + proxy.replaceAndDelete(load); + graph.addBeforeFixed(migrationEnd, load); + } + } + + GraphUtil.killCFG(rest); + + Debug.dump(graph, "OnStackReplacement result"); + new DeadCodeEliminationPhase().apply(graph); + } +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Fri Nov 09 13:35:26 2012 +0100 @@ -134,25 +134,15 @@ * in an object array store check). */ @Snippet - public static Object checkcastUnknown( + public static Object checkcastDynamic( @Parameter("hub") Object hub, @Parameter("object") Object object, - @VarargsParameter("hints") Object[] hints, @ConstantParameter("checkNull") boolean checkNull) { if (checkNull && object == null) { isNull.inc(); return object; } Object objectHub = loadHub(object); - // if we get an exact match: succeed immediately - ExplodeLoopNode.explodeLoop(); - for (int i = 0; i < hints.length; i++) { - Object hintHub = hints[i]; - if (hintHub == objectHub) { - hintsHit.inc(); - return object; - } - } if (!checkUnknownSubType(hub, objectHub)) { DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ClassCastException); } @@ -237,14 +227,14 @@ private final ResolvedJavaMethod exact; private final ResolvedJavaMethod primary; private final ResolvedJavaMethod secondary; - private final ResolvedJavaMethod unknown; + private final ResolvedJavaMethod dynamic; public Templates(CodeCacheProvider runtime) { super(runtime, CheckCastSnippets.class); exact = snippet("checkcastExact", Object.class, Object.class, boolean.class); primary = snippet("checkcastPrimary", Object.class, Object.class, boolean.class, int.class); secondary = snippet("checkcastSecondary", Object.class, Object.class, Object[].class, boolean.class); - unknown = snippet("checkcastUnknown", Object.class, Object.class, Object[].class, boolean.class); + dynamic = snippet("checkcastDynamic", Object.class, Object.class, boolean.class); } /** @@ -252,25 +242,22 @@ */ public void lower(CheckCastNode checkcast, LoweringTool tool) { StructuredGraph graph = (StructuredGraph) checkcast.graph(); - ValueNode hub = checkcast.targetClassInstruction(); ValueNode object = checkcast.object(); - TypeCheckHints hintInfo = new TypeCheckHints(checkcast.targetClass(), checkcast.profile(), tool.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints); - final HotSpotResolvedJavaType target = (HotSpotResolvedJavaType) checkcast.targetClass(); + TypeCheckHints hintInfo = new TypeCheckHints(checkcast.type(), checkcast.profile(), tool.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints); + final HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) checkcast.type(); + ValueNode hub = ConstantNode.forObject(type.klassOop(), runtime, checkcast.graph()); boolean checkNull = !object.stamp().nonNull(); Arguments arguments; Key key; - if (target == null) { - HotSpotKlassOop[] hints = createHints(hintInfo); - key = new Key(unknown).add("hints", vargargs(Object.class, hints.length)).add("checkNull", checkNull); - arguments = arguments("hub", hub).add("object", object).add("hints", hints); - } else if (hintInfo.exact) { + assert type != null; + if (hintInfo.exact) { HotSpotKlassOop[] hints = createHints(hintInfo); assert hints.length == 1; key = new Key(exact).add("checkNull", checkNull); arguments = arguments("object", object).add("exactHub", hints[0]); - } else if (target.isPrimaryType()) { - key = new Key(primary).add("checkNull", checkNull).add("superCheckOffset", target.superCheckOffset()); + } else if (type.isPrimaryType()) { + key = new Key(primary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset()); arguments = arguments("hub", hub).add("object", object); } else { HotSpotKlassOop[] hints = createHints(hintInfo); @@ -283,6 +270,23 @@ template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments); } + /** + * Lowers a dynamic checkcast node. + */ + public void lower(CheckCastDynamicNode checkcast) { + StructuredGraph graph = (StructuredGraph) checkcast.graph(); + ValueNode hub = checkcast.type(); + ValueNode object = checkcast.object(); + boolean checkNull = !object.stamp().nonNull(); + + Key key = new Key(dynamic).add("checkNull", checkNull); + Arguments arguments = arguments("hub", hub).add("object", object); + + SnippetTemplate template = cache.get(key); + Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments); + template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments); + } + static HotSpotKlassOop[] createHints(TypeCheckHints hints) { HotSpotKlassOop[] hintHubs = new HotSpotKlassOop[hints.types.length]; for (int i = 0; i < hintHubs.length; i++) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java Fri Nov 09 13:35:26 2012 +0100 @@ -25,30 +25,23 @@ import static com.oracle.graal.hotspot.snippets.CheckCastSnippets.Templates.*; import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; import static com.oracle.graal.snippets.Snippet.Varargs.*; -import static com.oracle.graal.snippets.SnippetTemplate.*; import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*; -import static com.oracle.graal.snippets.nodes.JumpNode.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; import com.oracle.graal.snippets.*; import com.oracle.graal.snippets.Snippet.ConstantParameter; import com.oracle.graal.snippets.Snippet.Parameter; import com.oracle.graal.snippets.Snippet.VarargsParameter; -import com.oracle.graal.snippets.SnippetTemplate.AbstractTemplates; import com.oracle.graal.snippets.SnippetTemplate.Arguments; import com.oracle.graal.snippets.SnippetTemplate.Key; -import com.oracle.graal.snippets.SnippetTemplate.UsageReplacer; import com.oracle.graal.snippets.nodes.*; /** @@ -62,10 +55,10 @@ public class InstanceOfSnippets implements SnippetsInterface { /** - * A test against a final type with the result being {@linkplain ConditionalNode materialized}. + * A test against a final type. */ @Snippet - public static Object materializeExact( + public static Object instanceofExact( @Parameter("object") Object object, @Parameter("exactHub") Object exactHub, @Parameter("trueValue") Object trueValue, @@ -85,33 +78,10 @@ } /** - * A test against a final type with the result being {@linkplain IfNode branched} upon. + * A test against a primary type. */ @Snippet - public static void ifExact( - @Parameter("object") Object object, - @Parameter("exactHub") Object exactHub, - @ConstantParameter("checkNull") boolean checkNull) { - if (checkNull && object == null) { - isNull.inc(); - jump(IfNode.FALSE_EDGE); - return; - } - Object objectHub = loadHub(object); - if (objectHub != exactHub) { - exactMiss.inc(); - jump(IfNode.FALSE_EDGE); - return; - } - exactHit.inc(); - jump(IfNode.TRUE_EDGE); - } - - /** - * A test against a primary type with the result being {@linkplain ConditionalNode materialized}. - */ - @Snippet - public static Object materializePrimary( + public static Object instanceofPrimary( @Parameter("hub") Object hub, @Parameter("object") Object object, @Parameter("trueValue") Object trueValue, @@ -132,35 +102,10 @@ } /** - * A test against a primary type with the result being {@linkplain IfNode branched} upon. + * A test against a restricted secondary type type. */ @Snippet - public static void ifPrimary( - @Parameter("hub") Object hub, - @Parameter("object") Object object, - @ConstantParameter("checkNull") boolean checkNull, - @ConstantParameter("superCheckOffset") int superCheckOffset) { - if (checkNull && object == null) { - isNull.inc(); - jump(IfNode.FALSE_EDGE); - return; - } - Object objectHub = loadHub(object); - if (UnsafeLoadNode.loadObject(objectHub, 0, superCheckOffset, true) != hub) { - displayMiss.inc(); - jump(IfNode.FALSE_EDGE); - return; - } - displayHit.inc(); - jump(IfNode.TRUE_EDGE); - return; - } - - /** - * A test against a restricted secondary type type with the result being {@linkplain ConditionalNode materialized}. - */ - @Snippet - public static Object materializeSecondary( + public static Object instanceofSecondary( @Parameter("hub") Object hub, @Parameter("object") Object object, @Parameter("trueValue") Object trueValue, @@ -187,70 +132,6 @@ return trueValue; } - /** - * A test against a restricted secondary type with the result being {@linkplain IfNode branched} upon. - */ - @Snippet - public static void ifSecondary( - @Parameter("hub") Object hub, - @Parameter("object") Object object, - @VarargsParameter("hints") Object[] hints, - @ConstantParameter("checkNull") boolean checkNull) { - if (checkNull && object == null) { - isNull.inc(); - jump(IfNode.FALSE_EDGE); - return; - } - Object objectHub = loadHub(object); - // if we get an exact match: succeed immediately - ExplodeLoopNode.explodeLoop(); - for (int i = 0; i < hints.length; i++) { - Object hintHub = hints[i]; - if (hintHub == objectHub) { - hintsHit.inc(); - jump(IfNode.TRUE_EDGE); - return; - } - } - if (!checkSecondarySubType(hub, objectHub)) { - jump(IfNode.FALSE_EDGE); - return; - } - jump(IfNode.TRUE_EDGE); - return; - } - - /** - * A test against an unknown (at compile time) type with the result being {@linkplain ConditionalNode materialized}. - */ - @Snippet - public static Object materializeUnknown( - @Parameter("hub") Object hub, - @Parameter("object") Object object, - @Parameter("trueValue") Object trueValue, - @Parameter("falseValue") Object falseValue, - @VarargsParameter("hints") Object[] hints, - @ConstantParameter("checkNull") boolean checkNull) { - if (checkNull && object == null) { - isNull.inc(); - return falseValue; - } - Object objectHub = loadHub(object); - // if we get an exact match: succeed immediately - ExplodeLoopNode.explodeLoop(); - for (int i = 0; i < hints.length; i++) { - Object hintHub = hints[i]; - if (hintHub == objectHub) { - hintsHit.inc(); - return trueValue; - } - } - if (!checkUnknownSubType(hub, objectHub)) { - return falseValue; - } - return trueValue; - } - static boolean checkSecondarySubType(Object t, Object s) { // if (S.cache == T) return true if (UnsafeLoadNode.loadObject(s, 0, secondarySuperCacheOffset(), true) == t) { @@ -278,136 +159,45 @@ return false; } - public static class Templates extends AbstractTemplates<InstanceOfSnippets> { + public static class Templates extends InstanceOfSnippetsTemplates<InstanceOfSnippets> { - private final ResolvedJavaMethod ifExact; - private final ResolvedJavaMethod ifPrimary; - private final ResolvedJavaMethod ifSecondary; - private final ResolvedJavaMethod materializeExact; - private final ResolvedJavaMethod materializePrimary; - private final ResolvedJavaMethod materializeSecondary; + private final ResolvedJavaMethod instanceofExact; + private final ResolvedJavaMethod instanceofPrimary; + private final ResolvedJavaMethod instanceofSecondary; public Templates(CodeCacheProvider runtime) { super(runtime, InstanceOfSnippets.class); - ifExact = snippet("ifExact", Object.class, Object.class, boolean.class); - ifPrimary = snippet("ifPrimary", Object.class, Object.class, boolean.class, int.class); - ifSecondary = snippet("ifSecondary", Object.class, Object.class, Object[].class, boolean.class); - - materializeExact = snippet("materializeExact", Object.class, Object.class, Object.class, Object.class, boolean.class); - materializePrimary = snippet("materializePrimary", Object.class, Object.class, Object.class, Object.class, boolean.class, int.class); - materializeSecondary = snippet("materializeSecondary", Object.class, Object.class, Object.class, Object.class, Object[].class, boolean.class); + instanceofExact = snippet("instanceofExact", Object.class, Object.class, Object.class, Object.class, boolean.class); + instanceofPrimary = snippet("instanceofPrimary", Object.class, Object.class, Object.class, Object.class, boolean.class, int.class); + instanceofSecondary = snippet("instanceofSecondary", Object.class, Object.class, Object.class, Object.class, Object[].class, boolean.class); } - private static final boolean MATERIALIZE_IF_NODE_USAGES = Boolean.getBoolean("graal.instanceof.disableJumpNodes"); - - public void lower(InstanceOfNode instanceOf, LoweringTool tool) { - ValueNode hub = instanceOf.targetClassInstruction(); + @Override + protected KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) { + InstanceOfNode instanceOf = replacer.instanceOf; + ValueNode trueValue = replacer.trueValue; + ValueNode falseValue = replacer.falseValue; ValueNode object = instanceOf.object(); - TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.targetClass(), instanceOf.profile(), tool.assumptions(), GraalOptions.CheckcastMinHintHitProbability, GraalOptions.CheckcastMaxHints); - final HotSpotResolvedJavaType target = (HotSpotResolvedJavaType) instanceOf.targetClass(); + TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), GraalOptions.InstanceOfMinHintHitProbability, GraalOptions.InstanceOfMaxHints); + final HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) instanceOf.type(); + ConstantNode hub = ConstantNode.forObject(type.klassOop(), runtime, instanceOf.graph()); boolean checkNull = !object.stamp().nonNull(); - - for (Node usage : instanceOf.usages().snapshot()) { - Arguments arguments = null; - Key key = null; - - // instanceof nodes are lowered separately for each usage. To simply graph modifications, - // we duplicate the instanceof node for each usage. - final InstanceOfNode duplicate = instanceOf.graph().add(new InstanceOfNode(instanceOf.targetClassInstruction(), instanceOf.targetClass(), instanceOf.object(), instanceOf.profile())); - usage.replaceFirstInput(instanceOf, duplicate); - - if (usage instanceof IfNode) { - final StructuredGraph graph = (StructuredGraph) usage.graph(); - if (!MATERIALIZE_IF_NODE_USAGES) { - - IfNode ifNode = (IfNode) usage; - if (hintInfo.exact) { - HotSpotKlassOop[] hints = createHints(hintInfo); - assert hints.length == 1; - key = new Key(ifExact).add("checkNull", checkNull); - arguments = arguments("object", object).add("exactHub", hints[0]); - } else if (target.isPrimaryType()) { - key = new Key(ifPrimary).add("checkNull", checkNull).add("superCheckOffset", target.superCheckOffset()); - arguments = arguments("hub", hub).add("object", object); - } else { - HotSpotKlassOop[] hints = createHints(hintInfo); - key = new Key(ifSecondary).add("hints", vargargs(Object.class, hints.length)).add("checkNull", checkNull); - arguments = arguments("hub", hub).add("object", object).add("hints", hints); - } - - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, duplicate, ifNode, arguments); - assert ifNode.isDeleted(); - - } else { - - final ValueNode falseValue = ConstantNode.forInt(0, graph); - final ValueNode trueValue = ConstantNode.forInt(1, graph); - - if (hintInfo.exact) { - HotSpotKlassOop[] hints = createHints(hintInfo); - assert hints.length == 1; - key = new Key(materializeExact).add("checkNull", checkNull); - arguments = arguments("object", object).add("exactHub", hints[0]).add("trueValue", trueValue).add("falseValue", falseValue); - } else if (target.isPrimaryType()) { - key = new Key(materializePrimary).add("checkNull", checkNull).add("superCheckOffset", target.superCheckOffset()); - arguments = arguments("hub", hub).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue); - } else { - HotSpotKlassOop[] hints = createHints(hintInfo); - key = new Key(materializeSecondary).add("hints", vargargs(Object.class, hints.length)).add("checkNull", checkNull); - arguments = arguments("hub", hub).add("object", object).add("hints", hints).add("trueValue", trueValue).add("falseValue", falseValue); - } - - UsageReplacer replacer = new UsageReplacer() { - @Override - public void replace(ValueNode oldNode, ValueNode newNode) { - assert oldNode == duplicate; - newNode.inferStamp(); - IntegerEqualsNode condition = graph.add(new IntegerEqualsNode(newNode, trueValue)); - oldNode.replaceAtUsages(condition); - } - }; - - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, duplicate, replacer, tool.lastFixedNode(), arguments); - } - - } else if (usage instanceof ConditionalNode) { - - ConditionalNode materialize = (ConditionalNode) usage; - materialize.replaceAtUsages(duplicate); - ValueNode falseValue = materialize.falseValue(); - ValueNode trueValue = materialize.trueValue(); - - // The materialize node is no longer connected to anyone -> kill it - materialize.clearInputs(); - assert materialize.usages().isEmpty(); - GraphUtil.killWithUnusedFloatingInputs(materialize); - - if (hintInfo.exact) { - HotSpotKlassOop[] hints = createHints(hintInfo); - assert hints.length == 1; - key = new Key(materializeExact).add("checkNull", checkNull); - arguments = arguments("object", object).add("exactHub", hints[0]).add("trueValue", trueValue).add("falseValue", falseValue); - } else if (target.isPrimaryType()) { - key = new Key(materializePrimary).add("checkNull", checkNull).add("superCheckOffset", target.superCheckOffset()); - arguments = arguments("hub", hub).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue); - } else { - HotSpotKlassOop[] hints = createHints(hintInfo); - key = new Key(materializeSecondary).add("hints", vargargs(Object.class, hints.length)).add("checkNull", checkNull); - arguments = arguments("hub", hub).add("object", object).add("hints", hints).add("trueValue", trueValue).add("falseValue", falseValue); - } - - SnippetTemplate template = cache.get(key); - template.instantiate(runtime, duplicate, DEFAULT_REPLACER, tool.lastFixedNode(), arguments); - } else { - throw new GraalInternalError("Unexpected usage of %s: %s", instanceOf, usage); - } + Arguments arguments; + Key key; + if (hintInfo.exact) { + HotSpotKlassOop[] hints = createHints(hintInfo); + assert hints.length == 1; + key = new Key(instanceofExact).add("checkNull", checkNull); + arguments = arguments("object", object).add("exactHub", hints[0]).add("trueValue", trueValue).add("falseValue", falseValue); + } else if (type.isPrimaryType()) { + key = new Key(instanceofPrimary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset()); + arguments = arguments("hub", hub).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue); + } else { + HotSpotKlassOop[] hints = createHints(hintInfo); + key = new Key(instanceofSecondary).add("hints", vargargs(Object.class, hints.length)).add("checkNull", checkNull); + arguments = arguments("hub", hub).add("object", object).add("hints", hints).add("trueValue", trueValue).add("falseValue", falseValue); } - - assert !instanceOf.isDeleted(); - assert instanceOf.usages().isEmpty(); - GraphUtil.killWithUnusedFloatingInputs(instanceOf); + return new KeyAndArguments(key, arguments); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Fri Nov 09 13:35:26 2012 +0100 @@ -520,7 +520,7 @@ callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter, new ValueNode[] {errMsg}, returnType)); invoke = graph.add(new InvokeNode(callTarget, 0, -1)); List<ValueNode> stack = Collections.emptyList(); - FrameState stateAfter = new FrameState(graph.method(), FrameState.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], false, false, null); + FrameState stateAfter = new FrameState(graph.method(), FrameState.AFTER_BCI, new ValueNode[0], stack, new ValueNode[0], false, false); invoke.setStateAfter(graph.add(stateAfter)); graph.addBeforeFixed(ret, invoke); inlineeGraph = (StructuredGraph) checkCounter.getCompilerStorage().get(Graph.class);
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Fri Nov 09 13:35:26 2012 +0100 @@ -28,6 +28,7 @@ import java.util.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.Node.Verbosity; @@ -128,7 +129,7 @@ } public FrameState create(int bci) { - return graph.add(new FrameState(method, bci, locals, Arrays.asList(stack).subList(0, stackSize), locks, rethrowException, false, null)); + return graph.add(new FrameState(method, bci, locals, Arrays.asList(stack).subList(0, stackSize), locks, rethrowException, false)); } public FrameStateBuilder copy() { @@ -153,8 +154,7 @@ } for (int i = 0; i < locks.length; i++) { if (GraphUtil.originalValue(locks[i]) != GraphUtil.originalValue(other.locks[i])) { - System.out.println("unbalanced monitors"); - return false; + throw new BailoutException("unbalanced monitors"); } } return true; @@ -229,7 +229,7 @@ } } - public void insertProxies(LoopExitNode loopExit, FrameStateBuilder loopEntryState) { + public void insertLoopProxies(LoopExitNode loopExit, FrameStateBuilder loopEntryState) { for (int i = 0; i < localsSize(); i++) { ValueNode value = localAt(i); if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { @@ -253,6 +253,30 @@ } } + public void insertProxies(BeginNode begin) { + for (int i = 0; i < localsSize(); i++) { + ValueNode value = localAt(i); + if (value != null) { + Debug.log(" inserting proxy for %s", value); + storeLocal(i, graph.unique(new ValueProxyNode(value, begin, PhiType.Value))); + } + } + for (int i = 0; i < stackSize(); i++) { + ValueNode value = stackAt(i); + if (value != null) { + Debug.log(" inserting proxy for %s", value); + storeStack(i, graph.unique(new ValueProxyNode(value, begin, PhiType.Value))); + } + } + for (int i = 0; i < locks.length; i++) { + ValueNode value = locks[i]; + if (value != null) { + Debug.log(" inserting proxy for %s", value); + locks[i] = graph.unique(new ValueProxyNode(value, begin, PhiType.Value)); + } + } + } + private PhiNode createLoopPhi(MergeNode block, ValueNode value) { if (value == null) { return null;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Nov 09 13:35:26 2012 +0100 @@ -75,6 +75,7 @@ private final MetaAccessProvider runtime; private ConstantPool constantPool; private ResolvedJavaMethod method; + private int entryBCI; private ProfilingInfo profilingInfo; private BytecodeStream stream; // the bytecode stream @@ -119,6 +120,7 @@ @Override protected void run(StructuredGraph graph) { method = graph.method(); + entryBCI = graph.getEntryBCI(); graphId = graph.graphId(); profilingInfo = method.getProfilingInfo(); assert method.getCode() != null : "method must contain bytecodes: " + method; @@ -633,9 +635,8 @@ JavaType type = lookupType(cpi, CHECKCAST); boolean initialized = type instanceof ResolvedJavaType; if (initialized) { - ConstantNode typeInstruction = genTypeOrDeopt(Representation.ObjectHub, type, true); ValueNode object = frameState.apop(); - CheckCastNode checkCast = currentGraph.add(new CheckCastNode(typeInstruction, (ResolvedJavaType) type, object, getProfileForTypeCheck((ResolvedJavaType) type))); + CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) type, object, getProfileForTypeCheck((ResolvedJavaType) type))); append(checkCast); frameState.apush(checkCast); } else { @@ -651,8 +652,7 @@ ValueNode object = frameState.apop(); if (type instanceof ResolvedJavaType) { ResolvedJavaType resolvedType = (ResolvedJavaType) type; - ConstantNode hub = appendConstant(resolvedType.getEncoding(Representation.ObjectHub)); - InstanceOfNode instanceOfNode = new InstanceOfNode(hub, (ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType)); + InstanceOfNode instanceOfNode = new InstanceOfNode((ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType)); frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode)))); } else { BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode()); @@ -1188,7 +1188,7 @@ } lastLoopExit = loopExit; Debug.log("Target %s (%s) Exits %s, scanning framestates...", targetBlock, target, loop); - newState.insertProxies(loopExit, loop.entryState); + newState.insertLoopProxies(loopExit, loop.entryState); loopExit.setStateAfter(newState.create(bci)); } @@ -1201,7 +1201,7 @@ private FixedNode createTarget(double probability, Block block, FrameStateBuilder stateAfter) { assert probability >= 0 && probability <= 1.01 : probability; - if (probability == 0 && optimisticOpts.removeNeverExecutedCode()) { + if (probability == 0 && optimisticOpts.removeNeverExecutedCode() && entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI) { return currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode, graphId)); } else { return createTarget(block, stateAfter); @@ -1373,7 +1373,6 @@ synchronizedEpilogue(FrameState.AFTER_BCI); if (!frameState.locksEmpty()) { - System.out.println("unbalanced monitors"); throw new BailoutException("unbalanced monitors"); } ReturnNode returnNode = currentGraph.add(new ReturnNode(x)); @@ -1412,11 +1411,10 @@ } } - ConstantNode typeInstruction = genTypeOrDeopt(Representation.ObjectHub, catchType, initialized); - if (typeInstruction != null) { + if (initialized) { Block nextBlock = block.successors.size() == 1 ? unwindBlock(block.deoptBci) : block.successors.get(1); ValueNode exception = frameState.stackAt(0); - CheckCastNode checkCast = currentGraph.add(new CheckCastNode(typeInstruction, (ResolvedJavaType) catchType, exception)); + CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) catchType, exception, null)); frameState.apop(); frameState.push(Kind.Object, checkCast); FixedNode catchSuccessor = createTarget(block.successors.get(0), frameState); @@ -1424,8 +1422,10 @@ frameState.push(Kind.Object, exception); FixedNode nextDispatch = createTarget(nextBlock, frameState); checkCast.setNext(catchSuccessor); - IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new InstanceOfNode(typeInstruction, (ResolvedJavaType) catchType, exception)), checkCast, nextDispatch, 0.5, graphId)); + IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new InstanceOfNode((ResolvedJavaType) catchType, exception, null)), checkCast, nextDispatch, 0.5, graphId)); append(ifNode); + } else { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved, graphId))); } } @@ -1487,6 +1487,12 @@ int opcode = stream.currentBC(); traceState(); traceInstruction(bci, opcode, bci == block.startBci); + if (bci == entryBCI) { + EntryMarkerNode x = currentGraph.add(new EntryMarkerNode()); + append(x); + frameState.insertProxies(x); + x.setStateAfter(frameState.create(bci)); + } processBytecode(bci, opcode); if (lastInstr == null || isBlockEnd(lastInstr) || lastInstr.next() != null) {
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Fri Nov 09 13:35:26 2012 +0100 @@ -25,6 +25,7 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.*;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Fri Nov 09 13:35:26 2012 +0100 @@ -64,7 +64,7 @@ protected void emitAlignmentForDirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { // make sure that the displacement word of the call ends up word aligned int offset = masm.codeBuffer.position(); - offset += tasm.target.arch.machineCodeCallDisplacementOffset; + offset += tasm.target.arch.getMachineCodeCallDisplacementOffset(); while (offset++ % tasm.target.wordSize != 0) { masm.nop(); }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Fri Nov 09 13:35:26 2012 +0100 @@ -25,6 +25,7 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.Address.Scale; import com.oracle.graal.api.code.CompilationResult.JumpTable;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Fri Nov 09 13:35:26 2012 +0100 @@ -27,6 +27,7 @@ import static java.lang.Double.*; import static java.lang.Float.*; +import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java Fri Nov 09 13:35:26 2012 +0100 @@ -137,7 +137,7 @@ } private int returnAddressSize() { - return target.arch.returnAddressSize; + return target.arch.getReturnAddressSize(); } private int calleeSaveAreaSize() { @@ -294,7 +294,7 @@ * Initializes a reference map that covers all registers of the target architecture. */ public BitSet initRegisterRefMap() { - return new BitSet(target.arch.registerReferenceMapBitCount); + return new BitSet(target.arch.getRegisterReferenceMapBitCount()); } /**
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Fri Nov 09 13:35:26 2012 +0100 @@ -51,7 +51,7 @@ } private int maxRegisterNum() { - return frameMap.target.arch.registers.length; + return frameMap.target.arch.getRegisters().length; } private boolean isAllocatableRegister(Value value) { @@ -101,11 +101,12 @@ ValueProcedure useProc = new ValueProcedure() { @Override public Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } }; ValueProcedure defProc = new ValueProcedure() { @Override public Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, mode, flags); } }; + int maxRegisterNum = maxRegisterNum(); curRegistersDefined = new BitSet(); for (Block block : lir.linearScanOrder()) { curBlock = block; curVariablesLive = new BitSet(); - curRegistersLive = new Value[maxRegisterNum()]; + curRegistersLive = new Value[maxRegisterNum]; if (block.getDominator() != null) { curVariablesLive.or(liveOutFor(block.getDominator()));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -87,7 +87,7 @@ return null; } - public void evacuateGuards(FixedNode evacuateFrom) { + private void evacuateGuards(FixedNode evacuateFrom) { if (!usages().isEmpty()) { BeginNode prevBegin = prevBegin(evacuateFrom); assert prevBegin != null;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -25,6 +25,7 @@ import java.util.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.type.*; /** @@ -61,28 +62,8 @@ branchProbability[successorIndex] = x; } - public Iterable<BeginNode> blockSuccessors() { - return new Iterable<BeginNode>() { - @Override - public Iterator<BeginNode> iterator() { - return new Iterator<BeginNode>() { - int i = 0; - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - @Override - public BeginNode next() { - return ControlSplitNode.this.blockSuccessor(i++); - } - - @Override - public boolean hasNext() { - return i < ControlSplitNode.this.blockSuccessorCount(); - } - }; - } - }; + public NodeIterable<BeginNode> blockSuccessors() { + return blockSuccessors; } public int blockSuccessorIndex(BeginNode successor) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.spi.*; + +/** + * This node will be inserted at point specified by {@link StructuredGraph#getEntryBCI()}, usually by the graph builder. + */ +public class EntryMarkerNode extends BeginNode implements Node.IterableNodeType, Simplifiable, LIRLowerable { + + @Override + public void simplify(SimplifierTool tool) { + // this node should not be removed, this overrides BeginNode.simplify + } + + @Override + public void generate(LIRGeneratorTool gen) { + throw new GraalInternalError("OnStackReplacementNode should not survive"); + } +}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Fri Nov 09 13:35:26 2012 +0100 @@ -38,29 +38,6 @@ @NodeInfo(nameTemplate = "FrameState@{p#method/s}:{p#bci}") public final class FrameState extends VirtualState implements Node.IterableNodeType, LIRLowerable { - /** - * An instance of this class is an identifier for all nodes that were generated by one specific inlining operation. - * It is used to generate the correct debug information for nested locks. - */ - public static final class InliningIdentifier { - private final ResolvedJavaMethod method; - private final Object context; - - public InliningIdentifier(ResolvedJavaMethod method, Object context) { - this.method = method; - this.context = context; - } - - @Override - public String toString() { - try { - return method + "@" + context; - } catch (Exception e) { - return super.toString(); - } - } - } - protected final int localsSize; protected final int stackSize; @@ -70,12 +47,6 @@ private boolean duringCall; /** - * This object identifies the concrete inlining operation that produced this frame state. - * It is set during inlining, therefore for the outermost frame states of a graph this field is null. - */ - private InliningIdentifier inliningIdentifier; - - /** * This BCI should be used for frame states that are built for code with no meaningful BCI. */ public static final int UNKNOWN_BCI = -4; @@ -121,7 +92,7 @@ * @param stackSize size of the stack * @param rethrowException if true the VM should re-throw the exception on top of the stack when deopt'ing using this framestate */ - public FrameState(ResolvedJavaMethod method, int bci, List<ValueNode> values, int localsSize, int stackSize, boolean rethrowException, boolean duringCall, InliningIdentifier inliningIdentifier, List<EscapeObjectState> virtualObjectMappings) { + public FrameState(ResolvedJavaMethod method, int bci, List<ValueNode> values, int localsSize, int stackSize, boolean rethrowException, boolean duringCall, List<EscapeObjectState> virtualObjectMappings) { assert stackSize >= 0; assert (bci >= 0 && method != null) || (bci < 0 && method == null && values.isEmpty()); this.method = method; @@ -132,7 +103,6 @@ this.virtualObjectMappings = new NodeInputList<>(this, virtualObjectMappings); this.rethrowException = rethrowException; this.duringCall = duringCall; - this.inliningIdentifier = inliningIdentifier; assert !rethrowException || stackSize == 1 : "must have exception on top of the stack"; } @@ -141,11 +111,10 @@ * @param bci marker bci, needs to be < 0 */ public FrameState(int bci) { - this(null, bci, Collections.<ValueNode>emptyList(), 0, 0, false, false, null, Collections.<EscapeObjectState>emptyList()); + this(null, bci, Collections.<ValueNode>emptyList(), 0, 0, false, false, Collections.<EscapeObjectState>emptyList()); } - public FrameState(ResolvedJavaMethod method, int bci, ValueNode[] locals, List<ValueNode> stack, ValueNode[] locks, boolean rethrowException, boolean duringCall, - InliningIdentifier inliningIdentifier) { + public FrameState(ResolvedJavaMethod method, int bci, ValueNode[] locals, List<ValueNode> stack, ValueNode[] locks, boolean rethrowException, boolean duringCall) { this.method = method; this.bci = bci; this.localsSize = locals.length; @@ -168,11 +137,10 @@ this.virtualObjectMappings = new NodeInputList<>(this); this.rethrowException = rethrowException; this.duringCall = duringCall; - this.inliningIdentifier = inliningIdentifier; assert !rethrowException || stackSize == 1 : "must have exception on top of the stack"; } - public NodeIterable<ValueNode> values() { + public NodeInputList<ValueNode> values() { return values; } @@ -185,14 +153,6 @@ this.outerFrameState = x; } - public InliningIdentifier inliningIdentifier() { - return inliningIdentifier; - } - - public void setInliningIdentifier(InliningIdentifier inliningIdentifier) { - this.inliningIdentifier = inliningIdentifier; - } - public boolean rethrowException() { return rethrowException; } @@ -229,7 +189,7 @@ * Gets a copy of this frame state. */ public FrameState duplicate(int newBci) { - FrameState other = graph().add(new FrameState(method, newBci, values, localsSize, stackSize, rethrowException, duringCall, inliningIdentifier, virtualObjectMappings)); + FrameState other = graph().add(new FrameState(method, newBci, values, localsSize, stackSize, rethrowException, duringCall, virtualObjectMappings)); other.setOuterFrameState(outerFrameState()); return other; } @@ -255,7 +215,7 @@ for (EscapeObjectState state : virtualObjectMappings) { newVirtualMappings.add(state.duplicateWithVirtualState()); } - FrameState other = graph().add(new FrameState(method, bci, values, localsSize, stackSize, rethrowException, duringCall, inliningIdentifier, newVirtualMappings)); + FrameState other = graph().add(new FrameState(method, bci, values, localsSize, stackSize, rethrowException, duringCall, newVirtualMappings)); other.setOuterFrameState(newOuterFrameState); return other; } @@ -279,7 +239,7 @@ int newStackSize = copy.size() - localsSize; copy.addAll(values.subList(localsSize + stackSize, values.size())); - FrameState other = graph().add(new FrameState(method, newBci, copy, localsSize, newStackSize, newRethrowException, false, inliningIdentifier, virtualObjectMappings)); + FrameState other = graph().add(new FrameState(method, newBci, copy, localsSize, newStackSize, newRethrowException, false, virtualObjectMappings)); other.setOuterFrameState(outerFrameState()); return other; } @@ -361,11 +321,11 @@ for (int i = 0; i < fs.localsSize(); i++) { sb.append(i == 0 ? "" : ", ").append(fs.localAt(i) == null ? "_" : fs.localAt(i).toString(Verbosity.Id)); } - sb.append("]").append(nl).append("stack: "); + sb.append("]").append(nl).append("stack: ["); for (int i = 0; i < fs.stackSize(); i++) { sb.append(i == 0 ? "" : ", ").append(fs.stackAt(i) == null ? "_" : fs.stackAt(i).toString(Verbosity.Id)); } - sb.append("]").append(nl).append("locks: "); + sb.append("]").append(nl).append("locks: ["); for (int i = 0; i < fs.locksSize(); i++) { sb.append(i == 0 ? "" : ", ").append(fs.lockAt(i) == null ? "_" : fs.lockAt(i).toString(Verbosity.Id)); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -49,6 +49,15 @@ private boolean negated; private final long leafGraphId; + public GuardNode(BooleanNode condition, FixedNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, long leafGraphId) { + super(StampFactory.dependency(), anchor); + this.condition = condition; + this.reason = reason; + this.action = action; + this.negated = negated; + this.leafGraphId = leafGraphId; + } + /** * The instruction that produces the tested boolean value. */ @@ -73,13 +82,8 @@ return action; } - public GuardNode(BooleanNode condition, FixedNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, long leafGraphId) { - super(StampFactory.dependency(), anchor); - this.condition = condition; - this.reason = reason; - this.action = action; - this.negated = negated; - this.leafGraphId = leafGraphId; + public long getLeafGraphId() { + return leafGraphId; } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -25,8 +25,12 @@ import java.util.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.PhiNode.PhiType; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; /** * The {@code IfNode} represents a branch that can go one of two directions depending on the outcome of a @@ -121,40 +125,259 @@ ((StructuredGraph) graph()).removeSplit(this, FALSE_EDGE); } } else if (trueSuccessor().guards().isEmpty() && falseSuccessor().guards().isEmpty()) { - if (trueSuccessor().next() instanceof EndNode && falseSuccessor().next() instanceof EndNode) { - EndNode trueEnd = (EndNode) trueSuccessor().next(); - EndNode falseEnd = (EndNode) falseSuccessor().next(); - MergeNode merge = trueEnd.merge(); - if (merge == falseEnd.merge() && merge.forwardEndCount() == 2 && trueSuccessor().anchored().isEmpty() && falseSuccessor().anchored().isEmpty()) { - Iterator<PhiNode> phis = merge.phis().iterator(); + if (removeOrMaterializeIf(tool)) { + return; + } else if (removeIntermediateMaterialization(tool)) { + return; + } + } + } + + /** + * Tries to remove an empty if construct or replace an if construct with a materialization. + * + * @return true if a transformation was made, false otherwise + */ + private boolean removeOrMaterializeIf(SimplifierTool tool) { + if (trueSuccessor().next() instanceof EndNode && falseSuccessor().next() instanceof EndNode) { + EndNode trueEnd = (EndNode) trueSuccessor().next(); + EndNode falseEnd = (EndNode) falseSuccessor().next(); + MergeNode merge = trueEnd.merge(); + if (merge == falseEnd.merge() && merge.forwardEndCount() == 2 && trueSuccessor().anchored().isEmpty() && falseSuccessor().anchored().isEmpty()) { + Iterator<PhiNode> phis = merge.phis().iterator(); + if (!phis.hasNext()) { + // empty if construct with no phis: remove it + removeEmptyIf(tool); + return false; + } else { + PhiNode singlePhi = phis.next(); if (!phis.hasNext()) { - // empty if construct with no phis: remove it - removeEmptyIf(tool); - return; - } else { - PhiNode singlePhi = phis.next(); - if (!phis.hasNext()) { - // one phi at the merge of an otherwise empty if construct: try to convert into a MaterializeNode - boolean inverted = trueEnd == merge.forwardEndAt(FALSE_EDGE); - ValueNode trueValue = singlePhi.valueAt(inverted ? 1 : 0); - ValueNode falseValue = singlePhi.valueAt(inverted ? 0 : 1); - if (trueValue.kind() != falseValue.kind()) { - return; - } - if (trueValue.kind() != Kind.Int && trueValue.kind() != Kind.Long) { - return; - } - if (trueValue.isConstant() && falseValue.isConstant()) { - MaterializeNode materialize = MaterializeNode.create(condition(), trueValue, falseValue); - ((StructuredGraph) graph()).replaceFloating(singlePhi, materialize); - removeEmptyIf(tool); - return; - } + // one phi at the merge of an otherwise empty if construct: try to convert into a MaterializeNode + boolean inverted = trueEnd == merge.forwardEndAt(FALSE_EDGE); + ValueNode trueValue = singlePhi.valueAt(inverted ? 1 : 0); + ValueNode falseValue = singlePhi.valueAt(inverted ? 0 : 1); + if (trueValue.kind() != falseValue.kind()) { + return false; + } + if (trueValue.kind() != Kind.Int && trueValue.kind() != Kind.Long) { + return false; + } + if (trueValue.isConstant() && falseValue.isConstant()) { + MaterializeNode materialize = MaterializeNode.create(condition(), trueValue, falseValue); + ((StructuredGraph) graph()).replaceFloating(singlePhi, materialize); + removeEmptyIf(tool); + return true; } } } } } + return false; + } + + /** + * Tries to connect code that initializes a variable directly with the successors of an if construct + * that switches on the variable. For example, the pseudo code below: + * + * <pre> + * contains(list, e, yes, no) { + * if (list == null || e == null) { + * condition = false; + * } else { + * condition = false; + * for (i in list) { + * if (i.equals(e)) { + * condition = true; + * break; + * } + * } + * } + * if (condition) { + * return yes; + * } else { + * return no; + * } + * } + * </pre> + * will be transformed into: + * <pre> + * contains(list, e, yes, no) { + * if (list == null || e == null) { + * return no; + * } else { + * condition = false; + * for (i in list) { + * if (i.equals(e)) { + * return yes; + * } + * } + * return no; + * } + * } + * </pre> + * + * @return true if a transformation was made, false otherwise + */ + private boolean removeIntermediateMaterialization(SimplifierTool tool) { + if (!(condition() instanceof CompareNode)) { + return false; + } + + CompareNode compare = (CompareNode) condition(); + if (compare.usages().count() != 1) { + return false; + } + + if (!(predecessor() instanceof MergeNode)) { + return false; + } + + MergeNode merge = (MergeNode) predecessor(); + if (!merge.anchored().isEmpty()) { + return false; + } + + // Only consider merges with a single usage that is both a phi and an operand of the comparison + NodeUsagesList mergeUsages = merge.usages(); + if (mergeUsages.count() != 1) { + return false; + } + Node singleUsage = mergeUsages.first(); + if (!(singleUsage instanceof PhiNode) || (singleUsage != compare.x() && singleUsage != compare.y())) { + return false; + } + + // Ensure phi is used by at most the comparison and the merge's frame state (if any) + PhiNode phi = (PhiNode) singleUsage; + NodeUsagesList phiUsages = phi.usages(); + if (phiUsages.count() > 2) { + return false; + } + for (Node usage : phiUsages) { + if (usage != compare && usage != merge.stateAfter()) { + return false; + } + } + + List<EndNode> mergePredecessors = merge.cfgPredecessors().snapshot(); + if (phi.valueCount() != merge.forwardEndCount()) { + // Handles a loop begin merge + return false; + } + + Constant[] xs = constantValues(compare.x(), merge); + Constant[] ys = constantValues(compare.y(), merge); + if (xs == null || ys == null) { + return false; + } + + List<EndNode> falseEnds = new ArrayList<>(mergePredecessors.size()); + List<EndNode> trueEnds = new ArrayList<>(mergePredecessors.size()); + Map<EndNode, ValueNode> phiValues = new HashMap<>(mergePredecessors.size()); + + BeginNode falseSuccessor = falseSuccessor(); + BeginNode trueSuccessor = trueSuccessor(); + + setFalseSuccessor(null); + setTrueSuccessor(null); + + Iterator<EndNode> ends = mergePredecessors.iterator(); + for (int i = 0; i < xs.length; i++) { + EndNode end = ends.next(); + phiValues.put(end, phi.valueAt(end)); + if (compare.condition().foldCondition(xs[i], ys[i], tool.runtime(), compare.unorderedIsTrue())) { + trueEnds.add(end); + } else { + falseEnds.add(end); + } + } + assert !ends.hasNext(); + + connectEnds(falseEnds, phiValues, falseSuccessor, merge, tool); + connectEnds(trueEnds, phiValues, trueSuccessor, merge, tool); + + GraphUtil.killCFG(merge); + + assert !merge.isAlive() : merge; + assert !phi.isAlive() : phi; + assert !compare.isAlive() : compare; + assert !this.isAlive() : this; + + return true; + } + + /** + * Connects a set of ends to a given successor, inserting a merge node if + * there is more than one end. If {@code ends} is empty, then {@code successor} + * is {@linkplain GraphUtil#killCFG(FixedNode) killed} otherwise it is added to {@code tool}'s + * {@linkplain SimplifierTool#addToWorkList(com.oracle.graal.graph.Node) work list}. + * + * @param oldMerge the merge being removed + * @param phiValues the values of the phi at the merge, keyed by the merge ends + */ + private void connectEnds(List<EndNode> ends, Map<EndNode, ValueNode> phiValues, BeginNode successor, MergeNode oldMerge, SimplifierTool tool) { + if (ends.isEmpty()) { + GraphUtil.killCFG(successor); + } else { + if (ends.size() == 1) { + EndNode end = ends.get(0); + ((FixedWithNextNode) end.predecessor()).setNext(successor); + oldMerge.removeEnd(end); + GraphUtil.killCFG(end); + } else { + // Need a new phi in case the frame state is used by more than the merge being removed + MergeNode newMerge = graph().add(new MergeNode()); + PhiNode oldPhi = (PhiNode) oldMerge.usages().first(); + PhiNode newPhi = graph().add(new PhiNode(oldPhi.stamp(), newMerge)); + + for (EndNode end : ends) { + newPhi.addInput(phiValues.get(end)); + newMerge.addForwardEnd(end); + } + + FrameState stateAfter = oldMerge.stateAfter(); + if (stateAfter != null) { + stateAfter = stateAfter.duplicate(); + stateAfter.replaceFirstInput(oldPhi, newPhi); + newMerge.setStateAfter(stateAfter); + } + + newMerge.setNext(successor); + } + tool.addToWorkList(successor); + } + } + + /** + * Gets an array of constants derived from a node that is either a {@link ConstantNode} + * or a {@link PhiNode} whose input values are all constants. The length of the returned + * array is equal to the number of ends terminating in a given merge node. + * + * @return null if {@code node} is neither a {@link ConstantNode} nor a {@link PhiNode} whose input values are all constants + */ + private static Constant[] constantValues(ValueNode node, MergeNode merge) { + if (node.isConstant()) { + Constant[] result = new Constant[merge.forwardEndCount()]; + Arrays.fill(result, node.asConstant()); + return result; + } + + if (node instanceof PhiNode) { + PhiNode phi = (PhiNode) node; + if (phi.merge() == merge && phi.type() == PhiType.Value && phi.valueCount() == merge.forwardEndCount()) { + Constant[] result = new Constant[merge.forwardEndCount()]; + int i = 0; + for (ValueNode n : phi.values()) { + if (!n.isConstant()) { + return null; + } + result[i++] = n.asConstant(); + } + return result; + } + } + + return null; } private void removeEmptyIf(SimplifierTool tool) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -48,6 +48,11 @@ this.loopFrequency = loopFrequency; } + /** + * Returns the <b>unordered</b> set of {@link LoopEndNode} that correspond to back-edges for this loop. + * The order of the back-edges is unspecified, if you need to get an ordering compatible for {@link PhiNode} creation, use {@link #orderedLoopEnds()}. + * @return the set of {@code LoopEndNode} that correspond to back-edges for this loop + */ public NodeIterable<LoopEndNode> loopEnds() { return usages().filter(LoopEndNode.class); } @@ -61,6 +66,11 @@ return super.anchored().filter(isNotA(LoopEndNode.class).nor(LoopExitNode.class)); } + /** + * Returns the set of {@link LoopEndNode} that correspond to back-edges for this loop, ordered in increasing {@link #phiPredecessorIndex}. + * This method is suited to create new loop {@link PhiNode}. + * @return the set of {@code LoopEndNode} that correspond to back-edges for this loop + */ public List<LoopEndNode> orderedLoopEnds() { List<LoopEndNode> snapshot = loopEnds().snapshot(); Collections.sort(snapshot, new Comparator<LoopEndNode>() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -27,7 +27,7 @@ public final class MaterializeNode extends ConditionalNode { - private static CompareNode createCompareNode(Condition condition, ValueNode x, ValueNode y) { + public static CompareNode createCompareNode(Condition condition, ValueNode x, ValueNode y) { assert x.kind() == y.kind(); assert condition.isCanonical() : "condition is not canonical: " + condition;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -37,6 +37,7 @@ public static enum PhiType { Value(null), // normal value phis + Guard(StampFactory.dependency()), Memory(StampFactory.dependency()); public final Stamp stamp;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Fri Nov 09 13:35:26 2012 +0100 @@ -38,11 +38,14 @@ */ public class StructuredGraph extends Graph { + public static final int INVOCATION_ENTRY_BCI = -1; public static final long INVALID_GRAPH_ID = -1; + private static final AtomicLong uniqueGraphIds = new AtomicLong(); private final StartNode start; private final ResolvedJavaMethod method; private final long graphId; + private final int entryBCI; /** * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node. @@ -54,23 +57,24 @@ /** * Creates a new Graph containing a single {@link BeginNode} as the {@link #start() start} node. */ - public StructuredGraph(String name) { - this(name, null); + public StructuredGraph(String name, ResolvedJavaMethod method) { + this(name, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI); } - public StructuredGraph(String name, ResolvedJavaMethod method) { - this(name, method, uniqueGraphIds.incrementAndGet()); + public StructuredGraph(ResolvedJavaMethod method) { + this(null, method, uniqueGraphIds.incrementAndGet(), INVOCATION_ENTRY_BCI); } - private StructuredGraph(String name, ResolvedJavaMethod method, long graphId) { + public StructuredGraph(ResolvedJavaMethod method, int entryBCI) { + this(null, method, uniqueGraphIds.incrementAndGet(), entryBCI); + } + + private StructuredGraph(String name, ResolvedJavaMethod method, long graphId, int entryBCI) { super(name); this.start = add(new StartNode()); this.method = method; this.graphId = graphId; - } - - public StructuredGraph(ResolvedJavaMethod method) { - this(null, method); + this.entryBCI = entryBCI; } @Override @@ -102,6 +106,10 @@ return method; } + public int getEntryBCI() { + return entryBCI; + } + public long graphId() { return graphId; } @@ -113,7 +121,7 @@ @Override public StructuredGraph copy(String newName) { - StructuredGraph copy = new StructuredGraph(newName, method, graphId); + StructuredGraph copy = new StructuredGraph(newName, method, graphId, entryBCI); HashMap<Node, Node> replacements = new HashMap<>(); replacements.put(start, copy.start); copy.addDuplicates(getNodes(), replacements);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -84,24 +84,20 @@ Constant falseConstant = conditionalNode.falseValue().asConstant(); if (falseConstant != null && trueConstant != null && runtime != null) { - Boolean trueResult = cond.foldCondition(trueConstant, constant, runtime, unorderedIsTrue()); - Boolean falseResult = cond.foldCondition(falseConstant, constant, runtime, unorderedIsTrue()); + boolean trueResult = cond.foldCondition(trueConstant, constant, runtime, unorderedIsTrue()); + boolean falseResult = cond.foldCondition(falseConstant, constant, runtime, unorderedIsTrue()); - if (trueResult != null && falseResult != null) { - boolean trueUnboxedResult = trueResult; - boolean falseUnboxedResult = falseResult; - if (trueUnboxedResult == falseUnboxedResult) { - return ConstantNode.forBoolean(trueUnboxedResult, graph()); + if (trueResult == falseResult) { + return ConstantNode.forBoolean(trueResult, graph()); + } else { + if (trueResult) { + assert falseResult == false; + return conditionalNode.condition(); } else { - if (trueUnboxedResult) { - assert falseUnboxedResult == false; - return conditionalNode.condition(); - } else { - assert falseUnboxedResult == true; - negateUsages(); - return conditionalNode.condition(); + assert falseResult == true; + negateUsages(); + return conditionalNode.condition(); - } } } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -28,7 +28,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -@NodeInfo(nameTemplate = "RuntimeCall#{p#call/s}") +@NodeInfo(nameTemplate = "RuntimeCall#{p#descriptor/s}") public final class RuntimeCallNode extends AbstractCallNode implements LIRLowerable { private final Descriptor descriptor;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.java; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Implements a type check where the type being checked is loaded at runtime. + * This is used, for instance, to implement an object array store check. + */ +public final class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable, Lowerable, Node.IterableNodeType { + + @Input private ValueNode object; + @Input private ValueNode type; + + /** + * @param type the type being cast to + * @param object the instruction producing the object + */ + public CheckCastDynamicNode(ValueNode type, ValueNode object) { + super(StampFactory.object()); + this.type = type; + this.object = object; + } + + @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + @Override + public boolean inferStamp() { + if (object().stamp().nonNull() && !stamp().nonNull()) { + setStamp(StampFactory.objectNonNull()); + return true; + } + return super.inferStamp(); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + assert object() != null : this; + + if (object().objectStamp().alwaysNull()) { + return object(); + } + return this; + } + + public ValueNode object() { + return object; + } + + /** + * Gets the runtime-loaded type being cast to. + */ + public ValueNode type() { + return type; + } +}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -29,29 +29,24 @@ import com.oracle.graal.nodes.type.*; /** - * Implements a type check that results in a {@link ClassCastException} if it fails. + * Implements a type check against a compile-time known type. */ public final class CheckCastNode extends FixedWithNextNode implements Canonicalizable, Lowerable, Node.IterableNodeType { @Input private ValueNode object; - @Input private ValueNode targetClassInstruction; - private final ResolvedJavaType targetClass; + private final ResolvedJavaType type; private final JavaTypeProfile profile; /** * Creates a new CheckCast instruction. - * @param targetClassInstruction the instruction which produces the class which is being cast to - * @param targetClass the class being cast to + * + * @param type the type being cast to * @param object the instruction producing the object */ - public CheckCastNode(ValueNode targetClassInstruction, ResolvedJavaType targetClass, ValueNode object) { - this(targetClassInstruction, targetClass, object, null); - } - - public CheckCastNode(ValueNode targetClassInstruction, ResolvedJavaType targetClass, ValueNode object, JavaTypeProfile profile) { - super(targetClass == null ? StampFactory.object() : StampFactory.declared(targetClass)); - this.targetClassInstruction = targetClassInstruction; - this.targetClass = targetClass; + public CheckCastNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) { + super(StampFactory.declared(type)); + assert type != null; + this.type = type; this.object = object; this.profile = profile; } @@ -64,7 +59,7 @@ @Override public boolean inferStamp() { if (object().stamp().nonNull() && !stamp().nonNull()) { - setStamp(targetClass == null ? StampFactory.objectNonNull() : StampFactory.declaredNonNull(targetClass)); + setStamp(StampFactory.declaredNonNull(type)); return true; } return super.inferStamp(); @@ -74,9 +69,9 @@ public ValueNode canonical(CanonicalizerTool tool) { assert object() != null : this; - if (targetClass != null) { + if (type != null) { ResolvedJavaType objectType = object().objectStamp().type(); - if (objectType != null && objectType.isSubtypeOf(targetClass)) { + if (objectType != null && objectType.isSubtypeOf(type)) { // we don't have to check for null types here because they will also pass the checkcast. return object(); } @@ -92,19 +87,11 @@ return object; } - public ValueNode targetClassInstruction() { - return targetClassInstruction; - } - /** - * Gets the target class, i.e. the class being cast to, or the class being tested against. - * This may be null in the case where the type being tested is dynamically loaded such as - * when checking an object array store. - * - * @return the target class or null if not known + * Gets the type being cast to. */ - public ResolvedJavaType targetClass() { - return targetClass; + public ResolvedJavaType type() { + return type; } public JavaTypeProfile profile() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -35,28 +35,21 @@ public final class InstanceOfNode extends BooleanNode implements Canonicalizable, Lowerable, LIRLowerable { @Input private ValueNode object; - @Input private ValueNode targetClassInstruction; - private final ResolvedJavaType targetClass; + private final ResolvedJavaType type; private final JavaTypeProfile profile; /** * Constructs a new InstanceOfNode. * - * @param targetClassInstruction the instruction which produces the target class of the instanceof check - * @param targetClass the class which is the target of the instanceof check - * @param object the instruction producing the object input to this instruction + * @param type the target type of the instanceof check + * @param object the object being tested by the instanceof */ - public InstanceOfNode(ValueNode targetClassInstruction, ResolvedJavaType targetClass, ValueNode object) { - this(targetClassInstruction, targetClass, object, null); - } - - public InstanceOfNode(ValueNode targetClassInstruction, ResolvedJavaType targetClass, ValueNode object, JavaTypeProfile profile) { + public InstanceOfNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) { super(StampFactory.condition()); - this.targetClassInstruction = targetClassInstruction; - this.targetClass = targetClass; + this.type = type; this.object = object; this.profile = profile; - assert targetClass != null; + assert type != null; } @Override @@ -73,10 +66,10 @@ assert object() != null : this; ObjectStamp stamp = object().objectStamp(); - ResolvedJavaType type = stamp.type(); + ResolvedJavaType stampType = stamp.type(); if (stamp.isExactType()) { - boolean subType = type.isSubtypeOf(targetClass()); + boolean subType = stampType.isSubtypeOf(type()); if (subType) { if (stamp.nonNull()) { @@ -92,8 +85,8 @@ // we also don't care about null values, since they will also make the check fail. return ConstantNode.forBoolean(false, graph()); } - } else if (type != null) { - boolean subType = type.isSubtypeOf(targetClass()); + } else if (stampType != null) { + boolean subType = stampType.isSubtypeOf(type()); if (subType) { if (stamp.nonNull()) { @@ -118,16 +111,11 @@ return object; } - public ValueNode targetClassInstruction() { - return targetClassInstruction; - } - /** - * Gets the target class, i.e. the class being cast to, or the class being tested against. - * @return the target class + * Gets the type being tested. */ - public ResolvedJavaType targetClass() { - return targetClass; + public ResolvedJavaType type() { + return type; } public JavaTypeProfile profile() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -114,16 +114,22 @@ @Override public ValueNode[] fieldState() { ValueNode[] state = new ValueNode[constantLength]; + ConstantNode defaultForKind = constantLength == 0 ? null : ConstantNode.defaultForKind(elementType().getKind(), graph()); for (int i = 0; i < constantLength; i++) { - state[i] = ConstantNode.defaultForKind(elementType().getKind(), graph()); + state[i] = defaultForKind; } return state; } @Override - public VirtualObjectNode virtualObject(int virtualId) { + public VirtualObjectNode virtualObject(long virtualId) { return new VirtualArrayNode(virtualId, elementType, constantLength); } + + @Override + public int lockCount() { + return 0; + } }; } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -111,9 +111,14 @@ } @Override - public VirtualObjectNode virtualObject(int virtualId) { + public VirtualObjectNode virtualObject(long virtualId) { return new VirtualInstanceNode(virtualId, instanceClass(), fields); } + + @Override + public int lockCount() { + return 0; + } }; } return null;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/EscapeOp.java Fri Nov 09 13:35:26 2012 +0100 @@ -32,6 +32,8 @@ */ public abstract ValueNode[] fieldState(); - public abstract VirtualObjectNode virtualObject(int virtualId); + public abstract VirtualObjectNode virtualObject(long virtualId); + + public abstract int lockCount(); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java Fri Nov 09 13:35:26 2012 +0100 @@ -24,7 +24,9 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; public interface LoweringTool { GraalCodeCacheProvider getRuntime(); @@ -33,6 +35,8 @@ ValueNode createGuard(BooleanNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated, long leafGraphId); Assumptions assumptions(); + Block getBlockFor(Node node); + /** * Gets the closest fixed node preceding the node currently being lowered. */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/SimplifierTool.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/SimplifierTool.java Fri Nov 09 13:35:26 2012 +0100 @@ -25,8 +25,14 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; - +/** + * @see Simplifiable + */ public interface SimplifierTool extends CanonicalizerTool { void deleteBranch(FixedNode branch); + + /** + * Adds a node to the worklist independent of whether it has already been on the worklist. + */ void addToWorkList(Node node); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -32,7 +32,7 @@ private final ResolvedJavaType componentType; private final int length; - public VirtualArrayNode(int virtualId, ResolvedJavaType componentType, int length) { + public VirtualArrayNode(long virtualId, ResolvedJavaType componentType, int length) { super(virtualId); this.componentType = componentType; this.length = length;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -34,7 +34,7 @@ private final ResolvedJavaField[] fields; private final HashMap<ResolvedJavaField, Integer> fieldMap = new HashMap<>(); - public VirtualInstanceNode(int virtualId, ResolvedJavaType type, ResolvedJavaField[] fields) { + public VirtualInstanceNode(long virtualId, ResolvedJavaType type, ResolvedJavaField[] fields) { super(virtualId); this.type = type; this.fields = fields;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -31,9 +31,9 @@ @NodeInfo(nameTemplate = "VirtualObject {p#type}") public abstract class VirtualObjectNode extends FloatingNode implements LIRLowerable { - private final int virtualId; + private final long virtualId; - public VirtualObjectNode(int virtualId) { + public VirtualObjectNode(long virtualId) { super(StampFactory.virtual()); this.virtualId = virtualId; } @@ -42,7 +42,7 @@ public abstract int entryCount(); - public int virtualId() { + public long virtualId() { return virtualId; }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Fri Nov 09 13:35:26 2012 +0100 @@ -210,29 +210,35 @@ graph.removeFloating((FloatingNode) node); } else { // case 2 - assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode) : node + " -> " + canonical + + assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical + " : replacement should be floating or fixed and connected"; graph.replaceFloating((FloatingNode) node, canonical); } } else { assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")"; + FixedWithNextNode fixedWithNext = (FixedWithNextNode) node; + + // When removing a fixed node, new canonicalization opportunities for its successor may arise + assert fixedWithNext.next() != null; + tool.addToWorkList(fixedWithNext.next()); + if (canonical == null) { // case 3 - graph.removeFixed((FixedWithNextNode) node); + graph.removeFixed(fixedWithNext); } else if (canonical instanceof FloatingNode) { // case 4 - graph.replaceFixedWithFloating((FixedWithNextNode) node, (FloatingNode) canonical); + graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical); } else { assert canonical instanceof FixedNode; if (canonical.predecessor() == null) { assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors"; // case 5 - graph.replaceFixedWithFixed((FixedWithNextNode) node, (FixedWithNextNode) canonical); + graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical); } else { assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; // case 6 node.replaceAtUsages(canonical); - graph.removeFixed((FixedWithNextNode) node); + graph.removeFixed(fixedWithNext); } } } @@ -321,7 +327,7 @@ @Override public void addToWorkList(Node node) { - nodeWorkSet.add(node); + nodeWorkSet.addAgain(node); } @Override
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CheckCastEliminationPhase.java Fri Nov 09 13:32:53 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,384 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases.common; - -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.util.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.graph.*; - -public class CheckCastEliminationPhase extends Phase { - - private static final DebugMetric metricInstanceOfRegistered = Debug.metric("InstanceOfRegistered"); - private static final DebugMetric metricNullCheckRegistered = Debug.metric("NullCheckRegistered"); - private static final DebugMetric metricCheckCastRemoved = Debug.metric("CheckCastRemoved"); - private static final DebugMetric metricInstanceOfRemoved = Debug.metric("InstanceOfRemoved"); - private static final DebugMetric metricNullCheckRemoved = Debug.metric("NullCheckRemoved"); - private static final DebugMetric metricNullCheckGuardRemoved = Debug.metric("NullCheckGuardRemoved"); - private static final DebugMetric metricGuardsReplaced = Debug.metric("GuardsReplaced"); - - private StructuredGraph graph; - - @Override - protected void run(StructuredGraph inputGraph) { - graph = inputGraph; - new EliminateCheckCasts(graph.start(), new State()).apply(); - } - - public static class State implements MergeableState<State> { - - private IdentityHashMap<ValueNode, ResolvedJavaType> knownTypes; - private HashSet<ValueNode> knownNotNull; - private HashSet<ValueNode> knownNull; - private IdentityHashMap<BooleanNode, ValueNode> trueConditions; - private IdentityHashMap<BooleanNode, ValueNode> falseConditions; - - public State() { - this.knownTypes = new IdentityHashMap<>(); - this.knownNotNull = new HashSet<>(); - this.knownNull = new HashSet<>(); - this.trueConditions = new IdentityHashMap<>(); - this.falseConditions = new IdentityHashMap<>(); - } - - public State(State other) { - this.knownTypes = new IdentityHashMap<>(other.knownTypes); - this.knownNotNull = new HashSet<>(other.knownNotNull); - this.knownNull = new HashSet<>(other.knownNull); - this.trueConditions = new IdentityHashMap<>(other.trueConditions); - this.falseConditions = new IdentityHashMap<>(other.falseConditions); - } - - @Override - public boolean merge(MergeNode merge, List<State> withStates) { - IdentityHashMap<ValueNode, ResolvedJavaType> newKnownTypes = new IdentityHashMap<>(); - HashSet<ValueNode> newKnownNotNull = new HashSet<>(); - HashSet<ValueNode> newKnownNull = new HashSet<>(); - IdentityHashMap<BooleanNode, ValueNode> newTrueConditions = new IdentityHashMap<>(); - IdentityHashMap<BooleanNode, ValueNode> newFalseConditions = new IdentityHashMap<>(); - - for (Map.Entry<ValueNode, ResolvedJavaType> entry : knownTypes.entrySet()) { - ValueNode node = entry.getKey(); - ResolvedJavaType type = entry.getValue(); - - for (State other : withStates) { - ResolvedJavaType otherType = other.getNodeType(node); - type = widen(type, otherType); - if (type == null) { - break; - } - } - if (type == null && type != node.objectStamp().type()) { - newKnownTypes.put(node, type); - } - } - for (ValueNode node : knownNotNull) { - boolean notNull = true; - for (State other : withStates) { - if (!other.knownNotNull.contains(node)) { - notNull = false; - break; - } - } - if (notNull) { - newKnownNotNull.add(node); - } - } - for (ValueNode node : knownNull) { - boolean nul = true; - for (State other : withStates) { - if (!other.knownNull.contains(node)) { - nul = false; - break; - } - } - if (nul) { - newKnownNull.add(node); - } - } - for (Map.Entry<BooleanNode, ValueNode> entry : trueConditions.entrySet()) { - BooleanNode check = entry.getKey(); - ValueNode guard = entry.getValue(); - - for (State other : withStates) { - ValueNode otherGuard = other.trueConditions.get(check); - if (otherGuard == null) { - guard = null; - break; - } - if (otherGuard != guard) { - guard = merge; - } - } - if (guard != null) { - newTrueConditions.put(check, guard); - } - } - for (Map.Entry<BooleanNode, ValueNode> entry : falseConditions.entrySet()) { - BooleanNode check = entry.getKey(); - ValueNode guard = entry.getValue(); - - for (State other : withStates) { - ValueNode otherGuard = other.falseConditions.get(check); - if (otherGuard == null) { - guard = null; - break; - } - if (otherGuard != guard) { - guard = merge; - } - } - if (guard != null) { - newFalseConditions.put(check, guard); - } - } - - /* - // this piece of code handles phis (merges the types and knownNull/knownNotNull of the values) - if (!(merge instanceof LoopBeginNode)) { - for (PhiNode phi : merge.phis()) { - if (phi.type() == PhiType.Value && phi.kind() == Kind.Object) { - ValueNode firstValue = phi.valueAt(0); - ResolvedJavaType type = getNodeType(firstValue); - boolean notNull = knownNotNull.contains(firstValue); - boolean nul = knownNull.contains(firstValue); - - for (int i = 0; i < withStates.size(); i++) { - State otherState = withStates.get(i); - ValueNode value = phi.valueAt(i + 1); - ResolvedJavaType otherType = otherState.getNodeType(value); - type = widen(type, otherType); - notNull &= otherState.knownNotNull.contains(value); - nul &= otherState.knownNull.contains(value); - } - if (type == null && type != phi.declaredType()) { - newKnownTypes.put(phi, type); - } - if (notNull) { - newKnownNotNull.add(phi); - } - if (nul) { - newKnownNull.add(phi); - } - } - } - } - */ - this.knownTypes = newKnownTypes; - this.knownNotNull = newKnownNotNull; - this.knownNull = newKnownNull; - this.trueConditions = newTrueConditions; - this.falseConditions = newFalseConditions; - return true; - } - - public ResolvedJavaType getNodeType(ValueNode node) { - ResolvedJavaType result = knownTypes.get(node); - return result == null ? node.objectStamp().type() : result; - } - - @Override - public void loopBegin(LoopBeginNode loopBegin) { - } - - @Override - public void loopEnds(LoopBeginNode loopBegin, List<State> loopEndStates) { - } - - @Override - public void afterSplit(FixedNode node) { - } - - @Override - public State clone() { - return new State(this); - } - } - - public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) { - if (a == null || b == null) { - return null; - } else if (a == b) { - return a; - } else { - return a.findLeastCommonAncestor(b); - } - } - - public static ResolvedJavaType tighten(ResolvedJavaType a, ResolvedJavaType b) { - if (a == null) { - return b; - } else if (b == null) { - return a; - } else if (a == b) { - return a; - } else if (a.isSubtypeOf(b)) { - return a; - } else if (b.isSubtypeOf(a)) { - return b; - } else { - return a; - } - } - - public class EliminateCheckCasts extends PostOrderNodeIterator<State> { - private BeginNode lastBegin = null; - - public EliminateCheckCasts(FixedNode start, State initialState) { - super(start, initialState); - } - - @Override - protected void node(FixedNode node) { - if (node instanceof BeginNode) { - BeginNode begin = (BeginNode) node; - lastBegin = begin; - Node pred = node.predecessor(); - if (pred != null && pred instanceof IfNode) { - IfNode ifNode = (IfNode) pred; - if (!(ifNode.condition() instanceof ConstantNode)) { - boolean isTrue = (node == ifNode.trueSuccessor()); - if (isTrue) { - state.trueConditions.put(ifNode.condition(), begin); - } else { - state.falseConditions.put(ifNode.condition(), begin); - } - } - if (ifNode.condition() instanceof InstanceOfNode) { - InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition(); - if ((node == ifNode.trueSuccessor())) { - ValueNode object = instanceOf.object(); - state.knownNotNull.add(object); - state.knownTypes.put(object, tighten(instanceOf.targetClass(), state.getNodeType(object))); - metricInstanceOfRegistered.increment(); - } - } else if (ifNode.condition() instanceof IsNullNode) { - IsNullNode nullCheck = (IsNullNode) ifNode.condition(); - boolean isNull = (node == ifNode.trueSuccessor()); - if (isNull) { - state.knownNull.add(nullCheck.object()); - } else { - state.knownNotNull.add(nullCheck.object()); - } - metricNullCheckRegistered.increment(); - } - } - for (GuardNode guard : begin.guards().snapshot()) { - BooleanNode condition = guard.condition(); - ValueNode existingGuards = guard.negated() ? state.falseConditions.get(condition) : state.trueConditions.get(condition); - if (existingGuards != null) { - guard.replaceAtUsages(existingGuards); - GraphUtil.killWithUnusedFloatingInputs(guard); - metricGuardsReplaced.increment(); - } else { - boolean removeCheck = false; - if (condition instanceof IsNullNode) { - IsNullNode isNull = (IsNullNode) condition; - if (guard.negated() && state.knownNotNull.contains(isNull.object())) { - removeCheck = true; - } else if (!guard.negated() && state.knownNull.contains(isNull.object())) { - removeCheck = true; - } - if (removeCheck) { - metricNullCheckGuardRemoved.increment(); - } - } - if (removeCheck) { - guard.replaceAtUsages(begin); - GraphUtil.killWithUnusedFloatingInputs(guard); - } else { - if (guard.negated()) { - state.falseConditions.put(condition, guard); - } else { - state.trueConditions.put(condition, guard); - } - } - } - } - } else if (node instanceof CheckCastNode) { - CheckCastNode checkCast = (CheckCastNode) node; - ResolvedJavaType type = state.getNodeType(checkCast.object()); - if (checkCast.targetClass() != null && type != null && type.isSubtypeOf(checkCast.targetClass())) { - PiNode piNode; - boolean nonNull = state.knownNotNull.contains(checkCast.object()); - piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, nonNull ? StampFactory.declaredNonNull(type) : StampFactory.declared(type))); - checkCast.replaceAtUsages(piNode); - graph.removeFixed(checkCast); - metricCheckCastRemoved.increment(); - } - } else if (node instanceof IfNode) { - IfNode ifNode = (IfNode) node; - BooleanNode replaceWith = null; - BooleanNode compare = ifNode.condition(); - - if (state.trueConditions.containsKey(compare)) { - replaceWith = ConstantNode.forBoolean(true, graph); - } else if (state.falseConditions.containsKey(compare)) { - replaceWith = ConstantNode.forBoolean(false, graph); - } else { - if (compare instanceof InstanceOfNode) { - InstanceOfNode instanceOf = (InstanceOfNode) compare; - ValueNode object = instanceOf.object(); - if (state.knownNull.contains(object)) { - replaceWith = ConstantNode.forBoolean(false, graph); - } else if (state.knownNotNull.contains(object)) { - ResolvedJavaType type = state.getNodeType(object); - if (type != null && type.isSubtypeOf(instanceOf.targetClass())) { - replaceWith = ConstantNode.forBoolean(true, graph); - } - } - if (replaceWith != null) { - metricInstanceOfRemoved.increment(); - } - } else if (compare instanceof IsNullNode) { - IsNullNode isNull = (IsNullNode) compare; - ValueNode object = isNull.object(); - if (state.knownNull.contains(object)) { - replaceWith = ConstantNode.forBoolean(true, graph); - } else if (state.knownNotNull.contains(object)) { - replaceWith = ConstantNode.forBoolean(false, graph); - } - if (replaceWith != null) { - metricNullCheckRemoved.increment(); - } - } - } - if (replaceWith != null) { - ifNode.setCondition(replaceWith); - if (compare.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(compare); - } - } - } - } - } - -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,384 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.PhiNode.PhiType; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.graph.*; + +public class ConditionalEliminationPhase extends Phase { + + private static final DebugMetric metricInstanceOfRegistered = Debug.metric("InstanceOfRegistered"); + private static final DebugMetric metricNullCheckRegistered = Debug.metric("NullCheckRegistered"); + private static final DebugMetric metricCheckCastRemoved = Debug.metric("CheckCastRemoved"); + private static final DebugMetric metricInstanceOfRemoved = Debug.metric("InstanceOfRemoved"); + private static final DebugMetric metricNullCheckRemoved = Debug.metric("NullCheckRemoved"); + private static final DebugMetric metricNullCheckGuardRemoved = Debug.metric("NullCheckGuardRemoved"); + private static final DebugMetric metricGuardsReplaced = Debug.metric("GuardsReplaced"); + + private StructuredGraph graph; + + @Override + protected void run(StructuredGraph inputGraph) { + graph = inputGraph; + new ConditionalElimination(graph.start(), new State()).apply(); + } + + public static class State implements MergeableState<State> { + + private IdentityHashMap<ValueNode, ResolvedJavaType> knownTypes; + private HashSet<ValueNode> knownNotNull; + private HashSet<ValueNode> knownNull; + private IdentityHashMap<BooleanNode, ValueNode> trueConditions; + private IdentityHashMap<BooleanNode, ValueNode> falseConditions; + + public State() { + this.knownTypes = new IdentityHashMap<>(); + this.knownNotNull = new HashSet<>(); + this.knownNull = new HashSet<>(); + this.trueConditions = new IdentityHashMap<>(); + this.falseConditions = new IdentityHashMap<>(); + } + + public State(State other) { + this.knownTypes = new IdentityHashMap<>(other.knownTypes); + this.knownNotNull = new HashSet<>(other.knownNotNull); + this.knownNull = new HashSet<>(other.knownNull); + this.trueConditions = new IdentityHashMap<>(other.trueConditions); + this.falseConditions = new IdentityHashMap<>(other.falseConditions); + } + + @Override + public boolean merge(MergeNode merge, List<State> withStates) { + IdentityHashMap<ValueNode, ResolvedJavaType> newKnownTypes = new IdentityHashMap<>(); + HashSet<ValueNode> newKnownNotNull = new HashSet<>(); + HashSet<ValueNode> newKnownNull = new HashSet<>(); + IdentityHashMap<BooleanNode, ValueNode> newTrueConditions = new IdentityHashMap<>(); + IdentityHashMap<BooleanNode, ValueNode> newFalseConditions = new IdentityHashMap<>(); + + for (Map.Entry<ValueNode, ResolvedJavaType> entry : knownTypes.entrySet()) { + ValueNode node = entry.getKey(); + ResolvedJavaType type = entry.getValue(); + + for (State other : withStates) { + ResolvedJavaType otherType = other.getNodeType(node); + type = widen(type, otherType); + if (type == null) { + break; + } + } + if (type == null && type != node.objectStamp().type()) { + newKnownTypes.put(node, type); + } + } + for (ValueNode node : knownNotNull) { + boolean notNull = true; + for (State other : withStates) { + if (!other.knownNotNull.contains(node)) { + notNull = false; + break; + } + } + if (notNull) { + newKnownNotNull.add(node); + } + } + for (ValueNode node : knownNull) { + boolean isNull = true; + for (State other : withStates) { + if (!other.knownNull.contains(node)) { + isNull = false; + break; + } + } + if (isNull) { + newKnownNull.add(node); + } + } + for (Map.Entry<BooleanNode, ValueNode> entry : trueConditions.entrySet()) { + BooleanNode check = entry.getKey(); + ValueNode guard = entry.getValue(); + + for (State other : withStates) { + ValueNode otherGuard = other.trueConditions.get(check); + if (otherGuard == null) { + guard = null; + break; + } + if (otherGuard != guard) { + guard = merge; + } + } + if (guard != null) { + newTrueConditions.put(check, guard); + } + } + for (Map.Entry<BooleanNode, ValueNode> entry : falseConditions.entrySet()) { + BooleanNode check = entry.getKey(); + ValueNode guard = entry.getValue(); + + for (State other : withStates) { + ValueNode otherGuard = other.falseConditions.get(check); + if (otherGuard == null) { + guard = null; + break; + } + if (otherGuard != guard) { + guard = merge; + } + } + if (guard != null) { + newFalseConditions.put(check, guard); + } + } + + // this piece of code handles phis (merges the types and knownNull/knownNotNull of the values) + if (!(merge instanceof LoopBeginNode)) { + for (PhiNode phi : merge.phis()) { + if (phi.type() == PhiType.Value && phi.kind() == Kind.Object) { + ValueNode firstValue = phi.valueAt(0); + ResolvedJavaType type = getNodeType(firstValue); + boolean notNull = knownNotNull.contains(firstValue); + boolean isNull = knownNull.contains(firstValue); + + for (int i = 0; i < withStates.size(); i++) { + State otherState = withStates.get(i); + ValueNode value = phi.valueAt(i + 1); + ResolvedJavaType otherType = otherState.getNodeType(value); + type = widen(type, otherType); + notNull &= otherState.knownNotNull.contains(value); + isNull &= otherState.knownNull.contains(value); + } + if (type != null) { + newKnownTypes.put(phi, type); + } + if (notNull) { + newKnownNotNull.add(phi); + } + if (isNull) { + newKnownNull.add(phi); + } + } + } + } + + this.knownTypes = newKnownTypes; + this.knownNotNull = newKnownNotNull; + this.knownNull = newKnownNull; + this.trueConditions = newTrueConditions; + this.falseConditions = newFalseConditions; + return true; + } + + public ResolvedJavaType getNodeType(ValueNode node) { + ResolvedJavaType result = knownTypes.get(node); + return result == null ? node.objectStamp().type() : result; + } + + @Override + public void loopBegin(LoopBeginNode loopBegin) { + } + + @Override + public void loopEnds(LoopBeginNode loopBegin, List<State> loopEndStates) { + } + + @Override + public void afterSplit(FixedNode node) { + } + + @Override + public State clone() { + return new State(this); + } + } + + public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) { + if (a == null || b == null) { + return null; + } else if (a == b) { + return a; + } else { + return a.findLeastCommonAncestor(b); + } + } + + public static ResolvedJavaType tighten(ResolvedJavaType a, ResolvedJavaType b) { + if (a == null) { + return b; + } else if (b == null) { + return a; + } else if (a == b) { + return a; + } else if (a.isSubtypeOf(b)) { + return a; + } else if (b.isSubtypeOf(a)) { + return b; + } else { + return a; + } + } + + public class ConditionalElimination extends PostOrderNodeIterator<State> { + private BeginNode lastBegin = null; + + public ConditionalElimination(FixedNode start, State initialState) { + super(start, initialState); + } + + @Override + protected void node(FixedNode node) { + if (node instanceof BeginNode) { + BeginNode begin = (BeginNode) node; + lastBegin = begin; + Node pred = node.predecessor(); + if (pred != null && pred instanceof IfNode) { + IfNode ifNode = (IfNode) pred; + if (!(ifNode.condition() instanceof ConstantNode)) { + boolean isTrue = (node == ifNode.trueSuccessor()); + if (isTrue) { + state.trueConditions.put(ifNode.condition(), begin); + } else { + state.falseConditions.put(ifNode.condition(), begin); + } + } + if (ifNode.condition() instanceof InstanceOfNode) { + InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition(); + if ((node == ifNode.trueSuccessor())) { + ValueNode object = instanceOf.object(); + state.knownNotNull.add(object); + state.knownTypes.put(object, tighten(instanceOf.type(), state.getNodeType(object))); + metricInstanceOfRegistered.increment(); + } + } else if (ifNode.condition() instanceof IsNullNode) { + IsNullNode nullCheck = (IsNullNode) ifNode.condition(); + boolean isNull = (node == ifNode.trueSuccessor()); + if (isNull) { + state.knownNull.add(nullCheck.object()); + } else { + state.knownNotNull.add(nullCheck.object()); + } + metricNullCheckRegistered.increment(); + } + } + for (GuardNode guard : begin.guards().snapshot()) { + BooleanNode condition = guard.condition(); + ValueNode existingGuards = guard.negated() ? state.falseConditions.get(condition) : state.trueConditions.get(condition); + if (existingGuards != null) { + guard.replaceAtUsages(existingGuards); + GraphUtil.killWithUnusedFloatingInputs(guard); + metricGuardsReplaced.increment(); + } else { + boolean removeCheck = false; + if (condition instanceof IsNullNode) { + IsNullNode isNull = (IsNullNode) condition; + if (guard.negated() && state.knownNotNull.contains(isNull.object())) { + removeCheck = true; + } else if (!guard.negated() && state.knownNull.contains(isNull.object())) { + removeCheck = true; + } + if (removeCheck) { + metricNullCheckGuardRemoved.increment(); + } + } + if (removeCheck) { + guard.replaceAtUsages(begin); + GraphUtil.killWithUnusedFloatingInputs(guard); + } else { + if (guard.negated()) { + state.falseConditions.put(condition, guard); + } else { + state.trueConditions.put(condition, guard); + } + } + } + } + } else if (node instanceof CheckCastNode) { + CheckCastNode checkCast = (CheckCastNode) node; + ResolvedJavaType type = state.getNodeType(checkCast.object()); + if (type != null && type.isSubtypeOf(checkCast.type())) { + PiNode piNode; + boolean nonNull = state.knownNotNull.contains(checkCast.object()); + piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, nonNull ? StampFactory.declaredNonNull(type) : StampFactory.declared(type))); + checkCast.replaceAtUsages(piNode); + graph.removeFixed(checkCast); + metricCheckCastRemoved.increment(); + } + } else if (node instanceof IfNode) { + IfNode ifNode = (IfNode) node; + BooleanNode replaceWith = null; + BooleanNode compare = ifNode.condition(); + + if (state.trueConditions.containsKey(compare)) { + replaceWith = ConstantNode.forBoolean(true, graph); + } else if (state.falseConditions.containsKey(compare)) { + replaceWith = ConstantNode.forBoolean(false, graph); + } else { + if (compare instanceof InstanceOfNode) { + InstanceOfNode instanceOf = (InstanceOfNode) compare; + ValueNode object = instanceOf.object(); + if (state.knownNull.contains(object)) { + replaceWith = ConstantNode.forBoolean(false, graph); + } else if (state.knownNotNull.contains(object)) { + ResolvedJavaType type = state.getNodeType(object); + if (type != null && type.isSubtypeOf(instanceOf.type())) { + replaceWith = ConstantNode.forBoolean(true, graph); + } + } + if (replaceWith != null) { + metricInstanceOfRemoved.increment(); + } + } else if (compare instanceof IsNullNode) { + IsNullNode isNull = (IsNullNode) compare; + ValueNode object = isNull.object(); + if (state.knownNull.contains(object)) { + replaceWith = ConstantNode.forBoolean(true, graph); + } else if (state.knownNotNull.contains(object)) { + replaceWith = ConstantNode.forBoolean(false, graph); + } + if (replaceWith != null) { + metricNullCheckRemoved.increment(); + } + } + } + if (replaceWith != null) { + ifNode.setCondition(replaceWith); + if (compare.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(compare); + } + } + } + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common; + +import java.util.*; +import java.util.Map.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.PhiNode.PhiType; +import com.oracle.graal.phases.*; + + +public class EliminatePartiallyRedundantGuardsPhase extends Phase { + + private static final DebugMetric metricPRGuardsEliminatedAtMerge = Debug.metric("PRGuardsEliminatedAtMerge"); + private static final DebugMetric metricPRGuardsEliminatedAtSplit = Debug.metric("PRGuardsEliminatedAtSplit"); + private static final DebugMetric metricPRGuardsDifferentGraphId = Debug.metric("PRGuardsDifferentGraphId"); + + private final boolean eliminateAtSplit; + private final boolean eliminateAtMerge; + + public EliminatePartiallyRedundantGuardsPhase(boolean eliminateAtSplit, boolean eliminateAtMerge) { + assert eliminateAtMerge || eliminateAtSplit; + this.eliminateAtSplit = eliminateAtSplit; + this.eliminateAtMerge = eliminateAtMerge; + } + + private static class Condition { + final BooleanNode conditionNode; + final boolean negated; + public Condition(BooleanNode conditionNode, boolean negated) { + this.conditionNode = conditionNode; + this.negated = negated; + } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((conditionNode == null) ? 0 : conditionNode.hashCode()); + result = prime * result + (negated ? 1231 : 1237); + return result; + } + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Condition other = (Condition) obj; + if (conditionNode == null) { + if (other.conditionNode != null) { + return false; + } + } else if (!conditionNode.equals(other.conditionNode)) { + return false; + } + if (negated != other.negated) { + return false; + } + return true; + } + } + + @Override + protected void run(StructuredGraph graph) { + boolean hits; + do { + hits = false; + if (eliminateAtMerge) { + for (MergeNode merge : graph.getNodes(MergeNode.class)) { + hits |= eliminateAtMerge(merge); + } + } + if (eliminateAtSplit) { + for (ControlSplitNode controlSplit : graph.getNodes().filter(ControlSplitNode.class)) { + hits |= eliminateAtControlSplit(controlSplit); + } + } + } while(hits); + } + + private static boolean eliminateAtMerge(MergeNode merge) { + if (merge.forwardEndCount() < 2) { + return false; + } + Collection<GuardNode> hits = new LinkedList<>(); + for (GuardNode guard : merge.guards()) { + if (guard.dependencies().size() != 1) { + continue; + } + for (EndNode end : merge.forwardEnds()) { + BeginNode begin = BeginNode.prevBegin(end); + boolean found = false; + for (GuardNode predecessorGuard : begin.guards()) { + if (predecessorGuard.dependencies().size() != 1) { + continue; + } + if (guard.condition() == predecessorGuard.condition() && guard.negated() == predecessorGuard.negated()) { + hits.add(guard); + found = true; + break; + } + } + if (found) { + break; + } + } + } + Graph graph = merge.graph(); + for (GuardNode guard : hits) { + PhiNode phi = graph.add(new PhiNode(PhiType.Guard, merge)); + for (EndNode otherEnd : merge.forwardEnds()) { + phi.addInput(graph.unique(new GuardNode(guard.condition(), BeginNode.prevBegin(otherEnd), guard.reason(), guard.action(), guard.negated(), guard.getLeafGraphId()))); + } + guard.replaceAndDelete(phi); + metricPRGuardsEliminatedAtMerge.increment(); + } + return !hits.isEmpty(); + } + + private static boolean eliminateAtControlSplit(ControlSplitNode controlSplit) { + Map<Condition, Collection<GuardNode>> conditionToGuard = new HashMap<>(); + for (BeginNode begin : controlSplit.blockSuccessors()) { + for (GuardNode guard : begin.guards()) { + if (guard.dependencies().size() != 1) { + continue; + } + Condition condition = new Condition(guard.condition(), guard.negated()); + Collection<GuardNode> guards = conditionToGuard.get(condition); + if (guards == null) { + guards = new LinkedList<>(); + conditionToGuard.put(condition, guards); + } + guards.add(guard); + } + } + + boolean hits = false; + for (Entry<Condition, Collection<GuardNode>> entry : conditionToGuard.entrySet()) { + Collection<GuardNode> guards = entry.getValue(); + if (guards.size() < 2) { + continue; + } + DeoptimizationReason reason = null; + DeoptimizationAction action = DeoptimizationAction.None; + long leafGraphId = -1; + Set<BeginNode> begins = new HashSet<>(3); + for (GuardNode guard : guards) { + BeginNode begin = (BeginNode) guard.dependencies().first(); + begins.add(begin); + if (guard.action().ordinal() > action.ordinal()) { + action = guard.action(); + } + if (reason == null) { + reason = guard.reason(); + } else if (reason != guard.reason()) { + reason = DeoptimizationReason.None; + } + if (leafGraphId == -1) { + leafGraphId = guard.getLeafGraphId(); + } else if (leafGraphId != guard.getLeafGraphId()) { + metricPRGuardsDifferentGraphId.increment(); + leafGraphId = -1; + break; + } + } + if (leafGraphId < 0) { + continue; + } + if (begins.size() == controlSplit.blockSuccessors().count()) { + hits = true; + Condition condition = entry.getKey(); + GuardNode newGuard = controlSplit.graph().unique(new GuardNode(condition.conditionNode, BeginNode.prevBegin(controlSplit), reason, action, condition.negated, leafGraphId)); + for (GuardNode guard : guards) { + guard.replaceAndDelete(newGuard); + metricPRGuardsEliminatedAtSplit.increment(); + } + } + } + return hits; + } +}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Fri Nov 09 13:35:26 2012 +0100 @@ -33,7 +33,6 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.FrameState.InliningIdentifier; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; @@ -807,7 +806,6 @@ * @param receiverNullCheck true if a null check needs to be generated for non-static inlinings, false if no such check is required */ public static void inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) { - InliningIdentifier identifier = new InliningIdentifier(inlineGraph.method(), invoke); NodeInputList<ValueNode> parameters = invoke.callTarget().arguments(); StructuredGraph graph = (StructuredGraph) invoke.node().graph(); @@ -917,7 +915,6 @@ outerFrameState.setDuringCall(true); } frameState.setOuterFrameState(outerFrameState); - frameState.setInliningIdentifier(identifier); } } } @@ -953,7 +950,7 @@ NodeInputList<ValueNode> parameters = callTarget.arguments(); ValueNode firstParam = parameters.size() <= 0 ? null : parameters.get(0); if (!callTarget.isStatic() && firstParam.kind() == Kind.Object && !firstParam.objectStamp().nonNull()) { - graph.addBeforeFixed(invoke.node(), graph.add(new FixedGuardNode(graph.unique(new IsNullNode(firstParam)), DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, true, invoke.leafGraphId()))); + graph.addBeforeFixed(invoke.node(), graph.add(new FixedGuardNode(graph.unique(new IsNullNode(firstParam)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true, invoke.leafGraphId()))); } } }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeCheckCastEliminationPhase.java Fri Nov 09 13:32:53 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases.common; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.Graph.InputChangedListener; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; - - -public class IterativeCheckCastEliminationPhase extends Phase { - private final TargetDescription target; - private final MetaAccessProvider runtime; - private final Assumptions assumptions; - - public IterativeCheckCastEliminationPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) { - this.target = target; - this.runtime = runtime; - this.assumptions = assumptions; - } - - @Override - protected void run(StructuredGraph graph) { - Set<Node> canonicalizationRoots = new HashSet<>(); - CheckCastEliminationPhase eliminate = new CheckCastEliminationPhase(); - Listener listener = new Listener(canonicalizationRoots); - while (true) { - graph.trackInputChange(listener); - eliminate.apply(graph); - graph.stopTrackingInputChange(); - if (canonicalizationRoots.isEmpty()) { - break; - } - new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots, null).apply(graph); - canonicalizationRoots.clear(); - } - } - - private static class Listener implements InputChangedListener { - private final Set<Node> canonicalizationRoots; - public Listener(Set<Node> canonicalizationRoots) { - this.canonicalizationRoots = canonicalizationRoots; - } - @Override - public void inputChanged(Node node) { - canonicalizationRoots.add(node); - } - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.Graph.InputChangedListener; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; + + +public class IterativeConditionalEliminationPhase extends Phase { + private final TargetDescription target; + private final MetaAccessProvider runtime; + private final Assumptions assumptions; + + public IterativeConditionalEliminationPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) { + this.target = target; + this.runtime = runtime; + this.assumptions = assumptions; + } + + @Override + protected void run(StructuredGraph graph) { + Set<Node> canonicalizationRoots = new HashSet<>(); + ConditionalEliminationPhase eliminate = new ConditionalEliminationPhase(); + Listener listener = new Listener(canonicalizationRoots); + while (true) { + graph.trackInputChange(listener); + eliminate.apply(graph); + graph.stopTrackingInputChange(); + if (canonicalizationRoots.isEmpty()) { + break; + } + new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots, null).apply(graph); + canonicalizationRoots.clear(); + } + } + + private static class Listener implements InputChangedListener { + private final Set<Node> canonicalizationRoots; + public Listener(Set<Node> canonicalizationRoots) { + this.canonicalizationRoots = canonicalizationRoots; + } + @Override + public void inputChanged(Node node) { + canonicalizationRoots.add(node); + } + } +}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Fri Nov 09 13:35:26 2012 +0100 @@ -46,10 +46,12 @@ final FixedNode guardAnchor; final NodeBitMap activeGuards; FixedWithNextNode lastFixedNode; + ControlFlowGraph cfg; - public LoweringToolImpl(FixedNode guardAnchor, NodeBitMap activeGuards) { + public LoweringToolImpl(FixedNode guardAnchor, NodeBitMap activeGuards, ControlFlowGraph cfg) { this.guardAnchor = guardAnchor; this.activeGuards = activeGuards; + this.cfg = cfg; } @Override @@ -89,6 +91,11 @@ return newGuard; } + @Override + public Block getBlockFor(Node node) { + return cfg.blockFor(node); + } + public FixedWithNextNode lastFixedNode() { return lastFixedNode; } @@ -164,7 +171,7 @@ private void process(final Block b, final NodeBitMap activeGuards, final FixedNode anchor, SchedulePhase schedule, NodeBitMap processed) { - final LoweringToolImpl loweringTool = new LoweringToolImpl(anchor, activeGuards); + final LoweringToolImpl loweringTool = new LoweringToolImpl(anchor, activeGuards, schedule.getCFG()); // Lower the instructions of this block. List<ScheduledNode> nodes = schedule.nodesFor(b);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Fri Nov 09 13:35:26 2012 +0100 @@ -52,7 +52,6 @@ public static int SmallCompiledCodeSize = 2200; public static boolean LimitInlinedProbability = ____; // WeightBasedInliningPolicy (0) - public static boolean ParseBeforeInlining = ____; public static float InliningSizePenaltyExp = 20; public static float MaximumInlineWeight = 1.25f; public static float InliningSizePenalty = 1; @@ -69,9 +68,11 @@ // escape analysis settings public static boolean PartialEscapeAnalysis = true; + public static int EscapeAnalysisIterations = 2; + public static String EscapeAnalyzeOnly = null; - public static double TailDuplicationProbability = 0.5; - public static int TailDuplicationTrivialSize = 1; + public static double TailDuplicationProbability = 0.5; + public static int TailDuplicationTrivialSize = 1; // absolute probability analysis public static boolean ProbabilityAnalysis = true; @@ -96,9 +97,6 @@ public static int GraphCacheSize = 1000; public static boolean PrintGraphCache = ____; - //rematerialize settings - public static float MinimumUsageProbability = 0.95f; - //loop transform settings TODO (gd) tune public static boolean LoopPeeling = true; public static boolean ReassociateInvariants = true; @@ -120,26 +118,22 @@ public static String PrintFilter = null; - // printing settings - public static boolean PrintLIR = ____; - public static boolean PrintCFGToFile = ____; - // Debug settings: public static boolean Debug = true; public static boolean PerThreadDebugValues = ____; public static boolean SummarizeDebugValues = ____; public static boolean SummarizePerPhase = ____; - public static String Dump = null; - public static String Meter = null; - public static String Time = null; - public static String Log = null; - public static String LogFile = null; - public static String MethodFilter = null; + public static String Dump = null; + public static String Meter = null; + public static String Time = null; + public static String Log = null; + public static String LogFile = null; + public static String MethodFilter = null; public static boolean DumpOnError = ____; // Ideal graph visualizer output settings - public static boolean PrintBinaryGraphs = ____; - public static boolean PrintCFG = true; + public static boolean PrintBinaryGraphs = true; + public static boolean PrintCFG = ____; public static boolean PrintIdealGraphFile = ____; public static String PrintIdealGraphAddress = "127.0.0.1"; public static int PrintIdealGraphPort = 4444; @@ -149,24 +143,16 @@ public static boolean PrintQueue = ____; public static boolean PrintCompilation = ____; public static boolean PrintProfilingInformation = ____; - public static boolean PrintXirTemplates = ____; public static boolean PrintIRWithLIR = ____; - public static boolean PrintAssembly = ____; public static boolean PrintCodeBytes = ____; - public static int PrintAssemblyBytesPerLine = 16; public static boolean PrintBailout = ____; public static int TraceLinearScanLevel = 0; - public static boolean TraceRegisterAllocation = false; public static int TraceLIRGeneratorLevel = 0; public static boolean TraceEscapeAnalysis = ____; public static int TraceBytecodeParserLevel = 0; - public static boolean PrintBailouts = true; public static boolean ExitVMOnBailout = ____; public static boolean ExitVMOnException = true; - // state merging settings - public static boolean AssumeVerifiedBytecode = true; - // Code generator settings public static boolean CheckCastElimination = true; public static boolean CullFrameStates = ____; @@ -180,7 +166,6 @@ static boolean UseTypeCheckHints = true; public static boolean InlineVTableStubs = true; public static boolean AlwaysInlineVTableStubs = ____; - public static boolean GenAssertionCode = ____; public static boolean AlignCallsForPatching = true; public static boolean ResolveClassBeforeStaticInvoke = true; @@ -193,33 +178,23 @@ public static boolean DetailedAsserts = ____; // Runtime settings - public static int ReadPrefetchInstr = 0; public static int StackShadowPages = 2; - // Assembler settings - public static boolean CommentedAssembly = ____; - public static boolean PrintLIRWithAssembly = ____; - public static boolean SupportJsrBytecodes = true; public static boolean OptAssumptions = true; public static boolean OptReadElimination = true; - public static boolean OptGVN = true; public static boolean OptCanonicalizer = true; - public static boolean ScheduleOutOfLoops = true; + public static boolean OptScheduleOutOfLoops = true; public static boolean OptReorderLoops = true; public static boolean OptEliminateGuards = true; public static boolean OptImplicitNullChecks = true; public static boolean OptLivenessAnalysis = true; public static boolean OptLoopTransform = true; public static boolean OptSafepointElimination = true; - public static boolean FloatingReads = true; + public static boolean OptFloatingReads = true; public static boolean OptTailDuplication = true; - - /** - * Prints all the available GraalOptions. - */ - public static boolean PrintFlags = false; + public static boolean OptEliminatePartiallyRedundantGuards = true; /** * Counts the various paths taken through snippets. @@ -247,11 +222,10 @@ /** * @see #CheckcastMaxHints */ - public static int InstanceOfMaxHints = 1; + public static int InstanceOfMaxHints = 2; static { // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this) assert (DetailedAsserts = true) == true; - assert (CommentedAssembly = true) == true; } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,185 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.graph; + +import java.util.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; + +public final class ReentrantBlockIterator { + + public abstract static class MergeableBlockState<T> { + + public abstract T cloneState(); + } + + public static class LoopInfo<T extends MergeableBlockState<T>> { + + public final List<T> endStates = new ArrayList<>(); + public final List<T> exitStates = new ArrayList<>(); + } + + public abstract static class BlockIteratorClosure<T extends MergeableBlockState<T>> { + + protected abstract void processBlock(Block block, T currentState); + + protected abstract T merge(MergeNode merge, List<T> states); + + protected abstract T afterSplit(FixedNode node, T oldState); + + protected abstract List<T> processLoop(Loop loop, T initialState); + } + + private ReentrantBlockIterator() { + // no instances allowed + } + + public static <T extends MergeableBlockState<T>> LoopInfo<T> processLoop(BlockIteratorClosure<T> closure, Loop loop, T initialState) { + IdentityHashMap<FixedNode, T> blockEndStates = apply(closure, loop.header, initialState, new HashSet<>(loop.blocks)); + + LoopInfo<T> info = new LoopInfo<>(); + List<Block> predecessors = loop.header.getPredecessors(); + for (int i = 1; i < predecessors.size(); i++) { + info.endStates.add(blockEndStates.get(predecessors.get(i).getEndNode())); + } + for (Block loopExit : loop.exits) { + assert loopExit.getPredecessors().size() == 1; + T exitState = blockEndStates.get(loopExit.getPredecessors().get(0).getEndNode()); + assert exitState != null; + info.exitStates.add(exitState); + } + return info; + } + + public static <T extends MergeableBlockState<T>> IdentityHashMap<FixedNode, T> apply(BlockIteratorClosure<T> closure, Block start, T initialState, Set<Block> boundary) { + Deque<Block> blockQueue = new ArrayDeque<>(); + IdentityHashMap<FixedNode, T> blockEndStates = new IdentityHashMap<>(); + + T state = initialState; + Block current = start; + + do { + if (boundary == null || boundary.contains(current)) { + closure.processBlock(current, state); + + if (current.getSuccessors().isEmpty()) { + // nothing to do... + } else if (current.getSuccessors().size() == 1) { + Block successor = current.getSuccessors().get(0); + if (successor.isLoopHeader()) { + if (current.isLoopEnd()) { + // nothing to do... loop ends only lead to loop begins we've already visited + blockEndStates.put(current.getEndNode(), state); + } else { + // recurse into the loop + Loop loop = successor.getLoop(); + LoopBeginNode loopBegin = loop.loopBegin(); + assert successor.getBeginNode() == loopBegin; + + List<T> exitStates = closure.processLoop(loop, state); + + int i = 0; + assert loop.exits.size() == exitStates.size(); + for (Block exit : loop.exits) { + blockEndStates.put(exit.getPredecessors().get(0).getEndNode(), exitStates.get(i++)); + blockQueue.addFirst(exit); + } + } + } else { + if (successor.getBeginNode() instanceof LoopExitNode) { + assert successor.getPredecessors().size() == 1; + blockEndStates.put(current.getEndNode(), state); + current = successor; + continue; + } else { + if (current.getEndNode() instanceof EndNode) { + assert successor.getPredecessors().size() > 1 : "invalid block schedule at " + successor.getBeginNode(); + EndNode end = (EndNode) current.getEndNode(); + + // add the end node and see if the merge is ready for processing + assert !blockEndStates.containsKey(end); + blockEndStates.put(end, state); + MergeNode merge = end.merge(); + boolean endsVisited = true; + for (int i = 0; i < merge.forwardEndCount(); i++) { + if (!blockEndStates.containsKey(merge.forwardEndAt(i))) { + endsVisited = false; + break; + } + } + if (endsVisited) { + blockQueue.addFirst(successor); + } + } else { + assert successor.getPredecessors().size() == 1 : "invalid block schedule at " + successor.getBeginNode(); + current = successor; + continue; + } + } + } + } else { + assert current.getSuccessors().size() > 1; + blockEndStates.put(current.getEndNode(), state); + for (Block block : current.getSuccessors()) { + blockQueue.addFirst(block); + } + } + } + + // get next queued block + if (blockQueue.isEmpty()) { + current = null; + } else { + int maxIterations = blockQueue.size(); + while (maxIterations-- > 0) { + current = blockQueue.removeFirst(); + if (current.getPredecessors().size() > 1) { + MergeNode merge = (MergeNode) current.getBeginNode(); + ArrayList<T> states = new ArrayList<>(merge.forwardEndCount()); + for (int i = 0; i < merge.forwardEndCount(); i++) { + T other = blockEndStates.get(merge.forwardEndAt(i)); + assert other != null; + states.add(other); + } + state = closure.merge(merge, states); + if (state != null) { + break; + } else { + blockQueue.addLast(current); + current = null; + } + } else { + assert current.getPredecessors().size() == 1; + assert current.getBeginNode().predecessor() != null; + if (boundary == null || boundary.contains(current)) { + state = closure.afterSplit(current.getBeginNode(), blockEndStates.get(current.getBeginNode().predecessor())); + break; + } + } + } + } + } while (current != null); + return blockEndStates; + } +}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Fri Nov 09 13:35:26 2012 +0100 @@ -127,7 +127,7 @@ Block block; if (latestBlock == null) { block = earliestBlock(node); - } else if (GraalOptions.ScheduleOutOfLoops && !(node instanceof VirtualObjectNode)) { + } else if (GraalOptions.OptScheduleOutOfLoops && !(node instanceof VirtualObjectNode)) { Block earliestBlock = earliestBlock(node); block = scheduleOutOfLoops(node, latestBlock, earliestBlock); assert earliestBlock.dominates(block) : "Graph can not be scheduled : inconsistent for " + node + " (" + earliestBlock + " needs to dominate " + block + ")";
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java Fri Nov 09 13:35:26 2012 +0100 @@ -117,8 +117,9 @@ if (registerRefMap != null) { sb.append("reg-ref-map:"); + Register[] registers = arch.getRegisters(); for (int reg = registerRefMap.nextSetBit(0); reg >= 0; reg = registerRefMap.nextSetBit(reg + 1)) { - sb.append(' ').append(arch == null ? "r" + reg : arch.registers[reg]); + sb.append(' ').append(arch == null ? "r" + reg : registers[reg]); } sb.append("\n"); }
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/CheckCastTest.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/CheckCastTest.java Fri Nov 09 13:35:26 2012 +0100 @@ -34,27 +34,13 @@ */ public class CheckCastTest extends TypeCheckTest { - /** - * Enables making the target type "unknown" at compile time. - */ - boolean unknown; - @Override protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first(); if (ccn != null) { - ResolvedJavaType targetClass = unknown ? null : ccn.targetClass(); - CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.targetClassInstruction(), targetClass, ccn.object(), profile)); + CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.type(), ccn.object(), profile)); graph.replaceFixedWithFixed(ccn, ccnNew); } - unknown = false; - } - - @Override - protected void test(String name, JavaTypeProfile profile, Object... args) { - super.test(name, profile, args); - unknown = true; - super.test(name, profile, args); } @Test @@ -113,12 +99,12 @@ @Test public void test8() { - test("arrayStore", profile(), new Object[100], "111"); + test("arrayStore", new Object[100], "111"); } @Test public void test8_1() { - test("arrayFill", profile(), new Object[100], "111"); + test("arrayFill", new Object[100], "111"); } public static Number asNumber(Object o) { @@ -197,6 +183,6 @@ @Test public void test10() { Object o = new Depth13[3][]; - test("asDepth12Arr", profile(), o); + test("asDepth12Arr", o); } }
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InstanceOfTest.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InstanceOfTest.java Fri Nov 09 13:35:26 2012 +0100 @@ -26,12 +26,17 @@ import org.junit.*; +import com.oracle.graal.api.code.CompilationResult.Call; +import com.oracle.graal.api.code.CompilationResult.Mark; +import com.oracle.graal.api.code.CompilationResult.Site; import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; -import com.oracle.graal.snippets.CheckCastTest.*; +import com.oracle.graal.snippets.CheckCastTest.Depth12; +import com.oracle.graal.snippets.CheckCastTest.Depth13; +import com.oracle.graal.snippets.CheckCastTest.Depth14; /** * Tests the implementation of instanceof, allowing profiling information to @@ -48,7 +53,7 @@ protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first(); if (ion != null) { - InstanceOfNode ionNew = graph.add(new InstanceOfNode(ion.targetClassInstruction(), ion.targetClass(), ion.object(), profile)); + InstanceOfNode ionNew = graph.add(new InstanceOfNode(ion.type(), ion.object(), profile)); graph.replaceFloating(ion, ionNew); } } @@ -196,15 +201,12 @@ return -1; } - public static int isThrowableInt(Object o) { + int result = o instanceof Throwable ? 4 : 5; if (o instanceof Throwable) { - return 1; + return id(4); } - if (o instanceof Throwable) { - return 2; - } - return 0; + return result; } public static boolean isMap(Object o) { @@ -213,9 +215,9 @@ public static int isMapInt(Object o) { if (o instanceof Map) { - return 1; + return id(1); } - return 0; + return id(0); } public static boolean isDepth12(Object o) { @@ -228,4 +230,98 @@ } return id(0); } + + abstract static class MySite { + final int offset; + MySite(int offset) { + this.offset = offset; + } + } + + static class MyMark extends MySite { + MyMark(int offset) { + super(offset); + } + } + + abstract static class MySafepoint extends MySite { + MySafepoint(int offset) { + super(offset); + } + } + + static class MyCall extends MySafepoint { + MyCall(int offset) { + super(offset); + } + } + + @Test + public void test9() { + MyCall callAt63 = new MyCall(63); + MyMark markAt63 = new MyMark(63); + test("compareMySites", callAt63, callAt63); + test("compareMySites", callAt63, markAt63); + test("compareMySites", markAt63, callAt63); + test("compareMySites", markAt63, markAt63); + } + + public static int compareMySites(MySite s1, MySite s2) { + if (s1.offset == s2.offset && (s1 instanceof MyMark ^ s2 instanceof MyMark)) { + return s1 instanceof MyMark ? -1 : 1; + } + return s1.offset - s2.offset; + } + + @Test + public void test10() { + Mark[] noMarks = {}; + Call callAt63 = new Call("ignore", 63, 5, true, null); + Mark markAt63 = new Mark(63, "1", noMarks); + test("compareSites", callAt63, callAt63); + test("compareSites", callAt63, markAt63); + test("compareSites", markAt63, callAt63); + test("compareSites", markAt63, markAt63); + } + + public static int compareSites(Site s1, Site s2) { + if (s1.pcOffset == s2.pcOffset && (s1 instanceof Mark ^ s2 instanceof Mark)) { + return s1 instanceof Mark ? -1 : 1; + } + return s1.pcOffset - s2.pcOffset; + } + + /** + * This test exists to show the kind of pattern that is be optimizable by + * {@code removeIntermediateMaterialization()} in {@link IfNode}. + * <p> + * The test exists in this source file as the transformation was originally motivated by the need to + * remove use of special JumpNodes in the {@code InstanceOfSnippets}. + */ + @Test + public void test_removeIntermediateMaterialization() { + List<String> list = Arrays.asList("1", "2", "3", "4"); + test("removeIntermediateMaterialization", profile(), list, "2", "yes", "no"); + test("removeIntermediateMaterialization", profile(), list, null, "yes", "no"); + test("removeIntermediateMaterialization", profile(), null, "2", "yes", "no"); + } + + public static String removeIntermediateMaterialization(List<Object> list, Object e, String a, String b) { + boolean test; + if (list == null || e == null) { + test = false; + } else { + test = false; + for (Object i : list) { + if (i.equals(e)) { + test = true; + break; + } + } + } + if (test) { + return a; + } + return b; + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.snippets; + +import static com.oracle.graal.nodes.MaterializeNode.*; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.snippets.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.snippets.SnippetTemplate.Arguments; +import com.oracle.graal.snippets.SnippetTemplate.Key; +import com.oracle.graal.snippets.SnippetTemplate.UsageReplacer; + + +/** + * Helper class for lowering {@link InstanceOfNode}s with snippets. The majority of the + * complexity in such a lowering derives from the fact that {@link InstanceOfNode} + * is a floating node. A snippet used to lower an {@link InstanceOfNode} will almost always + * incorporate control flow and replacing a floating node with control flow is not trivial. + * <p> + * The mechanism implemented in this class ensures that the graph for an instanceof snippet + * is instantiated once per {@link InstanceOfNode} being lowered. The result produced the graph + * is then re-used by all usages of the node. Additionally, if there is a single usage that + * is an {@link IfNode}, the control flow in the snippet is connected directly to the true + * and false successors of the {@link IfNode}. This avoids materializating the instanceof + * test as a boolean which is then retested by the {@link IfNode}. + */ +public abstract class InstanceOfSnippetsTemplates<T extends SnippetsInterface> extends AbstractTemplates<T> { + + public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Class<T> snippetsClass) { + super(runtime, snippetsClass); + } + + /** + * The key and arguments used to retrieve and instantiate an instanceof snippet template. + */ + public static class KeyAndArguments { + public final Key key; + public final Arguments arguments; + public KeyAndArguments(Key key, Arguments arguments) { + this.key = key; + this.arguments = arguments; + } + + } + + /** + * Gets the key and arguments used to retrieve and instantiate an instanceof snippet template. + */ + protected abstract KeyAndArguments getKeyAndArguments(InstanceOfUsageReplacer replacer, LoweringTool tool); + + public void lower(InstanceOfNode instanceOf, LoweringTool tool) { + List<Node> usages = instanceOf.usages().snapshot(); + int nUsages = usages.size(); + + Instantiation instantiation = new Instantiation(); + for (Node usage : usages) { + final StructuredGraph graph = (StructuredGraph) usage.graph(); + + InstanceOfUsageReplacer replacer = createReplacer(instanceOf, tool, nUsages, instantiation, usage, graph); + + if (instantiation.isInitialized()) { + // No need to re-instantiate the snippet - just re-use its result + replacer.replaceUsingInstantiation(); + } else { + KeyAndArguments keyAndArguments = getKeyAndArguments(replacer, tool); + SnippetTemplate template = cache.get(keyAndArguments.key); + template.instantiate(runtime, instanceOf, replacer, tool.lastFixedNode(), keyAndArguments.arguments); + } + } + + assert instanceOf.usages().isEmpty(); + if (!instanceOf.isDeleted()) { + GraphUtil.killWithUnusedFloatingInputs(instanceOf); + } + } + + /** + * Gets the specific replacer object used to replace the usage of an instanceof node + * with the result of an instantiated instanceof snippet. + */ + protected InstanceOfUsageReplacer createReplacer(InstanceOfNode instanceOf, LoweringTool tool, int nUsages, Instantiation instantiation, Node usage, final StructuredGraph graph) { + InstanceOfUsageReplacer replacer; + if (usage instanceof IfNode) { + replacer = new IfUsageReplacer(instantiation, ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph), instanceOf, (IfNode) usage, nUsages == 1, tool); + } else { + assert usage instanceof ConditionalNode : "unexpected usage of " + instanceOf + ": " + usage; + ConditionalNode c = (ConditionalNode) usage; + replacer = new ConditionalUsageReplacer(instantiation, c.trueValue(), c.falseValue(), instanceOf, c); + } + return replacer; + } + + /** + * The result of an instantiating an instanceof snippet. + * This enables a snippet instantiation to be re-used which reduces compile time and produces better code. + */ + public static final class Instantiation { + private PhiNode result; + private CompareNode condition; + private ValueNode trueValue; + private ValueNode falseValue; + + /** + * Determines if the instantiation has occurred. + */ + boolean isInitialized() { + return result != null; + } + + void initialize(PhiNode phi, ValueNode t, ValueNode f) { + assert !isInitialized(); + this.result = phi; + this.trueValue = t; + this.falseValue = f; + } + + /** + * Gets the result of this instantiation as a condition. + * + * @param testValue the returned condition is true if the result is equal to this value + */ + CompareNode asCondition(ValueNode testValue) { + assert isInitialized(); + if (condition == null || condition.y() != testValue) { + // Re-use previously generated condition if the trueValue for the test is the same + condition = createCompareNode(Condition.EQ, result, testValue); + } + return condition; + } + + /** + * Gets the result of the instantiation as a materialized value. + * + * @param t the true value for the materialization + * @param f the false value for the materialization + */ + ValueNode asMaterialization(ValueNode t, ValueNode f) { + assert isInitialized(); + if (t == this.trueValue && f == this.falseValue) { + // Can simply use the phi result if the same materialized values are expected. + return result; + } else { + return MaterializeNode.create(asCondition(trueValue), t, f); + } + } + } + + /** + * Replaces a usage of an {@link InstanceOfNode}. + */ + public abstract static class InstanceOfUsageReplacer implements UsageReplacer { + public final Instantiation instantiation; + public final InstanceOfNode instanceOf; + public final ValueNode trueValue; + public final ValueNode falseValue; + + public InstanceOfUsageReplacer(Instantiation instantiation, InstanceOfNode instanceOf, ValueNode trueValue, ValueNode falseValue) { + this.instantiation = instantiation; + this.instanceOf = instanceOf; + this.trueValue = trueValue; + this.falseValue = falseValue; + } + + /** + * Does the replacement based on a previously snippet instantiation. + */ + public abstract void replaceUsingInstantiation(); + } + + /** + * Replaces an {@link IfNode} usage of an {@link InstanceOfNode}. + */ + public static class IfUsageReplacer extends InstanceOfUsageReplacer { + + private final boolean solitaryUsage; + private final IfNode usage; + private final boolean sameBlock; + + public IfUsageReplacer(Instantiation instantiation, ValueNode trueValue, ValueNode falseValue, InstanceOfNode instanceOf, IfNode usage, boolean solitaryUsage, LoweringTool tool) { + super(instantiation, instanceOf, trueValue, falseValue); + this.sameBlock = tool.getBlockFor(usage) == tool.getBlockFor(instanceOf); + this.solitaryUsage = solitaryUsage; + this.usage = usage; + } + + @Override + public void replaceUsingInstantiation() { + usage.replaceFirstInput(instanceOf, instantiation.asCondition(trueValue)); + } + + @Override + public void replace(ValueNode oldNode, ValueNode newNode) { + assert newNode instanceof PhiNode; + assert oldNode == instanceOf; + if (sameBlock && solitaryUsage) { + removeIntermediateMaterialization(newNode); + } else { + newNode.inferStamp(); + instantiation.initialize((PhiNode) newNode, trueValue, falseValue); + usage.replaceFirstInput(oldNode, instantiation.asCondition(trueValue)); + } + } + + /** + * Directly wires the incoming edges of the merge at the end of the snippet to + * the outgoing edges of the IfNode that uses the materialized result. + */ + private void removeIntermediateMaterialization(ValueNode newNode) { + IfNode ifNode = usage; + PhiNode phi = (PhiNode) newNode; + MergeNode merge = phi.merge(); + assert merge.stateAfter() == null; + + List<EndNode> mergePredecessors = merge.cfgPredecessors().snapshot(); + assert phi.valueCount() == mergePredecessors.size(); + + List<EndNode> falseEnds = new ArrayList<>(mergePredecessors.size()); + List<EndNode> trueEnds = new ArrayList<>(mergePredecessors.size()); + + int endIndex = 0; + for (EndNode end : mergePredecessors) { + ValueNode endValue = phi.valueAt(endIndex++); + if (endValue == trueValue) { + trueEnds.add(end); + } else { + assert endValue == falseValue; + falseEnds.add(end); + } + } + + BeginNode trueSuccessor = ifNode.trueSuccessor(); + BeginNode falseSuccessor = ifNode.falseSuccessor(); + ifNode.setTrueSuccessor(null); + ifNode.setFalseSuccessor(null); + + connectEnds(merge, trueEnds, trueSuccessor); + connectEnds(merge, falseEnds, falseSuccessor); + + GraphUtil.killCFG(merge); + GraphUtil.killCFG(ifNode); + + assert !merge.isAlive() : merge; + assert !phi.isAlive() : phi; + } + + private static void connectEnds(MergeNode merge, List<EndNode> ends, BeginNode successor) { + if (ends.size() == 1) { + EndNode end = ends.get(0); + ((FixedWithNextNode) end.predecessor()).setNext(successor); + merge.removeEnd(end); + GraphUtil.killCFG(end); + } else { + assert ends.size() > 1; + MergeNode newMerge = merge.graph().add(new MergeNode()); + + for (EndNode end : ends) { + newMerge.addForwardEnd(end); + } + newMerge.setNext(successor); + } + } + } + + /** + * Replaces a {@link ConditionalNode} usage of an {@link InstanceOfNode}. + */ + public static class ConditionalUsageReplacer extends InstanceOfUsageReplacer { + + public final ConditionalNode usage; + + public ConditionalUsageReplacer(Instantiation instantiation, ValueNode trueValue, ValueNode falseValue, InstanceOfNode instanceOf, ConditionalNode usage) { + super(instantiation, instanceOf, trueValue, falseValue); + this.usage = usage; + } + + @Override + public void replaceUsingInstantiation() { + ValueNode newValue = instantiation.asMaterialization(trueValue, falseValue); + usage.replaceAtUsages(newValue); + usage.clearInputs(); + assert usage.usages().isEmpty(); + GraphUtil.killWithUnusedFloatingInputs(usage); + } + + @Override + public void replace(ValueNode oldNode, ValueNode newNode) { + assert newNode instanceof PhiNode; + assert oldNode == instanceOf; + newNode.inferStamp(); + instantiation.initialize((PhiNode) newNode, trueValue, falseValue); + usage.replaceAtUsages(newNode); + usage.clearInputs(); + assert usage.usages().isEmpty(); + GraphUtil.killWithUnusedFloatingInputs(usage); + } + } +}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Fri Nov 09 13:35:26 2012 +0100 @@ -353,31 +353,6 @@ ReturnNode retNode = null; StartNode entryPointNode = snippet.start(); - Map<Integer, JumpNode[]> jumpsMap = new HashMap<>(); - for (JumpNode jump : snippet.getNodes().filter(JumpNode.class).snapshot()) { - FixedNode next = jump.next(); - - // Remove the nodes after the jump - jump.setNext(null); - GraphUtil.killCFG(next); - JumpNode[] jumpsForIndex = jumpsMap.get(jump.successorIndex()); - if (jumpsForIndex == null) { - jumpsMap.put(jump.successorIndex(), new JumpNode[] {jump}); - } else { - jumpsForIndex = Arrays.copyOf(jumpsForIndex, jumpsForIndex.length + 1); - jumpsForIndex[jumpsForIndex.length - 1] = jump; - jumpsMap.put(jump.successorIndex(), jumpsForIndex); - } - } - - this.jumps = new JumpNode[jumpsMap.size()][]; - for (Map.Entry<Integer, JumpNode[]> e : jumpsMap.entrySet()) { - int successorIndex = e.getKey(); - assert successorIndex >= 0 && successorIndex < this.jumps.length; - assert this.jumps[successorIndex] == null; - this.jumps[successorIndex] = e.getValue(); - } - new DeadCodeEliminationPhase().apply(snippetCopy); nodes = new ArrayList<>(snippet.getNodeCount()); @@ -387,7 +362,6 @@ } else { nodes.add(node); if (node instanceof ReturnNode) { - assert this.jumps.length == 0 : "snippet with Jump node(s) cannot have a return node"; retNode = (ReturnNode) node; } } @@ -460,12 +434,6 @@ private final ArrayList<Node> nodes; /** - * The {@link JumpNode}s in the snippet, indexed by {@linkplain ControlSplitNode#blockSuccessor(int) successor} indexes. - * There may be more than one jump per successor index which explains why this is a 2-dimensional array. - */ - private final JumpNode[][] jumps; - - /** * Gets the instantiation-time bindings to this template's parameters. * * @return the map that will be used to bind arguments to parameters when inlining this template @@ -588,14 +556,16 @@ replacer.replace(replacee, returnValue); Node returnDuplicate = duplicates.get(returnNode); - returnDuplicate.clearInputs(); - returnDuplicate.replaceAndDelete(next); + if (returnDuplicate.isAlive()) { + returnDuplicate.clearInputs(); + returnDuplicate.replaceAndDelete(next); + } } // Remove the replacee from its graph replacee.clearInputs(); replacee.replaceAtUsages(null); - GraphUtil.killCFG(replacee); + GraphUtil.killCFG(replacee); Debug.dump(replaceeGraph, "After lowering %s with %s", replacee, this); return duplicates; @@ -653,74 +623,14 @@ replacer.replace(replacee, returnValue); Node returnDuplicate = duplicates.get(returnNode); - returnDuplicate.clearInputs(); - returnDuplicate.replaceAndDelete(next); + if (returnDuplicate.isAlive()) { + returnDuplicate.clearInputs(); + returnDuplicate.replaceAndDelete(next); + } Debug.dump(replaceeGraph, "After lowering %s with %s", replacee, this); } - /** - * Replaces a given floating node that is an input to a {@link ControlSplitNode} with this specialized snippet. - * The {@linkplain JumpNode jumps} in the snippet are connected to the successors of the control split node. - * - * @param replacee the node that will be replaced - * @param controlSplitNode the node replaced by this wheCFG of the snippet is inserted after this node - * @param args the arguments to be bound to the flattened positional parameters of the snippet - */ - public void instantiate(MetaAccessProvider runtime, - FloatingNode replacee, - ControlSplitNode controlSplitNode, - SnippetTemplate.Arguments args) { - - // Inline the snippet nodes, replacing parameters with the given args in the process - String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}"; - StructuredGraph snippetCopy = new StructuredGraph(name, snippet.method()); - StartNode entryPointNode = snippet.start(); - FixedNode firstCFGNode = entryPointNode.next(); - StructuredGraph replaceeGraph = (StructuredGraph) replacee.graph(); - IdentityHashMap<Node, Node> replacements = bind(replaceeGraph, runtime, args); - Map<Node, Node> duplicates = replaceeGraph.addDuplicates(nodes, replacements); - Debug.dump(replaceeGraph, "After inlining snippet %s", snippetCopy.method()); - - - int successorIndex = 0; - for (JumpNode[] jumpsForIndex : jumps) { - fixEdge(controlSplitNode, jumpsForIndex, successorIndex++, duplicates); - } - - FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); - controlSplitNode.replaceAtPredecessor(firstCFGNodeDuplicate); - controlSplitNode.replaceAtUsages(null); - - assert sideEffectNode == null; - assert stampNode == null; - assert returnNode == null : replaceeGraph; - GraphUtil.killCFG(controlSplitNode); - - Debug.dump(replaceeGraph, "After lowering %s with %s", replacee, this); - } - - private static void fixEdge(ControlSplitNode splitAnchor, JumpNode[] jumpsForIndex, int successorIndex, Map<Node, Node> duplicates) { - BeginNode blockSuccessor = splitAnchor.blockSuccessor(successorIndex); - splitAnchor.setBlockSuccessor(successorIndex, null); - if (jumpsForIndex.length == 1) { - JumpNode jump = (JumpNode) duplicates.get(jumpsForIndex[0]); - jump.replaceAtPredecessor(blockSuccessor); - GraphUtil.killCFG(jump); - } else { - StructuredGraph graph = (StructuredGraph) splitAnchor.graph(); - MergeNode merge = graph.add(new MergeNode()); - for (int i = 0; i < jumpsForIndex.length; i++) { - EndNode end = graph.add(new EndNode()); - JumpNode jump = (JumpNode) duplicates.get(jumpsForIndex[i]); - jump.replaceAtPredecessor(end); - merge.addForwardEnd(end); - GraphUtil.killCFG(jump); - } - merge.setNext(blockSuccessor); - } - } - @Override public String toString() { StringBuilder buf = new StringBuilder(snippet.toString()).append('(');
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java Fri Nov 09 13:35:26 2012 +0100 @@ -54,7 +54,7 @@ verify(!isWord(node) || ((StoreFieldNode) usage).object() != node, node, usage, "cannot store to word value"); } else if (usage instanceof CheckCastNode) { verify(!isWord(node), node, usage, "word value cannot be cast"); - verify(!isWord(((CheckCastNode) usage).targetClass()), node, usage, "cannot cast to word value"); + verify(!isWord(((CheckCastNode) usage).type()), node, usage, "cannot cast to word value"); } else if (usage instanceof LoadIndexedNode) { verify(!isWord(node) || ((LoadIndexedNode) usage).array() != node, node, usage, "cannot load from word value"); verify(!isWord(node) || ((LoadIndexedNode) usage).index() != node, node, usage, "cannot use word value as index");
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/JumpNode.java Fri Nov 09 13:32:53 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.snippets.nodes; - -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; - -/** - * Delimits a control flow path in a snippet that will be connected to a - * {@link ControlSplitNode} successor upon snippet instantiation. - * This node can only appear in snippets with a void return type. - */ -public class JumpNode extends FixedWithNextNode { - - /** - * Index of {@link ControlSplitNode} successor to which this label will be connected. - */ - private final int successorIndex; - - public JumpNode(int successorIndex) { - super(StampFactory.forVoid()); - this.successorIndex = successorIndex; - } - - public int successorIndex() { - return successorIndex; - } - - @Override - public String toString(Verbosity verbosity) { - if (verbosity == Verbosity.Name) { - return super.toString(Verbosity.Name) + "{" + successorIndex() + "}"; - } else { - return super.toString(verbosity); - } - } - - /** - * There must be a return statement immediately following a call to this method. - * - * @param successorIndex e.g. {@link IfNode#TRUE_EDGE} - */ - @NodeIntrinsic - public static native void jump(@ConstantNodeParameter int successorIndex); -}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java Fri Nov 09 13:35:26 2012 +0100 @@ -35,12 +35,12 @@ @Input private final NodeInputList<ValueNode> values; @Input private final VirtualObjectNode virtualObject; - private final boolean locked; + private final int lockCount; - public MaterializeObjectNode(VirtualObjectNode virtualObject, boolean locked) { + public MaterializeObjectNode(VirtualObjectNode virtualObject, int lockCount) { super(StampFactory.exactNonNull(virtualObject.type())); this.virtualObject = virtualObject; - this.locked = locked; + this.lockCount = lockCount; this.values = new NodeInputList<>(this, virtualObject.entryCount()); } @@ -54,7 +54,7 @@ if (virtualObject instanceof VirtualInstanceNode) { VirtualInstanceNode virtual = (VirtualInstanceNode) virtualObject; - NewInstanceNode newInstance = graph.add(new NewInstanceNode(virtual.type(), false, locked)); + NewInstanceNode newInstance = graph.add(new NewInstanceNode(virtual.type(), false, lockCount > 0)); this.replaceAtUsages(newInstance); graph.addAfterFixed(this, newInstance); @@ -73,9 +73,9 @@ ResolvedJavaType element = virtual.componentType(); NewArrayNode newArray; if (element.getKind() == Kind.Object) { - newArray = graph.add(new NewObjectArrayNode(element, ConstantNode.forInt(virtual.entryCount(), graph), false, locked)); + newArray = graph.add(new NewObjectArrayNode(element, ConstantNode.forInt(virtual.entryCount(), graph), false, lockCount > 0)); } else { - newArray = graph.add(new NewPrimitiveArrayNode(element, ConstantNode.forInt(virtual.entryCount(), graph), false, locked)); + newArray = graph.add(new NewPrimitiveArrayNode(element, ConstantNode.forInt(virtual.entryCount(), graph), false, lockCount > 0)); } this.replaceAtUsages(newArray); graph.addAfterFixed(this, newArray); @@ -102,6 +102,9 @@ @Override public EscapeOp getEscapeOp() { + if (!shouldRevirtualize(this)) { + return null; + } return new EscapeOp() { @Override @@ -110,9 +113,51 @@ } @Override - public VirtualObjectNode virtualObject(int virtualId) { + public VirtualObjectNode virtualObject(long virtualId) { return virtualObject; } + + @Override + public int lockCount() { + return lockCount; + } }; } + + private boolean shouldRevirtualize(MaterializeObjectNode materializeObjectNode) { + FixedWithNextNode end = materializeObjectNode; + do { + Node next = end.next(); + if (next instanceof MaterializeObjectNode) { + if (!shouldRevirtualize((MaterializeObjectNode) next)) { + return false; + } + end = (FixedWithNextNode) next; + } else if (next instanceof CyclicMaterializeStoreNode) { + end = (FixedWithNextNode) next; + } else { + break; + } + } while (true); + FixedNode suffix = end.next(); + if (suffix instanceof EndNode) { + for (PhiNode phi : ((EndNode) suffix).merge().phis()) { + int materialized = 0; + boolean used = false; + for (Node input : phi.inputs()) { + if (input instanceof MaterializeObjectNode) { + materialized++; + } + if (input == materializeObjectNode) { + used = true; + } + } + if (used && materialized != phi.valueCount()) { + return false; + } + } + } + + return true; + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,200 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.virtual.phases.ea; + +import static com.oracle.graal.virtual.phases.ea.PartialEscapeAnalysisPhase.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.phases.graph.ReentrantBlockIterator.MergeableBlockState; +import com.oracle.graal.virtual.nodes.*; + +class BlockState extends MergeableBlockState<BlockState> { + + private final HashMap<VirtualObjectNode, ObjectState> objectStates = new HashMap<>(); + private final HashMap<ValueNode, VirtualObjectNode> objectAliases = new HashMap<>(); + private final HashMap<ValueNode, ValueNode> scalarAliases = new HashMap<>(); + + public BlockState() { + } + + public BlockState(BlockState other) { + for (Map.Entry<VirtualObjectNode, ObjectState> entry : other.objectStates.entrySet()) { + objectStates.put(entry.getKey(), entry.getValue().cloneState()); + } + for (Map.Entry<ValueNode, VirtualObjectNode> entry : other.objectAliases.entrySet()) { + objectAliases.put(entry.getKey(), entry.getValue()); + } + for (Map.Entry<ValueNode, ValueNode> entry : other.scalarAliases.entrySet()) { + scalarAliases.put(entry.getKey(), entry.getValue()); + } + } + + public ObjectState getObjectState(VirtualObjectNode object) { + assert objectStates.containsKey(object); + return objectStates.get(object); + } + + public ObjectState getObjectStateOptional(VirtualObjectNode object) { + return objectStates.get(object); + } + + public ObjectState getObjectState(ValueNode value) { + VirtualObjectNode object = objectAliases.get(value); + return object == null ? null : getObjectState(object); + } + + @Override + public BlockState cloneState() { + return new BlockState(this); + } + + public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual, GraphEffectList materializeEffects) { + HashSet<VirtualObjectNode> deferred = new HashSet<>(); + GraphEffectList deferredStores = new GraphEffectList(); + materializeChangedBefore(fixed, virtual, deferred, deferredStores, materializeEffects); + materializeEffects.addAll(deferredStores); + } + + private void materializeChangedBefore(FixedNode fixed, VirtualObjectNode virtual, HashSet<VirtualObjectNode> deferred, GraphEffectList deferredStores, GraphEffectList materializeEffects) { + trace("materializing %s at %s", virtual, fixed); + ObjectState obj = getObjectState(virtual); + if (obj.getLockCount() > 0 && obj.virtual.type().isArrayClass()) { + throw new BailoutException("array materialized with lock"); + } + + MaterializeObjectNode materialize = new MaterializeObjectNode(virtual, obj.getLockCount()); + ValueNode[] values = new ValueNode[obj.getEntries().length]; + materialize.setProbability(fixed.probability()); + ValueNode[] fieldState = obj.getEntries(); + obj.setMaterializedValue(materialize); + deferred.add(virtual); + for (int i = 0; i < fieldState.length; i++) { + ObjectState valueObj = getObjectState(fieldState[i]); + if (valueObj != null) { + if (valueObj.isVirtual()) { + materializeChangedBefore(fixed, valueObj.virtual, deferred, deferredStores, materializeEffects); + } + if (deferred.contains(valueObj.virtual)) { + Kind fieldKind; + CyclicMaterializeStoreNode store; + if (virtual instanceof VirtualArrayNode) { + store = new CyclicMaterializeStoreNode(materialize, valueObj.getMaterializedValue(), i); + fieldKind = ((VirtualArrayNode) virtual).componentType().getKind(); + } else { + VirtualInstanceNode instanceObject = (VirtualInstanceNode) virtual; + store = new CyclicMaterializeStoreNode(materialize, valueObj.getMaterializedValue(), instanceObject.field(i)); + fieldKind = instanceObject.field(i).getType().getKind(); + } + deferredStores.addFixedNodeBefore(store, fixed); + values[i] = ConstantNode.defaultForKind(fieldKind, fixed.graph()); + } else { + values[i] = valueObj.getMaterializedValue(); + } + } else { + values[i] = fieldState[i]; + } + } + deferred.remove(virtual); + + materializeEffects.addMaterialization(materialize, fixed, values); + } + + void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node, NodeBitMap usages) { + objectAliases.put(node, virtual); + for (Node usage : node.usages()) { + markVirtualUsages(usage, usages); + } + } + + private void markVirtualUsages(Node node, NodeBitMap usages) { + if (!usages.isNew(node)) { + usages.mark(node); + } + if (node instanceof VirtualState) { + for (Node usage : node.usages()) { + markVirtualUsages(usage, usages); + } + } + } + + public void addObject(VirtualObjectNode virtual, ObjectState state) { + objectStates.put(virtual, state); + } + + public void addScalarAlias(ValueNode alias, ValueNode value) { + scalarAliases.put(alias, value); + } + + public ValueNode getScalarAlias(ValueNode alias) { + ValueNode result = scalarAliases.get(alias); + return result == null ? alias : result; + } + + public Iterable<ObjectState> getStates() { + return objectStates.values(); + } + + public Iterable<VirtualObjectNode> getVirtualObjects() { + return objectAliases.values(); + } + + @Override + public String toString() { + return objectStates.toString(); + } + + public static BlockState meetAliases(List<BlockState> states) { + BlockState newState = new BlockState(); + + newState.objectAliases.putAll(states.get(0).objectAliases); + for (int i = 1; i < states.size(); i++) { + BlockState state = states.get(i); + for (Map.Entry<ValueNode, VirtualObjectNode> entry : states.get(0).objectAliases.entrySet()) { + if (state.objectAliases.containsKey(entry.getKey())) { + assert state.objectAliases.get(entry.getKey()) == entry.getValue(); + } else { + newState.objectAliases.remove(entry.getKey()); + } + } + } + + newState.scalarAliases.putAll(states.get(0).scalarAliases); + for (int i = 1; i < states.size(); i++) { + BlockState state = states.get(i); + for (Map.Entry<ValueNode, ValueNode> entry : states.get(0).scalarAliases.entrySet()) { + if (state.scalarAliases.containsKey(entry.getKey())) { + assert state.scalarAliases.get(entry.getKey()) == entry.getValue(); + } else { + newState.scalarAliases.remove(entry.getKey()); + } + } + } + return newState; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectList.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.virtual.phases.ea; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; + +/** + * An {@link EffectList} can be used to maintain a list of {@link Effect}s and backtrack to a previous state by + * truncating the list. It can also maintain a level for each effect, which helps in creating a string representation + * for the list. + */ +public class EffectList implements Iterable<EffectList.Effect> { + + public abstract static class Effect { + + public boolean isVisible() { + return true; + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + for (Field field : getClass().getDeclaredFields()) { + String name = field.getName(); + if (name.contains("$")) { + name = name.substring(name.indexOf('$') + 1); + } + if (!Modifier.isStatic(field.getModifiers()) && !name.equals("0")) { + try { + field.setAccessible(true); + str.append(str.length() > 0 ? ", " : "").append(name).append("=").append(format(field.get(this))); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + return name() + " [" + str + "]"; + } + + private static String format(Object object) { + if (object != null && Object[].class.isAssignableFrom(object.getClass())) { + return Arrays.toString((Object[]) object); + } + return "" + object; + } + + public abstract String name(); + + public abstract void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes); + } + + private Effect[] effects = new Effect[16]; + private int[] level = new int[16]; + private int size; + private int currentLevel; + + public void add(Effect effect) { + if (effects.length == size) { + effects = Arrays.copyOf(effects, effects.length * 2); + level = Arrays.copyOf(level, effects.length); + } + level[size] = currentLevel; + effects[size++] = effect; + } + + public void addAll(Collection< ? extends Effect> list) { + int length = effects.length; + if (size + list.size() > length) { + while (size + list.size() > length) { + length *= 2; + } + effects = Arrays.copyOf(effects, length); + level = Arrays.copyOf(level, effects.length); + } + for (Effect effect : list) { + level[size] = currentLevel; + effects[size++] = effect; + } + } + + public void addAll(EffectList list) { + int length = effects.length; + if (size + list.size > length) { + while (size + list.size > length) { + length *= 2; + } + effects = Arrays.copyOf(effects, length); + level = Arrays.copyOf(level, effects.length); + } + for (Effect effect : list) { + level[size] = currentLevel; + effects[size++] = effect; + } + } + + public int checkpoint() { + return size; + } + + public int size() { + return size; + } + + public void backtrack(int checkpoint) { + assert checkpoint <= size; + size = checkpoint; + } + + @Override + public Iterator<Effect> iterator() { + return new Iterator<Effect>() { + + int index; + final int listSize = EffectList.this.size; + + @Override + public boolean hasNext() { + return index < listSize; + } + + @Override + public Effect next() { + return effects[index++]; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + public void incLevel() { + currentLevel++; + } + + public void decLevel() { + currentLevel--; + } + + public Effect get(int index) { + if (index >= size) { + throw new IndexOutOfBoundsException(); + } + return effects[index]; + } + + public int levelAt(int index) { + if (index >= size) { + throw new IndexOutOfBoundsException(); + } + return level[index]; + } + + public void clear() { + size = 0; + } + + public boolean isEmpty() { + return size == 0; + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + for (int i = 0; i < size(); i++) { + Effect effect = get(i); + if (effect.isVisible()) { + for (int i2 = 0; i2 < levelAt(i); i2++) { + str.append(" "); + } + str.append(effect).toString(); + } + } + return str.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.virtual.phases.ea; + +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.virtual.nodes.*; + +public class GraphEffectList extends EffectList { + + /** + * Adds the given fixed node to the graph's control flow, before position (so that the original predecessor of + * position will then be node's predecessor). + * + * @param node The fixed node to be added to the graph. + * @param position The fixed node before which the node should be added. + */ + public void addFixedNodeBefore(final FixedWithNextNode node, final FixedNode position) { + add(new Effect() { + + @Override + public String name() { + return "addFixedNodeBefore"; + } + + @Override + public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { + assert !node.isAlive() && !node.isDeleted() && position.isAlive(); + graph.addBeforeFixed(position, graph.add(node)); + node.setProbability(position.probability()); + } + }); + } + + /** + * Add the given floating node to the graph. + * + * @param node The floating node to be added. + */ + public void addFloatingNode(final FloatingNode node) { + add(new Effect() { + + @Override + public String name() { + return "addFloatingNode"; + } + + @Override + public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { + assert !node.isAlive() && !node.isDeleted(); + graph.add(node); + } + }); + } + + /** + * Add the materialization node to the graph's control flow at the given position, and then sets its values. + * + * @param node The materialization node that should be added. + * @param position The fixed node before which the materialization node should be added. + * @param values The values for the materialization node's entries. + */ + public void addMaterialization(final MaterializeObjectNode node, final FixedNode position, final ValueNode[] values) { + add(new Effect() { + + @Override + public String name() { + return "addMaterialization"; + } + + @Override + public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { + assert !node.isAlive() && !node.isDeleted() && position.isAlive(); + graph.addBeforeFixed(position, graph.add(node)); + node.setProbability(position.probability()); + for (int i = 0; i < values.length; i++) { + node.values().set(i, values[i]); + } + } + }); + } + + /** + * Adds an value to the given phi node. + * + * @param node The phi node to which the value should be added. + * @param value The value that will be added to the phi node. + */ + public void addPhiInput(final PhiNode node, final ValueNode value) { + add(new Effect() { + + @Override + public String name() { + return "addPhiInput"; + } + + @Override + public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { + assert node.isAlive() && value.isAlive(); + node.addInput(value); + } + }); + } + + /** + * Sets the phi node's input at the given index to the given value. + * + * @param node The phi node whose input should be changed. + * @param index The index of the phi input to be changed. + * @param value The new value for the phi input. + */ + public void setPhiInput(final PhiNode node, final int index, final ValueNode value) { + add(new Effect() { + + @Override + public String name() { + return "setPhiInput"; + } + + @Override + public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { + assert node.isAlive() && value.isAlive() && index >= 0; + node.setValueAt(index, value); + } + }); + } + + /** + * Adds a virtual object's state to the given frame state. If the given reusedVirtualObjects set contains the + * virtual object then old states for this object will be removed. + * + * @param node The frame state to which the state should be added. + * @param state The virtual object state to add. + * @param reusedVirtualObjects A set of all reused virtual objects. + */ + public void addVirtualMapping(final FrameState node, final EscapeObjectState state, final HashSet<VirtualObjectNode> reusedVirtualObjects) { + add(new Effect() { + + @Override + public String name() { + return "addVirtualMapping"; + } + + @Override + public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { + assert node.isAlive() && !state.isAlive() && !state.isDeleted(); + FrameState stateAfter = node; + for (int i = 0; i < stateAfter.virtualObjectMappingCount(); i++) { + if (stateAfter.virtualObjectMappingAt(i).object() == state.object()) { + if (reusedVirtualObjects.contains(state.object())) { + stateAfter.virtualObjectMappings().remove(i); + } else { + throw new GraalInternalError("unexpected duplicate virtual state at: %s for %s", stateAfter, state.object()); + } + } + } + stateAfter.addVirtualObjectMapping(graph.add(state)); + } + + @Override + public boolean isVisible() { + return false; + } + }); + } + + /** + * Removes the given fixed node from the control flow and deletes it. + * + * @param node The fixed node that should be deleted. + */ + public void deleteFixedNode(final FixedWithNextNode node) { + add(new Effect() { + + @Override + public String name() { + return "deleteFixedNode"; + } + + @Override + public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { + assert node.isAlive(); + FixedNode next = node.next(); + node.setNext(null); + node.replaceAtPredecessor(next); + obsoleteNodes.add(node); + } + }); + } + + /** + * Virtualizes a monitor access by calling its {@link AccessMonitorNode#eliminate()} method. + * + * @param node The monitor access that should be virtualized. + */ + public void eliminateMonitor(final AccessMonitorNode node) { + add(new Effect() { + + @Override + public String name() { + return "eliminateMonitor"; + } + + @Override + public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { + assert node.isAlive() && node.object().isAlive() && (node.object() instanceof VirtualObjectNode); + node.eliminate(); + } + }); + } + + /** + * Replaces the given node at its usages without deleting it. + * + * @param node The node to be replaced. + * @param replacement The node that should replace the original value. + */ + public void replaceAtUsages(final ValueNode node, final ValueNode replacement) { + add(new Effect() { + + @Override + public String name() { + return "replaceAtUsages"; + } + + @Override + public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { + assert node.isAlive() && replacement.isAlive(); + node.replaceAtUsages(replacement); + } + }); + } + + /** + * Replaces the first occurrence of oldInput in node with newInput. + * + * @param node The node whose input should be changed. + * @param oldInput The value to look for. + * @param newInput The value to replace with. + */ + public void replaceFirstInput(final Node node, final ValueNode oldInput, final ValueNode newInput) { + add(new Effect() { + + @Override + public String name() { + return "replaceFirstInput"; + } + + @Override + public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { + assert node.isAlive() && oldInput.isAlive() && newInput.isAlive(); + node.replaceFirstInput(oldInput, newInput); + } + + @Override + public boolean isVisible() { + return !(node instanceof FrameState); + } + }); + } +}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/MergeableBlockState.java Fri Nov 09 13:32:53 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.virtual.phases.ea; - - -public interface MergeableBlockState<T> { - - T clone(); -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ObjectState.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,128 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.virtual.phases.ea; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.virtual.*; + +/** + * This class describes the state of a virtual object while iterating over the graph. + * It describes the fields or array elements (called "entries") and the lock count if the object is still virtual. + * If the object was materialized, it contains the current materialized value. + */ +class ObjectState { + + public final VirtualObjectNode virtual; + private ValueNode[] entries; + private ValueNode materializedValue; + private int lockCount; + + public ObjectState(VirtualObjectNode virtual, ValueNode[] entries, int lockCount) { + this.virtual = virtual; + this.entries = entries; + this.lockCount = lockCount; + } + + public ObjectState(VirtualObjectNode virtual, ValueNode materializedValue, int lockCount) { + this.virtual = virtual; + this.materializedValue = materializedValue; + this.lockCount = lockCount; + } + + private ObjectState(ObjectState other) { + virtual = other.virtual; + entries = other.entries == null ? null : other.entries.clone(); + materializedValue = other.materializedValue; + lockCount = other.lockCount; + } + + public ObjectState cloneState() { + return new ObjectState(this); + } + + public boolean isVirtual() { + assert (entries == null) ^ (materializedValue == null); + return materializedValue == null; + } + + public ValueNode[] getEntries() { + assert isVirtual(); + return entries; + } + + public ValueNode getEntry(int index) { + assert isVirtual(); + return entries[index]; + } + + public void setEntry(int index, ValueNode value) { + assert isVirtual(); + entries[index] = value; + } + + public ValueNode getMaterializedValue() { + assert !isVirtual(); + return materializedValue; + } + + public void setMaterializedValue(ValueNode value) { + assert isVirtual(); + materializedValue = value; + entries = null; + } + + public void updateMaterializedValue(ValueNode value) { + assert !isVirtual(); + materializedValue = value; + } + + public int getLockCount() { + return lockCount; + } + + public void incLockCount() { + lockCount++; + } + + public void decLockCount() { + lockCount--; + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder().append('{'); + if (lockCount > 0) { + str.append('l').append(lockCount).append(' '); + } + if (entries != null) { + for (int i = 0; i < entries.length; i++) { + str.append(virtual.fieldName(i)).append('=').append(entries[i]).append(' '); + } + } + if (materializedValue != null) { + str.append("mat=").append(materializedValue); + } + + return str.append('}').toString(); + } +}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Fri Nov 09 13:32:53 2012 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Fri Nov 09 13:35:26 2012 +0100 @@ -26,40 +26,26 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.ResolvedJavaType.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.PhiNode.PhiType; -import com.oracle.graal.nodes.VirtualState.NodeClosure; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.cfg.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.schedule.*; -import com.oracle.graal.virtual.nodes.*; +import com.oracle.graal.virtual.phases.ea.EffectList.Effect; -class EscapeAnalysisIteration { +public class PartialEscapeAnalysisPhase extends Phase { - // Metrics - private static final DebugMetric metricAllocationRemoved = Debug.metric("AllocationRemoved"); - private static final DebugMetric metricAllocationFieldsRemoved = Debug.metric("AllocationFieldsRemoved"); - private static final DebugMetric metricStoreRemoved = Debug.metric("StoreRemoved"); - private static final DebugMetric metricLoadRemoved = Debug.metric("LoadRemoved"); - private static final DebugMetric metricLockRemoved = Debug.metric("LockRemoved"); - private static final DebugMetric metricOtherRemoved = Debug.metric("OtherRemoved"); - private static final DebugMetric metricMaterializations = Debug.metric("Materializations"); - private static final DebugMetric metricMaterializationFields = Debug.metric("MaterializationFields"); - private static final DebugMetric metricLoopBailouts = Debug.metric("LoopBailouts"); - private static final DebugMetric metricMonitorBailouts = Debug.metric("MonitorBailouts"); + private final TargetDescription target; + private final MetaAccessProvider runtime; + private final Assumptions assumptions; - - private static final ValueNode DUMMY_NODE = new ValueNode(null) { - }; + public PartialEscapeAnalysisPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) { + this.target = target; + this.runtime = runtime; + this.assumptions = assumptions; + } public static final void trace(String format, Object... obj) { if (GraalOptions.TraceEscapeAnalysis) { @@ -71,1078 +57,118 @@ System.out.print(String.format(format, obj)); } - private final StructuredGraph graph; - private final MetaAccessProvider runtime; - private final SchedulePhase schedule; - private final NodeBitMap usages; - boolean changed = false; - - private final boolean changeGraph; - - private final HashSet<VirtualObjectNode> reusedVirtualObjects = new HashSet<>(); - private final HashSet<ValueNode> allocations; - private final ArrayList<ValueNode> obsoleteNodes = new ArrayList<>(); - private int virtualIds = 0; - - public EscapeAnalysisIteration(StructuredGraph graph, SchedulePhase schedule, MetaAccessProvider runtime, HashSet<ValueNode> allocations, boolean changeGraph) { - this.graph = graph; - this.schedule = schedule; - this.runtime = runtime; - this.allocations = allocations; - this.changeGraph = changeGraph; - this.usages = graph.createNodeBitMap(); - } - - public void run() { - new PartialEscapeIterator(graph, schedule.getCFG().getStartBlock()).apply(); - - if (changeGraph) { - Debug.dump(graph, "after PartialEscapeAnalysis"); - - for (ValueNode node : obsoleteNodes) { - if (node.isAlive() && node instanceof FixedWithNextNode) { - FixedWithNextNode x = (FixedWithNextNode) node; - FixedNode next = x.next(); - x.setNext(null); - ((FixedWithNextNode) node.predecessor()).setNext(next); - } - } - new DeadCodeEliminationPhase().apply(graph); - - if (changed) { - Debug.log("escape analysis on %s\n", graph.method()); - } - } - } - - private static class ObjectState { - - public final VirtualObjectNode virtual; - public ValueNode[] fieldState; - public ValueNode materializedValue; - public int lockCount; - public boolean initialized; - - public ObjectState(VirtualObjectNode virtual, ValueNode[] fieldState, int lockCount) { - this.virtual = virtual; - this.fieldState = fieldState; - this.lockCount = lockCount; - this.initialized = false; + @Override + protected void run(final StructuredGraph graph) { + if (!matches(graph, GraalOptions.EscapeAnalyzeOnly)) { + return; } - public ObjectState(VirtualObjectNode virtual, ValueNode materializedValue, int lockCount) { - this.virtual = virtual; - this.materializedValue = materializedValue; - this.lockCount = lockCount; - this.initialized = true; - } + for (int iteration = 0; iteration < GraalOptions.EscapeAnalysisIterations; iteration++) { + Debug.scope("iteration " + iteration, new Runnable() { + @Override + public void run() { + SchedulePhase schedule = new SchedulePhase(); + schedule.apply(graph, false); + PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, runtime); + ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock(), new BlockState(), null); - private ObjectState(ObjectState other) { - virtual = other.virtual; - fieldState = other.fieldState == null ? null : other.fieldState.clone(); - materializedValue = other.materializedValue; - lockCount = other.lockCount; - initialized = other.initialized; - } + if (closure.getVirtualIdCount() == 0) { + return; + } - @Override - public ObjectState clone() { - return new ObjectState(this); - } + // apply the effects collected during the escape analysis iteration + ArrayList<Node> obsoleteNodes = new ArrayList<>(); + for (Effect effect : closure.getEffects()) { + effect.apply(graph, obsoleteNodes); + } + trace("%s\n", closure.getEffects()); - @Override - public String toString() { - StringBuilder str = new StringBuilder().append('{'); - if (lockCount > 0) { - str.append('l').append(lockCount).append(' '); - } - if (fieldState != null) { - for (int i = 0; i < fieldState.length; i++) { - str.append(virtual.fieldName(i)).append('=').append(fieldState[i]).append(' '); + Debug.dump(graph, "after PartialEscapeAnalysis"); + assert noObsoleteNodes(graph, obsoleteNodes); + + new DeadCodeEliminationPhase().apply(graph); + if (GraalOptions.OptCanonicalizer) { + new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + } } - } - if (materializedValue != null) { - str.append("mat=").append(materializedValue); - } - - return str.append('}').toString(); + }); } } - private class BlockState implements MergeableBlockState<BlockState> { - - private final HashMap<VirtualObjectNode, ObjectState> objectStates = new HashMap<>(); - private final HashMap<ValueNode, VirtualObjectNode> objectAliases = new HashMap<>(); - - public BlockState() { + private static boolean matches(StructuredGraph graph, String filter) { + if (filter != null) { + ResolvedJavaMethod method = graph.method(); + return method != null && MetaUtil.format("%H.%n", method).contains(filter); } - - public BlockState(BlockState other) { - for (Map.Entry<VirtualObjectNode, ObjectState> entry : other.objectStates.entrySet()) { - objectStates.put(entry.getKey(), entry.getValue().clone()); - } - for (Map.Entry<ValueNode, VirtualObjectNode> entry : other.objectAliases.entrySet()) { - objectAliases.put(entry.getKey(), entry.getValue()); - } - } + return true; + } - public ObjectState objectState(VirtualObjectNode object) { - assert objectStates.containsKey(object); - return objectStates.get(object); - } - - public ObjectState objectState(ValueNode value) { - VirtualObjectNode object = objectAliases.get(value); - return object == null ? null : objectState(object); - } + private static boolean noObsoleteNodes(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { + // helper code that determines the paths that keep obsolete nodes alive: - @Override - public BlockState clone() { - return new BlockState(this); - } - - public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual) { - if (changeGraph) { - HashSet<VirtualObjectNode> deferred = new HashSet<>(); - ArrayList<FixedWithNextNode> deferredStores = new ArrayList<>(); - materializeChangedBefore(fixed, virtual, deferred, deferredStores); - for (FixedWithNextNode write : deferredStores) { - write.setProbability(fixed.probability()); - graph.addBeforeFixed(fixed, write); + NodeFlood flood = graph.createNodeFlood(); + IdentityHashMap<Node, Node> path = new IdentityHashMap<>(); + flood.add(graph.start()); + for (Node current : flood) { + if (current instanceof EndNode) { + EndNode end = (EndNode) current; + flood.add(end.merge()); + if (!path.containsKey(end.merge())) { + path.put(end.merge(), end); } } else { - materializeUnchangedBefore(virtual); - } - } - - private void materializeUnchangedBefore(VirtualObjectNode virtual) { - trace("materializing %s", virtual); - ObjectState obj = objectState(virtual); - if (obj.lockCount > 0) { - if (changeGraph) { - error("object materialized with lock: %s\n", virtual); - } - metricMonitorBailouts.increment(); - throw new BailoutException("object materialized with lock"); - } - - ValueNode[] fieldState = obj.fieldState; - obj.fieldState = null; - obj.materializedValue = DUMMY_NODE; - for (int i = 0; i < fieldState.length; i++) { - ObjectState valueObj = objectState(fieldState[i]); - if (valueObj != null) { - if (valueObj.materializedValue == null) { - materializeUnchangedBefore(valueObj.virtual); + for (Node successor : current.successors()) { + flood.add(successor); + if (!path.containsKey(successor)) { + path.put(successor, current); } } } - obj.initialized = true; - } - - private void materializeChangedBefore(FixedNode fixed, VirtualObjectNode virtual, HashSet<VirtualObjectNode> deferred, ArrayList<FixedWithNextNode> deferredStores) { - trace("materializing %s at %s", virtual, fixed); - ObjectState obj = objectState(virtual); - if (obj.lockCount > 0) { - error("object materialized with lock: %s\n", virtual); - metricMonitorBailouts.increment(); - throw new BailoutException("object materialized with lock"); - } - - MaterializeObjectNode materialize = graph.add(new MaterializeObjectNode(virtual, false)); - materialize.setProbability(fixed.probability()); - ValueNode[] fieldState = obj.fieldState; - metricMaterializations.increment(); - metricMaterializationFields.add(fieldState.length); - obj.fieldState = null; - obj.materializedValue = materialize; - deferred.add(virtual); - for (int i = 0; i < fieldState.length; i++) { - ObjectState valueObj = objectState(fieldState[i]); - if (valueObj != null) { - if (valueObj.materializedValue == null) { - materializeChangedBefore(fixed, valueObj.virtual, deferred, deferredStores); - } - if (deferred.contains(valueObj.virtual)) { - Kind fieldKind; - if (virtual instanceof VirtualArrayNode) { - deferredStores.add(graph.add(new CyclicMaterializeStoreNode(materialize, valueObj.materializedValue, i))); - fieldKind = ((VirtualArrayNode) virtual).componentType().getKind(); - } else { - VirtualInstanceNode instanceObject = (VirtualInstanceNode) virtual; - deferredStores.add(graph.add(new CyclicMaterializeStoreNode(materialize, valueObj.materializedValue, instanceObject.field(i)))); - fieldKind = instanceObject.field(i).getType().getKind(); - } - materialize.values().set(i, ConstantNode.defaultForKind(fieldKind, graph)); - } else { - assert valueObj.initialized : "should be initialized: " + virtual + " at " + fixed; - materialize.values().set(i, valueObj.materializedValue); - } - } else { - materialize.values().set(i, fieldState[i]); - } - } - deferred.remove(virtual); - - obj.initialized = true; - graph.addBeforeFixed(fixed, materialize); - } - - private void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node, boolean remove) { - objectAliases.put(node, virtual); - for (Node usage : node.usages()) { - markVirtualUsages(usage); - } - if (remove) { - obsoleteNodes.add(node); - } - } - - private void markVirtualUsages(Node node) { - if (!usages.isNew(node)) { - usages.mark(node); - } - if (node instanceof VirtualState) { - for (Node usage : node.usages()) { - markVirtualUsages(usage); - } - } } - public void addObject(VirtualObjectNode virtual, ObjectState state) { - objectStates.put(virtual, state); - } - - public Iterable<ObjectState> states() { - return objectStates.values(); - } - - @Override - public String toString() { - return objectStates.toString(); - } - } - - private class PartialEscapeIterator extends PostOrderBlockIterator<BlockState> { - - public PartialEscapeIterator(StructuredGraph graph, Block start) { - super(graph, start, new BlockState()); - } - - @Override - protected void processBlock(Block block, BlockState state) { - trace("\nBlock: %s (", block); - List<ScheduledNode> nodeList = schedule.getBlockToNodesMap().get(block); - - FixedWithNextNode lastFixedNode = null; - for (Node node : nodeList) { - EscapeOp op = null; - if (node instanceof EscapeAnalyzable) { - op = ((EscapeAnalyzable) node).getEscapeOp(); - } - if (op != null) { - // only escape analyze allocations that were escape analyzed during the first iteration - if (changeGraph && !allocations.contains(node)) { - op = null; - } - } - - if (op != null) { - trace("{{%s}} ", node); - VirtualObjectNode virtualObject = op.virtualObject(virtualIds); - if (virtualObject.isAlive()) { - reusedVirtualObjects.add(virtualObject); - state.addAndMarkAlias(virtualObject, virtualObject, false); - } else { - if (changeGraph) { - virtualObject = graph.add(virtualObject); - } - } - ValueNode[] fieldState = changeGraph ? op.fieldState() : new ValueNode[virtualObject.entryCount()]; - if (changeGraph) { - metricAllocationRemoved.increment(); - metricAllocationFieldsRemoved.add(fieldState.length); - } else { - allocations.add((ValueNode) node); - } - state.addObject(virtualObject, new ObjectState(virtualObject, fieldState, 0)); - state.addAndMarkAlias(virtualObject, (ValueNode) node, true); - virtualIds++; - } else { - if (changeGraph && node instanceof LoopExitNode) { - for (ObjectState obj : state.states()) { - if (obj.fieldState != null) { - for (int i = 0; i < obj.fieldState.length; i++) { - ValueNode value = obj.fieldState[i]; - ObjectState valueObj = state.objectState(value); - if (valueObj == null) { - obj.fieldState[i] = graph.unique(new ValueProxyNode(value, (LoopExitNode) node, PhiType.Value)); - } - } - } else { - obj.materializedValue = graph.unique(new ValueProxyNode(obj.materializedValue, (LoopExitNode) node, PhiType.Value)); - } - } - } - - if (usages.isMarked(node)) { - trace("[[%s]] ", node); - processNode((ValueNode) node, lastFixedNode == null ? null : lastFixedNode.next(), state); - } else { - trace("%s ", node); - } - } - - if (node instanceof FixedWithNextNode && node.isAlive()) { - lastFixedNode = (FixedWithNextNode) node; - } + for (Node node : obsoleteNodes) { + if (node instanceof FixedNode) { + assert !flood.isMarked(node); } - trace(")\n end state: %s\n", state); } - private void processNode(final ValueNode node, FixedNode insertBefore, final BlockState state) { - boolean usageFound = false; - if (node instanceof PiNode || node instanceof ValueProxyNode) { - ValueNode value = node instanceof PiNode ? ((PiNode) node).object() : ((ValueProxyNode) node).value(); - ObjectState obj = state.objectState(value); - assert obj != null : node; - if (obj.materializedValue == null) { - state.addAndMarkAlias(obj.virtual, node, true); - } else { - if (changeGraph) { - node.replaceFirstInput(value, obj.materializedValue); - } - } - usageFound = true; - } else if (node instanceof CheckCastNode) { - CheckCastNode x = (CheckCastNode) node; - ObjectState obj = state.objectState(x.object()); - assert obj != null : x; - if (obj.materializedValue == null) { - if (x.targetClass() != null && obj.virtual.type().isSubtypeOf(x.targetClass())) { - metricOtherRemoved.increment(); - state.addAndMarkAlias(obj.virtual, x, true); - // throw new UnsupportedOperationException("probably incorrect - losing dependency"); - } else { - replaceWithMaterialized(x.object(), x, state, obj); - } - } else { - if (changeGraph) { - node.replaceFirstInput(x.object(), obj.materializedValue); - } - } - usageFound = true; - } else if (node instanceof IsNullNode) { - IsNullNode x = (IsNullNode) node; - ObjectState obj = state.objectState(x.object()); - assert obj != null : x; - if (changeGraph) { - graph.replaceFloating(x, graph.unique(ConstantNode.forBoolean(false, graph))); - metricOtherRemoved.increment(); - } - usageFound = true; - } else if (node instanceof AccessMonitorNode) { - AccessMonitorNode x = (AccessMonitorNode) node; - ObjectState obj = state.objectState(x.object()); - if (obj != null) { - Debug.log("monitor operation %s on %s\n", x, obj.virtual); - if (node instanceof MonitorEnterNode) { - obj.lockCount++; - } else { - assert node instanceof MonitorExitNode; - obj.lockCount--; - } - if (changeGraph) { - changed = true; - if (obj.materializedValue == null) { - metricLockRemoved.increment(); - node.replaceFirstInput(x.object(), obj.virtual); - x.eliminate(); - } else { - node.replaceFirstInput(x.object(), obj.materializedValue); - } - } - usageFound = true; - } - } else if (node instanceof CyclicMaterializeStoreNode) { - CyclicMaterializeStoreNode x = (CyclicMaterializeStoreNode) node; - ObjectState obj = state.objectState(x.object()); - assert obj != null : x; - if (obj.virtual instanceof VirtualArrayNode) { - obj.fieldState[x.targetIndex()] = x.value(); - } else { - VirtualInstanceNode instance = (VirtualInstanceNode) obj.virtual; - int index = instance.fieldIndex(x.targetField()); - obj.fieldState[index] = x.value(); - } - if (changeGraph) { - graph.removeFixed(x); - } - usageFound = true; - } else if (node instanceof LoadFieldNode) { - LoadFieldNode x = (LoadFieldNode) node; - ObjectState obj = state.objectState(x.object()); - assert obj != null : x; - VirtualInstanceNode virtual = (VirtualInstanceNode) obj.virtual; - int fieldIndex = virtual.fieldIndex(x.field()); - if (fieldIndex == -1) { - // the field does not exist in the virtual object - ensureMaterialized(state, obj, x); - } - if (obj.materializedValue == null) { - ValueNode result = obj.fieldState[fieldIndex]; - ObjectState resultObj = state.objectState(result); - if (resultObj != null) { - state.addAndMarkAlias(resultObj.virtual, x, true); - } else { - if (changeGraph) { - x.replaceAtUsages(result); - graph.removeFixed(x); - } - } - if (changeGraph) { - metricLoadRemoved.increment(); - } - changed = true; - } else { - if (changeGraph) { - x.replaceFirstInput(x.object(), obj.materializedValue); - } - } - usageFound = true; - } else if (node instanceof StoreFieldNode) { - StoreFieldNode x = (StoreFieldNode) node; - ValueNode object = x.object(); - ValueNode value = x.value(); - ObjectState obj = state.objectState(object); - if (obj != null) { - VirtualInstanceNode virtual = (VirtualInstanceNode) obj.virtual; - int fieldIndex = virtual.fieldIndex(x.field()); - if (fieldIndex == -1) { - // the field does not exist in the virtual object - ensureMaterialized(state, obj, x); - } - if (obj.materializedValue == null) { - obj.fieldState[fieldIndex] = value; - if (changeGraph) { - graph.removeFixed(x); - metricStoreRemoved.increment(); - } - changed = true; - } else { - if (changeGraph) { - x.replaceFirstInput(object, obj.materializedValue); - } - ObjectState valueObj = state.objectState(value); - if (valueObj != null) { - replaceWithMaterialized(value, x, state, valueObj); - } - } - usageFound = true; - } else { - ObjectState valueObj = state.objectState(value); - if (valueObj != null) { - replaceWithMaterialized(value, x, state, valueObj); - usageFound = true; - } - } - } else if (node instanceof LoadIndexedNode) { - LoadIndexedNode x = (LoadIndexedNode) node; - ValueNode array = x.array(); - ObjectState arrayObj = state.objectState(array); - if (arrayObj != null) { - if (arrayObj.materializedValue == null) { - int index = x.index().isConstant() ? x.index().asConstant().asInt() : -1; - if (index < 0 || index >= arrayObj.fieldState.length) { - // out of bounds or not constant - replaceWithMaterialized(array, x, state, arrayObj); - } else { - ValueNode result = arrayObj.fieldState[index]; - ObjectState resultObj = state.objectState(result); - if (resultObj != null) { - state.addAndMarkAlias(resultObj.virtual, x, true); - } else { - if (changeGraph) { - x.replaceAtUsages(result); - graph.removeFixed(x); - } - } - if (changeGraph) { - metricLoadRemoved.increment(); - } - changed = true; - } - } else { - if (changeGraph) { - x.replaceFirstInput(array, arrayObj.materializedValue); - } - } - usageFound = true; - } - } else if (node instanceof StoreIndexedNode) { - StoreIndexedNode x = (StoreIndexedNode) node; - ValueNode array = x.array(); - ValueNode value = x.value(); - ObjectState arrayObj = state.objectState(array); - ObjectState valueObj = state.objectState(value); - - if (arrayObj != null) { - if (arrayObj.materializedValue == null) { - int index = x.index().isConstant() ? x.index().asConstant().asInt() : -1; - if (index < 0 || index >= arrayObj.fieldState.length) { - // out of bounds or not constant - replaceWithMaterialized(array, x, state, arrayObj); - if (valueObj != null) { - replaceWithMaterialized(value, x, state, valueObj); - } - } else { - arrayObj.fieldState[index] = value; - if (changeGraph) { - graph.removeFixed(x); - metricStoreRemoved.increment(); - } - changed = true; - } - } else { - if (changeGraph) { - x.replaceFirstInput(array, arrayObj.materializedValue); - } - if (valueObj != null) { - replaceWithMaterialized(value, x, state, valueObj); - } - } - usageFound = true; - } else { - if (valueObj != null) { - replaceWithMaterialized(value, x, state, valueObj); - usageFound = true; - } - } - } else if (node instanceof RegisterFinalizerNode) { - RegisterFinalizerNode x = (RegisterFinalizerNode) node; - ObjectState obj = state.objectState(x.object()); - replaceWithMaterialized(x.object(), x, state, obj); - usageFound = true; - } else if (node instanceof ArrayLengthNode) { - ArrayLengthNode x = (ArrayLengthNode) node; - ObjectState obj = state.objectState(x.array()); - assert obj != null : x; - if (changeGraph) { - graph.replaceFixedWithFloating(x, ConstantNode.forInt(((VirtualArrayNode) obj.virtual).entryCount(), graph)); - metricOtherRemoved.increment(); - } - changed = true; - usageFound = true; - } else if (node instanceof LoadHubNode) { - LoadHubNode x = (LoadHubNode) node; - ObjectState obj = state.objectState(x.object()); - assert obj != null : x; - if (changeGraph) { - ConstantNode hub = ConstantNode.forConstant(obj.virtual.type().getEncoding(Representation.ObjectHub), runtime, graph); - graph.replaceFixedWithFloating(x, hub); - metricOtherRemoved.increment(); - } - changed = true; - usageFound = true; - } else if (node instanceof ReturnNode) { - ReturnNode x = (ReturnNode) node; - ObjectState obj = state.objectState(x.result()); - replaceWithMaterialized(x.result(), x, state, obj); - usageFound = true; - } else if (node instanceof MethodCallTargetNode) { - for (ValueNode argument : ((MethodCallTargetNode) node).arguments()) { - ObjectState obj = state.objectState(argument); - if (obj != null) { - replaceWithMaterialized(argument, node, insertBefore, state, obj); - usageFound = true; - } - } - } else if (node instanceof ObjectEqualsNode) { - ObjectEqualsNode x = (ObjectEqualsNode) node; - ObjectState xObj = state.objectState(x.x()); - ObjectState yObj = state.objectState(x.y()); - boolean xVirtual = xObj != null && xObj.materializedValue == null; - boolean yVirtual = yObj != null && yObj.materializedValue == null; - - if (changeGraph) { - if (xVirtual ^ yVirtual) { - // one of them is virtual: they can never be the same objects - graph.replaceFloating(x, ConstantNode.forBoolean(false, graph)); - usageFound = true; - metricOtherRemoved.increment(); - changed = true; - } else if (xVirtual && yVirtual) { - // both are virtual: check if they refer to the same object - graph.replaceFloating(x, ConstantNode.forBoolean(xObj == yObj, graph)); - usageFound = true; - metricOtherRemoved.increment(); - changed = true; - } else { - assert xObj != null || yObj != null; - if (xObj != null) { - assert xObj.materializedValue != null; - node.replaceFirstInput(x.x(), xObj.materializedValue); - } - if (yObj != null) { - assert yObj.materializedValue != null; - node.replaceFirstInput(x.y(), yObj.materializedValue); - } - } - } - usageFound = true; - } else if (node instanceof MergeNode) { - usageFound = true; - } else if (node instanceof UnsafeLoadNode || node instanceof UnsafeStoreNode || node instanceof CompareAndSwapNode || node instanceof SafeReadNode) { - for (ValueNode input : node.inputs().filter(ValueNode.class)) { - ObjectState obj = state.objectState(input); - if (obj != null) { - replaceWithMaterialized(input, node, insertBefore, state, obj); - usageFound = true; + for (Node node : graph.getNodes()) { + if (node instanceof LocalNode) { + flood.add(node); + } + if (flood.isMarked(node)) { + for (Node input : node.inputs()) { + flood.add(input); + if (!path.containsKey(input)) { + path.put(input, node); } } } - if (node.isAlive() && node instanceof StateSplit) { - StateSplit split = (StateSplit) node; - FrameState stateAfter = split.stateAfter(); - if (stateAfter != null) { - if (changeGraph) { - if (stateAfter.usages().size() > 1) { - stateAfter = (FrameState) stateAfter.copyWithInputs(); - split.setStateAfter(stateAfter); - } - final HashSet<ObjectState> virtual = new HashSet<>(); - stateAfter.applyToNonVirtual(new NodeClosure<ValueNode>() { - - @Override - public void apply(Node usage, ValueNode value) { - ObjectState valueObj = state.objectState(value); - if (valueObj != null) { - virtual.add(valueObj); - usage.replaceFirstInput(value, valueObj.virtual); - } else if (value instanceof VirtualObjectNode) { - ObjectState virtualObj = null; - for (ObjectState obj : state.states()) { - if (value == obj.virtual) { - virtualObj = obj; - break; - } - } - if (virtualObj != null) { - virtual.add(virtualObj); - } - } - } - }); - for (ObjectState obj : state.states()) { - if (obj.materializedValue == null && obj.lockCount > 0) { - virtual.add(obj); - } - } - - ArrayDeque<ObjectState> queue = new ArrayDeque<>(virtual); - while (!queue.isEmpty()) { - ObjectState obj = queue.removeLast(); - if (obj.materializedValue == null) { - for (ValueNode field : obj.fieldState) { - ObjectState fieldObj = state.objectState(field); - if (fieldObj != null) { - if (fieldObj.materializedValue == null && !virtual.contains(fieldObj)) { - virtual.add(fieldObj); - queue.addLast(fieldObj); - } - } - } - } - } - for (ObjectState obj : virtual) { - EscapeObjectState v; - if (obj.materializedValue == null) { - ValueNode[] fieldState = obj.fieldState.clone(); - for (int i = 0; i < fieldState.length; i++) { - ObjectState valueObj = state.objectState(fieldState[i]); - if (valueObj != null) { - if (valueObj.materializedValue == null) { - fieldState[i] = valueObj.virtual; - } else { - fieldState[i] = valueObj.materializedValue; - } - } - } - v = graph.add(new VirtualObjectState(obj.virtual, fieldState)); - } else { - v = graph.add(new MaterializedObjectState(obj.virtual, obj.materializedValue)); - } - for (int i = 0; i < stateAfter.virtualObjectMappingCount(); i++) { - if (stateAfter.virtualObjectMappingAt(i).object() == v.object()) { - if (reusedVirtualObjects.contains(v.object())) { - stateAfter.virtualObjectMappings().remove(i); - } else { - throw new GraalInternalError("unexpected duplicate virtual state at: %s for %s", node, v.object()); - } - } - } - stateAfter.addVirtualObjectMapping(v); - } - } - usageFound = true; + } + for (Node current : flood) { + for (Node input : current.inputs()) { + flood.add(input); + if (!path.containsKey(input)) { + path.put(input, current); } } - if (!usageFound) { - for (ValueNode input : node.inputs().filter(ValueNode.class)) { - ObjectState obj = state.objectState(input); - if (obj != null) { - replaceWithMaterialized(input, node, insertBefore, state, obj); - usageFound = true; - } - } - Debug.log("unexpected usage of %s: %s\n", node, node.inputs().snapshot()); - } - } - - private void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore) { - assert obj != null; - if (obj.materializedValue == null) { - state.materializeBefore(materializeBefore, obj.virtual); - } - assert obj.materializedValue != null; - } - - private void replaceWithMaterialized(ValueNode value, FixedNode usage, BlockState state, ObjectState obj) { - ensureMaterialized(state, obj, usage); - if (changeGraph) { - usage.replaceFirstInput(value, obj.materializedValue); - } - } - - private void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockState state, ObjectState obj) { - ensureMaterialized(state, obj, materializeBefore); - if (changeGraph) { - usage.replaceFirstInput(value, obj.materializedValue); - } } - @Override - protected BlockState merge(MergeNode merge, List<BlockState> states) { - BlockState newState = new BlockState(); - - newState.objectAliases.putAll(states.get(0).objectAliases); - for (int i = 1; i < states.size(); i++) { - BlockState state = states.get(i); - for (Map.Entry<ValueNode, VirtualObjectNode> entry : states.get(0).objectAliases.entrySet()) { - if (state.objectAliases.containsKey(entry.getKey())) { - assert state.objectAliases.get(entry.getKey()) == entry.getValue(); - } else { - newState.objectAliases.remove(entry.getKey()); - } - } - } - - // Iterative processing: - // Merging the materialized/virtual state of virtual objects can lead to new materializations, which can - // lead to new materializations because of phis, and so on. - - boolean materialized; - do { - materialized = false; - // use a hash set to make the values distinct... - for (VirtualObjectNode object : new HashSet<>(newState.objectAliases.values())) { - ObjectState resultState = newState.objectStates.get(object); - if (resultState == null || resultState.materializedValue == null) { - int virtual = 0; - int lockCount = states.get(0).objectState(object).lockCount; - for (BlockState state : states) { - ObjectState obj = state.objectState(object); - if (obj.materializedValue == null) { - virtual++; - } - assert obj.lockCount == lockCount : "mismatching lock counts"; - } - - if (virtual < states.size()) { - ValueNode materializedValuePhi = changeGraph ? graph.add(new PhiNode(Kind.Object, merge)) : DUMMY_NODE; - for (int i = 0; i < states.size(); i++) { - BlockState state = states.get(i); - ObjectState obj = state.objectState(object); - materialized |= obj.materializedValue == null; - ensureMaterialized(state, obj, merge.forwardEndAt(i)); - if (changeGraph) { - ((PhiNode) materializedValuePhi).addInput(obj.materializedValue); - } - } - newState.addObject(object, new ObjectState(object, materializedValuePhi, lockCount)); - } else { - assert virtual == states.size(); - ValueNode[] values = states.get(0).objectState(object).fieldState.clone(); - PhiNode[] phis = new PhiNode[values.length]; - boolean[] phiCreated = new boolean[values.length]; - int mismatch = 0; - for (int i = 1; i < states.size(); i++) { - BlockState state = states.get(i); - ValueNode[] fields = state.objectState(object).fieldState; - for (int index = 0; index < values.length; index++) { - if (!phiCreated[index] && values[index] != fields[index]) { - mismatch++; - if (changeGraph) { - phis[index] = graph.add(new PhiNode(values[index].kind(), merge)); - } - phiCreated[index] = true; - } - } - } - if (mismatch > 0) { - for (int i = 0; i < states.size(); i++) { - BlockState state = states.get(i); - ValueNode[] fields = state.objectState(object).fieldState; - for (int index = 0; index < values.length; index++) { - if (phiCreated[index]) { - ObjectState obj = state.objectState(fields[index]); - if (obj != null) { - materialized |= obj.materializedValue == null; - ensureMaterialized(state, obj, merge.forwardEndAt(i)); - fields[index] = obj.materializedValue; - } - if (changeGraph) { - phis[index].addInput(fields[index]); - } - } - } - } - for (int index = 0; index < values.length; index++) { - if (phiCreated[index]) { - values[index] = phis[index]; - } - } - } - newState.addObject(object, new ObjectState(object, values, lockCount)); - } - } - } - - for (PhiNode phi : merge.phis().snapshot()) { - if (usages.isMarked(phi) && phi.type() == PhiType.Value) { - materialized |= processPhi(newState, merge, phi, states); - } - } - } while (materialized); - - return newState; - } - - private boolean processPhi(BlockState newState, MergeNode merge, PhiNode phi, List<BlockState> states) { - assert states.size() == phi.valueCount(); - int virtualInputs = 0; - boolean materialized = false; - VirtualObjectNode sameObject = null; - ResolvedJavaType sameType = null; - int sameEntryCount = -1; - for (int i = 0; i < phi.valueCount(); i++) { - ValueNode value = phi.valueAt(i); - ObjectState obj = states.get(i).objectState(value); - if (obj != null) { - if (obj.materializedValue == null) { - virtualInputs++; - if (i == 0) { - sameObject = obj.virtual; - sameType = obj.virtual.type(); - sameEntryCount = obj.virtual.entryCount(); - } else { - if (sameObject != obj.virtual) { - sameObject = null; - } - if (sameType != obj.virtual.type()) { - sameType = null; - } - if (sameEntryCount != obj.virtual.entryCount()) { - sameEntryCount = -1; - } - } - } else { - if (changeGraph) { - phi.setValueAt(i, obj.materializedValue); - } + boolean success = true; + for (Node node : obsoleteNodes) { + if (flood.isMarked(node)) { + trace("offending node path:"); + Node current = node; + while (current != null) { + trace(current.toString()); + current = path.get(current); + if (current != null && current instanceof FixedNode && !obsoleteNodes.contains(current)) { + break; } } - } - boolean materialize = false; - if (virtualInputs == 0) { - // nothing to do... - } else if (virtualInputs == phi.valueCount()) { - if (sameObject != null) { - newState.addAndMarkAlias(sameObject, phi, true); - } else if (sameType != null && sameEntryCount != -1) { - materialize = true; - // throw new GraalInternalError("merge required for %s", sameType); - } else { - materialize = true; - } - } else { - materialize = true; - } - - if (materialize) { - for (int i = 0; i < phi.valueCount(); i++) { - ValueNode value = phi.valueAt(i); - ObjectState obj = states.get(i).objectState(value); - if (obj != null) { - materialized |= obj.materializedValue == null; - replaceWithMaterialized(value, phi, merge.forwardEndAt(i), states.get(i), obj); - } - } - } - return materialized; - } - - @Override - protected BlockState loopBegin(LoopBeginNode loopBegin, BlockState beforeLoopState) { - BlockState state = beforeLoopState; - for (ObjectState obj : state.states()) { - if (obj.fieldState != null) { - for (int i = 0; obj.fieldState != null && i < obj.fieldState.length; i++) { - ValueNode value = obj.fieldState[i]; - ObjectState valueObj = state.objectState(value); - if (valueObj != null) { - ensureMaterialized(state, valueObj, loopBegin.forwardEnd()); - value = valueObj.materializedValue; - } - } - } - } - for (ObjectState obj : state.states()) { - if (obj.fieldState != null) { - for (int i = 0; i < obj.fieldState.length; i++) { - ValueNode value = obj.fieldState[i]; - ObjectState valueObj = state.objectState(value); - if (valueObj != null) { - value = valueObj.materializedValue; - } - if (changeGraph) { - assert value != null; - PhiNode valuePhi = graph.add(new PhiNode(value.kind(), loopBegin)); - valuePhi.addInput(value); - obj.fieldState[i] = valuePhi; - } - } - } + success = false; } - for (PhiNode phi : loopBegin.phis()) { - ObjectState obj = state.objectState(phi.valueAt(0)); - if (obj != null) { - ensureMaterialized(state, obj, loopBegin.forwardEnd()); - if (changeGraph) { - phi.setValueAt(0, obj.materializedValue); - } - } - } - return state.clone(); } - - @Override - protected BlockState loopEnds(LoopBeginNode loopBegin, BlockState loopBeginState, List<BlockState> loopEndStates) { - BlockState state = loopBeginState.clone(); - List<LoopEndNode> loopEnds = loopBegin.orderedLoopEnds(); - for (ObjectState obj : state.states()) { - if (obj.fieldState != null) { - Iterator<LoopEndNode> iter = loopEnds.iterator(); - for (BlockState loopEndState : loopEndStates) { - LoopEndNode loopEnd = iter.next(); - ObjectState endObj = loopEndState.objectState(obj.virtual); - if (endObj.fieldState == null) { - if (changeGraph) { - error("object materialized within loop: %s\n", obj.virtual); - } - metricLoopBailouts.increment(); - throw new BailoutException("object materialized within loop"); - } - for (int i = 0; endObj.fieldState != null && i < endObj.fieldState.length; i++) { - ValueNode value = endObj.fieldState[i]; - ObjectState valueObj = loopEndState.objectState(value); - if (valueObj != null) { - ensureMaterialized(loopEndState, valueObj, loopEnd); - value = valueObj.materializedValue; - } - if (changeGraph) { - ((PhiNode) obj.fieldState[i]).addInput(value); - } - } - } - } - } - for (PhiNode phi : loopBegin.phis()) { - if (phi.valueCount() == 1) { - if (changeGraph) { - phi.replaceAtUsages(phi.valueAt(0)); - } - } else { - assert phi.valueCount() == loopEndStates.size() + 1; - for (int i = 0; i < loopEndStates.size(); i++) { - BlockState loopEndState = loopEndStates.get(i); - ObjectState obj = loopEndState.objectState(phi.valueAt(i + 1)); - if (obj != null) { - ensureMaterialized(loopEndState, obj, loopEnds.get(i)); - if (changeGraph) { - phi.setValueAt(i + 1, obj.materializedValue); - } - } - } - } - } - return state; - } - - @Override - protected BlockState afterSplit(FixedNode node, BlockState oldState) { - return oldState.clone(); - } + return success; } } - -public class PartialEscapeAnalysisPhase extends Phase { - - private final TargetDescription target; - private final GraalCodeCacheProvider runtime; - private final Assumptions assumptions; - - public PartialEscapeAnalysisPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions) { - this.runtime = runtime; - this.target = target; - this.assumptions = assumptions; - } - - @Override - protected void run(StructuredGraph graph) { - iteration(graph, 0); - } - - - private void iteration(final StructuredGraph graph, final int num) { - HashSet<ValueNode> allocations = new HashSet<>(); - SchedulePhase schedule = new SchedulePhase(); - schedule.apply(graph, false); - EscapeAnalysisIteration iteration = null; - try { - iteration = new EscapeAnalysisIteration(graph, schedule, runtime, allocations, false); - iteration.run(); - } catch (BailoutException e) { - // do nothing if the if the escape analysis bails out during the analysis iteration... - return; - } - if (iteration.changed) { - try { - new EscapeAnalysisIteration(graph, schedule, runtime, allocations, true).run(); - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); - } catch (BailoutException e) { - throw new GraalInternalError(e); - } - // next round... - if (num < 2) { - Debug.scope("next", new Runnable() { - @Override - public void run() { - iteration(graph, num + 1); - } - }); - } - } - } -} -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,937 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.virtual.phases.ea; + +import static com.oracle.graal.virtual.phases.ea.PartialEscapeAnalysisPhase.*; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ResolvedJavaType.Representation; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.PhiNode.PhiType; +import com.oracle.graal.nodes.VirtualState.NodeClosure; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.phases.graph.*; +import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; +import com.oracle.graal.phases.graph.ReentrantBlockIterator.LoopInfo; +import com.oracle.graal.phases.schedule.*; +import com.oracle.graal.virtual.nodes.*; + +class PartialEscapeClosure extends BlockIteratorClosure<BlockState> { + + + private static final DebugMetric metricAllocationRemoved = Debug.metric("AllocationRemoved "); + + private final GraphEffectList effects = new GraphEffectList(); + private final HashSet<VirtualObjectNode> reusedVirtualObjects = new HashSet<>(); + private int virtualIds = 0; + + private final NodeBitMap usages; + private final SchedulePhase schedule; + private final MetaAccessProvider runtime; + + public PartialEscapeClosure(NodeBitMap usages, SchedulePhase schedule, MetaAccessProvider runtime) { + this.usages = usages; + this.schedule = schedule; + this.runtime = runtime; + } + + public GraphEffectList getEffects() { + return effects; + } + + public int getVirtualIdCount() { + return virtualIds; + } + + @Override + protected void processBlock(Block block, BlockState state) { + trace("\nBlock: %s (", block); + List<ScheduledNode> nodeList = schedule.getBlockToNodesMap().get(block); + + FixedWithNextNode lastFixedNode = null; + for (Node node : nodeList) { + EscapeOp op = null; + if (node instanceof EscapeAnalyzable) { + op = ((EscapeAnalyzable) node).getEscapeOp(); + } + + if (op != null) { + trace("{{%s}} ", node); + VirtualObjectNode virtualObject = op.virtualObject(virtualIds); + if (virtualObject.isAlive()) { + reusedVirtualObjects.add(virtualObject); + state.addAndMarkAlias(virtualObject, virtualObject, usages); + } else { + effects.addFloatingNode(virtualObject); + } + ValueNode[] fieldState = op.fieldState(); + for (int i = 0; i < fieldState.length; i++) { + fieldState[i] = state.getScalarAlias(fieldState[i]); + } + state.addObject(virtualObject, new ObjectState(virtualObject, fieldState, op.lockCount())); + state.addAndMarkAlias(virtualObject, (ValueNode) node, usages); + effects.deleteFixedNode((FixedWithNextNode) node); + virtualIds++; + metricAllocationRemoved.increment(); + } else { + if (usages.isMarked(node)) { + trace("[[%s]] ", node); + processNode((ValueNode) node, lastFixedNode == null ? null : lastFixedNode.next(), state); + } else { + trace("%s ", node); + } + } + + if (node instanceof FixedWithNextNode && node.isAlive()) { + lastFixedNode = (FixedWithNextNode) node; + } + } + trace(")\n end state: %s\n", state); + } + + private void processNode(final ValueNode node, FixedNode insertBefore, final BlockState state) { + boolean usageFound = false; + if (node instanceof PiNode || node instanceof ValueProxyNode) { + ValueNode value = node instanceof PiNode ? ((PiNode) node).object() : ((ValueProxyNode) node).value(); + ObjectState obj = state.getObjectState(value); + if (obj != null) { + if (obj.isVirtual()) { + state.addAndMarkAlias(obj.virtual, node, usages); + } else { + effects.replaceFirstInput(node, value, obj.getMaterializedValue()); + } + usageFound = true; + } + } else if (node instanceof CheckCastNode) { + CheckCastNode x = (CheckCastNode) node; + ObjectState obj = state.getObjectState(x.object()); + if (obj != null) { + if (obj.isVirtual()) { + if (obj.virtual.type().isSubtypeOf(x.type())) { + state.addAndMarkAlias(obj.virtual, x, usages); + effects.deleteFixedNode(x); + } else { + replaceWithMaterialized(x.object(), x, state, obj); + } + } else { + effects.replaceFirstInput(x, x.object(), obj.getMaterializedValue()); + } + usageFound = true; + } + } else if (node instanceof IsNullNode) { + IsNullNode x = (IsNullNode) node; + if (state.getObjectState(x.object()) != null) { + replaceAtUsages(state, x, ConstantNode.forBoolean(false, node.graph())); + usageFound = true; + } + } else if (node instanceof AccessMonitorNode) { + AccessMonitorNode x = (AccessMonitorNode) node; + ObjectState obj = state.getObjectState(x.object()); + if (obj != null) { + Debug.log("monitor operation %s on %s\n", x, obj.virtual); + if (node instanceof MonitorEnterNode) { + obj.incLockCount(); + } else { + assert node instanceof MonitorExitNode; + obj.decLockCount(); + } + if (obj.isVirtual()) { + effects.replaceFirstInput(node, x.object(), obj.virtual); + effects.eliminateMonitor(x); + } else { + effects.replaceFirstInput(node, x.object(), obj.getMaterializedValue()); + } + usageFound = true; + } + } else if (node instanceof CyclicMaterializeStoreNode) { + CyclicMaterializeStoreNode x = (CyclicMaterializeStoreNode) node; + ObjectState obj = state.getObjectState(x.object()); + if (obj != null) { + if (obj.virtual instanceof VirtualArrayNode) { + obj.setEntry(x.targetIndex(), x.value()); + } else { + VirtualInstanceNode instance = (VirtualInstanceNode) obj.virtual; + obj.setEntry(instance.fieldIndex(x.targetField()), x.value()); + } + effects.deleteFixedNode(x); + usageFound = true; + } + } else if (node instanceof LoadFieldNode) { + LoadFieldNode x = (LoadFieldNode) node; + ObjectState obj = state.getObjectState(x.object()); + if (obj != null) { + VirtualInstanceNode virtual = (VirtualInstanceNode) obj.virtual; + int fieldIndex = virtual.fieldIndex(x.field()); + if (fieldIndex == -1) { + // the field does not exist in the virtual object + ensureMaterialized(state, obj, x); + } + if (obj.isVirtual()) { + ValueNode result = obj.getEntry(fieldIndex); + ObjectState resultObj = state.getObjectState(result); + if (resultObj != null) { + state.addAndMarkAlias(resultObj.virtual, x, usages); + } else { + replaceAtUsages(state, x, result); + } + effects.deleteFixedNode(x); + } else { + effects.replaceFirstInput(x, x.object(), obj.getMaterializedValue()); + } + usageFound = true; + } + } else if (node instanceof StoreFieldNode) { + StoreFieldNode x = (StoreFieldNode) node; + ValueNode object = x.object(); + ValueNode value = x.value(); + ObjectState obj = state.getObjectState(object); + if (obj != null) { + VirtualInstanceNode virtual = (VirtualInstanceNode) obj.virtual; + int fieldIndex = virtual.fieldIndex(x.field()); + if (fieldIndex == -1) { + // the field does not exist in the virtual object + ensureMaterialized(state, obj, x); + } + if (obj.isVirtual()) { + obj.setEntry(fieldIndex, state.getScalarAlias(value)); + effects.deleteFixedNode(x); + } else { + effects.replaceFirstInput(x, object, obj.getMaterializedValue()); + ObjectState valueObj = state.getObjectState(value); + if (valueObj != null) { + replaceWithMaterialized(value, x, state, valueObj); + } + } + usageFound = true; + } else { + ObjectState valueObj = state.getObjectState(value); + if (valueObj != null) { + replaceWithMaterialized(value, x, state, valueObj); + usageFound = true; + } + } + } else if (node instanceof LoadIndexedNode) { + LoadIndexedNode x = (LoadIndexedNode) node; + ValueNode array = x.array(); + ObjectState arrayObj = state.getObjectState(array); + if (arrayObj != null) { + if (arrayObj.isVirtual()) { + ValueNode indexValue = state.getScalarAlias(x.index()); + int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1; + if (index < 0 || index >= arrayObj.getEntries().length) { + // out of bounds or not constant + replaceWithMaterialized(array, x, state, arrayObj); + } else { + ValueNode result = arrayObj.getEntry(index); + ObjectState resultObj = state.getObjectState(result); + if (resultObj != null) { + state.addAndMarkAlias(resultObj.virtual, x, usages); + } else { + replaceAtUsages(state, x, result); + } + effects.deleteFixedNode(x); + } + } else { + effects.replaceFirstInput(x, array, arrayObj.getMaterializedValue()); + } + usageFound = true; + } + } else if (node instanceof StoreIndexedNode) { + StoreIndexedNode x = (StoreIndexedNode) node; + ValueNode array = x.array(); + ValueNode value = x.value(); + ObjectState arrayObj = state.getObjectState(array); + ObjectState valueObj = state.getObjectState(value); + + if (arrayObj != null) { + if (arrayObj.isVirtual()) { + ValueNode indexValue = state.getScalarAlias(x.index()); + int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1; + if (index < 0 || index >= arrayObj.getEntries().length) { + // out of bounds or not constant + replaceWithMaterialized(array, x, state, arrayObj); + if (valueObj != null) { + replaceWithMaterialized(value, x, state, valueObj); + } + } else { + arrayObj.setEntry(index, state.getScalarAlias(value)); + effects.deleteFixedNode(x); + } + } else { + effects.replaceFirstInput(x, array, arrayObj.getMaterializedValue()); + if (valueObj != null) { + replaceWithMaterialized(value, x, state, valueObj); + } + } + usageFound = true; + } else { + if (valueObj != null) { + replaceWithMaterialized(value, x, state, valueObj); + usageFound = true; + } + } + } else if (node instanceof RegisterFinalizerNode) { + RegisterFinalizerNode x = (RegisterFinalizerNode) node; + ObjectState obj = state.getObjectState(x.object()); + if (obj != null) { + replaceWithMaterialized(x.object(), x, state, obj); + usageFound = true; + } + } else if (node instanceof ArrayLengthNode) { + ArrayLengthNode x = (ArrayLengthNode) node; + ObjectState obj = state.getObjectState(x.array()); + if (obj != null) { + replaceAtUsages(state, x, ConstantNode.forInt(((VirtualArrayNode) obj.virtual).entryCount(), node.graph())); + effects.deleteFixedNode(x); + usageFound = true; + } + } else if (node instanceof LoadHubNode) { + LoadHubNode x = (LoadHubNode) node; + ObjectState obj = state.getObjectState(x.object()); + if (obj != null) { + replaceAtUsages(state, x, ConstantNode.forConstant(obj.virtual.type().getEncoding(Representation.ObjectHub), runtime, node.graph())); + effects.deleteFixedNode(x); + usageFound = true; + } + } else if (node instanceof ReturnNode) { + ReturnNode x = (ReturnNode) node; + ObjectState obj = state.getObjectState(x.result()); + if (obj != null) { + replaceWithMaterialized(x.result(), x, state, obj); + usageFound = true; + } + } else if (node instanceof MethodCallTargetNode) { + for (ValueNode argument : ((MethodCallTargetNode) node).arguments()) { + ObjectState obj = state.getObjectState(argument); + if (obj != null) { + replaceWithMaterialized(argument, node, insertBefore, state, obj); + usageFound = true; + } + } + } else if (node instanceof ObjectEqualsNode) { + ObjectEqualsNode x = (ObjectEqualsNode) node; + ObjectState xObj = state.getObjectState(x.x()); + ObjectState yObj = state.getObjectState(x.y()); + boolean xVirtual = xObj != null && xObj.isVirtual(); + boolean yVirtual = yObj != null && yObj.isVirtual(); + + if (xVirtual ^ yVirtual) { + // one of them is virtual: they can never be the same objects + replaceAtUsages(state, x, ConstantNode.forBoolean(false, node.graph())); + usageFound = true; + } else if (xVirtual && yVirtual) { + // both are virtual: check if they refer to the same object + replaceAtUsages(state, x, ConstantNode.forBoolean(xObj == yObj, node.graph())); + usageFound = true; + } else { + if (xObj != null || yObj != null) { + if (xObj != null) { + assert !xObj.isVirtual(); + effects.replaceFirstInput(x, x.x(), xObj.getMaterializedValue()); + } + if (yObj != null) { + assert !yObj.isVirtual(); + effects.replaceFirstInput(x, x.y(), yObj.getMaterializedValue()); + } + usageFound = true; + } + } + } else if (node instanceof MergeNode) { + usageFound = true; + } else if (node instanceof UnsafeLoadNode || node instanceof UnsafeStoreNode || node instanceof CompareAndSwapNode || node instanceof SafeReadNode) { + for (ValueNode input : node.inputs().filter(ValueNode.class)) { + ObjectState obj = state.getObjectState(input); + if (obj != null) { + replaceWithMaterialized(input, node, insertBefore, state, obj); + usageFound = true; + } + } + } + if (node.isAlive() && node instanceof StateSplit) { + StateSplit split = (StateSplit) node; + FrameState stateAfter = split.stateAfter(); + if (stateAfter != null) { + if (stateAfter.usages().size() > 1) { + stateAfter = (FrameState) stateAfter.copyWithInputs(); + split.setStateAfter(stateAfter); + } + final HashSet<ObjectState> virtual = new HashSet<>(); + stateAfter.applyToNonVirtual(new NodeClosure<ValueNode>() { + + @Override + public void apply(Node usage, ValueNode value) { + ObjectState valueObj = state.getObjectState(value); + if (valueObj != null) { + virtual.add(valueObj); + effects.replaceFirstInput(usage, value, valueObj.virtual); + } else if (value instanceof VirtualObjectNode) { + ObjectState virtualObj = null; + for (ObjectState obj : state.getStates()) { + if (value == obj.virtual) { + virtualObj = obj; + break; + } + } + if (virtualObj != null) { + virtual.add(virtualObj); + } + } + } + }); + for (ObjectState obj : state.getStates()) { + if (obj.isVirtual() && obj.getLockCount() > 0) { + virtual.add(obj); + } + } + + ArrayDeque<ObjectState> queue = new ArrayDeque<>(virtual); + while (!queue.isEmpty()) { + ObjectState obj = queue.removeLast(); + if (obj.isVirtual()) { + for (ValueNode field : obj.getEntries()) { + ObjectState fieldObj = state.getObjectState(field); + if (fieldObj != null) { + if (fieldObj.isVirtual() && !virtual.contains(fieldObj)) { + virtual.add(fieldObj); + queue.addLast(fieldObj); + } + } + } + } + } + for (ObjectState obj : virtual) { + EscapeObjectState v; + if (obj.isVirtual()) { + ValueNode[] fieldState = obj.getEntries().clone(); + for (int i = 0; i < fieldState.length; i++) { + ObjectState valueObj = state.getObjectState(fieldState[i]); + if (valueObj != null) { + if (valueObj.isVirtual()) { + fieldState[i] = valueObj.virtual; + } else { + fieldState[i] = valueObj.getMaterializedValue(); + } + } + } + v = new VirtualObjectState(obj.virtual, fieldState); + } else { + v = new MaterializedObjectState(obj.virtual, obj.getMaterializedValue()); + } + effects.addVirtualMapping(stateAfter, v, reusedVirtualObjects); + } + } + usageFound = true; + } + if (!usageFound) { + for (ValueNode input : node.inputs().filter(ValueNode.class)) { + ObjectState obj = state.getObjectState(input); + if (obj != null) { + replaceWithMaterialized(input, node, insertBefore, state, obj); + usageFound = true; + } + } + Debug.log("unexpected usage of %s: %s\n", node, node.inputs().snapshot()); + } + } + + private void replaceAtUsages(final BlockState state, ValueNode x, ValueNode value) { + effects.replaceAtUsages(x, value); + state.addScalarAlias(x, value); + } + + private void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore) { + assert obj != null; + if (obj.isVirtual()) { + state.materializeBefore(materializeBefore, obj.virtual, effects); + } + assert !obj.isVirtual(); + } + + private void replaceWithMaterialized(ValueNode value, FixedNode usage, BlockState state, ObjectState obj) { + ensureMaterialized(state, obj, usage); + effects.replaceFirstInput(usage, value, obj.getMaterializedValue()); + } + + private void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockState state, ObjectState obj) { + ensureMaterialized(state, obj, materializeBefore); + effects.replaceFirstInput(usage, value, obj.getMaterializedValue()); + } + + @Override + protected BlockState merge(MergeNode merge, List<BlockState> states) { + + BlockState newState = BlockState.meetAliases(states); + + // Iterative processing: + // Merging the materialized/virtual state of virtual objects can lead to new materializations, which can + // lead to new materializations because of phis, and so on. + + boolean materialized; + do { + materialized = false; + // use a hash set to make the values distinct... + for (VirtualObjectNode object : newState.getVirtualObjects()) { + ObjectState resultState = newState.getObjectStateOptional(object); + if (resultState == null || resultState.isVirtual()) { + int virtual = 0; + ObjectState startObj = states.get(0).getObjectState(object); + int lockCount = startObj.getLockCount(); + boolean locksMatch = true; + ValueNode singleValue = startObj.isVirtual() ? null : startObj.getMaterializedValue(); + for (BlockState state : states) { + ObjectState obj = state.getObjectState(object); + if (obj.isVirtual()) { + virtual++; + singleValue = null; + } else { + if (obj.getMaterializedValue() != singleValue) { + singleValue = null; + } + } + locksMatch &= obj.getLockCount() == lockCount; + } + + assert virtual < states.size() || locksMatch : "mismatching lock counts at " + merge; + + if (virtual < states.size()) { + if (singleValue == null) { + PhiNode materializedValuePhi = new PhiNode(Kind.Object, merge); + effects.addFloatingNode(materializedValuePhi); + for (int i = 0; i < states.size(); i++) { + BlockState state = states.get(i); + ObjectState obj = state.getObjectState(object); + materialized |= obj.isVirtual(); + ensureMaterialized(state, obj, merge.forwardEndAt(i)); + effects.addPhiInput(materializedValuePhi, obj.getMaterializedValue()); + } + newState.addObject(object, new ObjectState(object, materializedValuePhi, lockCount)); + } else { + newState.addObject(object, new ObjectState(object, singleValue, lockCount)); + } + } else { + assert virtual == states.size(); + ValueNode[] values = startObj.getEntries().clone(); + PhiNode[] phis = new PhiNode[values.length]; + int mismatch = 0; + for (int i = 1; i < states.size(); i++) { + BlockState state = states.get(i); + ValueNode[] fields = state.getObjectState(object).getEntries(); + for (int index = 0; index < values.length; index++) { + if (phis[index] == null && values[index] != fields[index]) { + mismatch++; + phis[index] = new PhiNode(values[index].kind(), merge); + effects.addFloatingNode(phis[index]); + } + } + } + if (mismatch > 0) { + for (int i = 0; i < states.size(); i++) { + BlockState state = states.get(i); + ValueNode[] fields = state.getObjectState(object).getEntries(); + for (int index = 0; index < values.length; index++) { + if (phis[index] != null) { + ObjectState obj = state.getObjectState(fields[index]); + if (obj != null) { + materialized |= obj.isVirtual(); + ensureMaterialized(state, obj, merge.forwardEndAt(i)); + fields[index] = obj.getMaterializedValue(); + } + effects.addPhiInput(phis[index], fields[index]); + } + } + } + for (int index = 0; index < values.length; index++) { + if (phis[index] != null) { + values[index] = phis[index]; + } + } + } + newState.addObject(object, new ObjectState(object, values, lockCount)); + } + } + } + + for (PhiNode phi : merge.phis().snapshot()) { + if (usages.isMarked(phi) && phi.type() == PhiType.Value) { + materialized |= processPhi(newState, merge, phi, states); + } + } + } while (materialized); + + return newState; + } + + private boolean processPhi(BlockState newState, MergeNode merge, PhiNode phi, List<BlockState> states) { + assert states.size() == phi.valueCount(); + int virtualInputs = 0; + boolean materialized = false; + VirtualObjectNode sameObject = null; + ResolvedJavaType sameType = null; + int sameEntryCount = -1; + for (int i = 0; i < phi.valueCount(); i++) { + ValueNode value = phi.valueAt(i); + ObjectState obj = states.get(i).getObjectState(value); + if (obj != null) { + if (obj.isVirtual()) { + virtualInputs++; + if (i == 0) { + sameObject = obj.virtual; + sameType = obj.virtual.type(); + sameEntryCount = obj.virtual.entryCount(); + } else { + if (sameObject != obj.virtual) { + sameObject = null; + } + if (sameType != obj.virtual.type()) { + sameType = null; + } + if (sameEntryCount != obj.virtual.entryCount()) { + sameEntryCount = -1; + } + } + } else { + effects.setPhiInput(phi, i, obj.getMaterializedValue()); + } + } + } + boolean materialize = false; + if (virtualInputs == 0) { + // nothing to do... + } else if (virtualInputs == phi.valueCount()) { + if (sameObject != null) { + newState.addAndMarkAlias(sameObject, phi, usages); + } else if (sameType != null && sameEntryCount != -1) { + materialize = true; + // throw new GraalInternalError("merge required for %s", sameType); + } else { + materialize = true; + } + } else { + materialize = true; + } + + if (materialize) { + for (int i = 0; i < phi.valueCount(); i++) { + ValueNode value = phi.valueAt(i); + ObjectState obj = states.get(i).getObjectState(value); + if (obj != null) { + materialized |= obj.isVirtual(); + replaceWithMaterialized(value, phi, merge.forwardEndAt(i), states.get(i), obj); + } + } + } + return materialized; + } + + @Override + protected BlockState afterSplit(FixedNode node, BlockState oldState) { + return oldState.cloneState(); + } + + @Override + protected List<BlockState> processLoop(Loop loop, BlockState initialState) { + GraphEffectList successEffects = new GraphEffectList(); + HashSet<PhiDesc> phis = new HashSet<>(); + for (int iteration = 0; iteration < 10; iteration++) { + BlockState state = initialState.cloneState(); + int checkpoint = effects.checkpoint(); + + for (PhiDesc desc : phis) { + ObjectState obj = state.getObjectState(desc.virtualObject); + if (obj.isVirtual()) { + ValueNode value = obj.getEntry(desc.fieldIndex); + ObjectState valueObj = state.getObjectState(value); + if (valueObj != null) { + assert !valueObj.isVirtual(); + value = valueObj.getMaterializedValue(); + } + + PhiNode phiNode = new PhiNode(value.kind(), loop.loopBegin()); + effects.addFloatingNode(phiNode); + effects.addPhiInput(phiNode, value); + obj.setEntry(desc.fieldIndex, phiNode); + } + } + + for (PhiNode phi : loop.loopBegin().phis()) { + if (usages.isMarked(phi) && phi.type() == PhiType.Value) { + ObjectState initialObj = initialState.getObjectState(phi.valueAt(0)); + if (initialObj != null) { + if (initialObj.isVirtual()) { + state.addAndMarkAlias(initialObj.virtual, phi, usages); + } else { + successEffects.setPhiInput(phi, 0, initialObj.getMaterializedValue()); + } + } + } + } + + effects.incLevel(); + LoopInfo<BlockState> info = ReentrantBlockIterator.processLoop(this, loop, state.cloneState()); + + List<BlockState> loopEndStates = info.endStates; + List<Block> predecessors = loop.header.getPredecessors(); + HashSet<VirtualObjectNode> additionalMaterializations = new HashSet<>(); + int oldPhiCount = phis.size(); + for (int i = 1; i < predecessors.size(); i++) { + processLoopEnd(loop.loopBegin(), (LoopEndNode) predecessors.get(i).getEndNode(), state, loopEndStates.get(i - 1), successEffects, additionalMaterializations, phis); + } + if (additionalMaterializations.isEmpty() && oldPhiCount == phis.size()) { + effects.addAll(successEffects); + + assert info.exitStates.size() == loop.exits.size(); + for (int i = 0; i < loop.exits.size(); i++) { + BlockState exitState = info.exitStates.get(i); + assert exitState != null : "no loop exit state at " + loop.exits.get(i) + " / " + loop.header; + processLoopExit((LoopExitNode) loop.exits.get(i).getBeginNode(), state, exitState); + } + + effects.decLevel(); + return info.exitStates; + } else { + successEffects.clear(); + effects.backtrack(checkpoint); + effects.decLevel(); + for (VirtualObjectNode virtualObject : additionalMaterializations) { + ObjectState obj = initialState.getObjectState(virtualObject); + if (obj.isVirtual()) { + initialState.materializeBefore(loop.loopBegin().forwardEnd(), virtualObject, effects); + } + } + } + } + + throw new GraalInternalError("too many iterations at %s", loop); + } + + private void processLoopExit(LoopExitNode exitNode, BlockState initialState, BlockState exitState) { + HashMap<VirtualObjectNode, ValueProxyNode> proxies = new HashMap<>(); + + for (ValueProxyNode proxy : exitNode.proxies()) { + ObjectState obj = exitState.getObjectState(proxy.value()); + if (obj != null) { + proxies.put(obj.virtual, proxy); + } + } + for (ObjectState obj : exitState.getStates()) { + ObjectState initialObj = initialState.getObjectStateOptional(obj.virtual); + if (obj.isVirtual()) { + for (int i = 0; i < obj.getEntries().length; i++) { + ValueNode value = obj.getEntry(i); + ObjectState valueObj = exitState.getObjectState(value); + if (valueObj == null) { + if ((value instanceof PhiNode && ((PhiNode) value).merge() == exitNode.loopBegin()) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) { + ValueProxyNode proxy = new ValueProxyNode(value, exitNode, PhiType.Value); + obj.setEntry(i, proxy); + effects.addFloatingNode(proxy); + } + } + } + } else { + if (initialObj == null || initialObj.isVirtual()) { + ValueProxyNode proxy = proxies.get(obj.virtual); + if (proxy == null) { + proxy = new ValueProxyNode(obj.getMaterializedValue(), exitNode, PhiType.Value); + effects.addFloatingNode(proxy); + } else { + effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue()); + // nothing to do - will be handled in processNode + } + obj.updateMaterializedValue(proxy); + } else { + assert initialObj.getMaterializedValue() == obj.getMaterializedValue() : "materialized value is not allowed to change within loops: " + initialObj.getMaterializedValue() + + " vs. " + obj.getMaterializedValue(); + } + } + } + } + + private final class PhiDesc { + + public final VirtualObjectNode virtualObject; + public final int fieldIndex; + + public PhiDesc(VirtualObjectNode virtualObject, int fieldIndex) { + this.virtualObject = virtualObject; + this.fieldIndex = fieldIndex; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = fieldIndex; + result = prime * result + ((virtualObject == null) ? 0 : virtualObject.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + PhiDesc other = (PhiDesc) obj; + return virtualObject == other.virtualObject && fieldIndex == other.fieldIndex; + } + } + + private void processLoopEnd(LoopBeginNode loopBegin, LoopEndNode loopEnd, BlockState initialState, BlockState loopEndState, GraphEffectList successEffects, + Set<VirtualObjectNode> additionalMaterializations, HashSet<PhiDesc> phis) { + assert loopEnd.loopBegin() == loopBegin; + boolean materialized; + do { + materialized = false; + for (ObjectState state : initialState.getStates()) { + ObjectState endState = loopEndState.getObjectState(state.virtual); + if (state.isVirtual()) { + if (endState.isVirtual()) { + assert state.getEntries().length == endState.getEntries().length; + for (int i = 0; endState.isVirtual() && i < state.getEntries().length; i++) { + ValueNode value = state.getEntry(i); + ValueNode endValue = endState.getEntry(i); + ObjectState valueObj = initialState.getObjectState(value); + ObjectState endValueObj = loopEndState.getObjectState(endValue); + + if (valueObj != null) { + if (valueObj.isVirtual()) { + if (endValueObj == null || !endValueObj.isVirtual() || valueObj.virtual != endValueObj.virtual) { + additionalMaterializations.add(valueObj.virtual); + } else { + // endValue is also virtual and refers to the same virtual object, so we're + // good. + } + } + } else { + if (value instanceof PhiNode && ((PhiNode) value).merge() == loopBegin) { + if (endValueObj != null) { + if (endValueObj.isVirtual()) { + loopEndState.materializeBefore(loopEnd, endValueObj.virtual, successEffects); + materialized = true; + } + } + } + } + } + } else { + additionalMaterializations.add(state.virtual); + } + } + } + for (PhiNode phi : loopBegin.phis().snapshot()) { + if (usages.isMarked(phi) && phi.type() == PhiType.Value) { + ObjectState initialObj = initialState.getObjectState(phi.valueAt(0)); + boolean initialMaterialized = initialObj == null || !initialObj.isVirtual(); + + ObjectState loopEndObj = loopEndState.getObjectState(phi.valueAt(loopEnd)); + if (loopEndObj == null || !loopEndObj.isVirtual()) { + if (loopEndObj != null) { + successEffects.setPhiInput(phi, loopBegin.phiPredecessorIndex(loopEnd), loopEndObj.getMaterializedValue()); + } + if (!initialMaterialized) { + additionalMaterializations.add(initialObj.virtual); + } + } else { + if (initialMaterialized) { + loopEndState.materializeBefore(loopEnd, loopEndObj.virtual, successEffects); + materialized = true; + } else { + if (loopEndObj.virtual != initialObj.virtual) { + additionalMaterializations.add(initialObj.virtual); + } + } + } + } + } + } while (materialized); + + for (ObjectState state : initialState.getStates()) { + ObjectState endState = loopEndState.getObjectState(state.virtual); + if (state.isVirtual()) { + if (endState.isVirtual()) { + assert state.getEntries().length == endState.getEntries().length; + for (int i = 0; i < state.getEntries().length; i++) { + ValueNode value = state.getEntry(i); + ValueNode endValue = endState.getEntry(i); + ObjectState valueObj = initialState.getObjectState(value); + ObjectState endValueObj = loopEndState.getObjectState(endValue); + + if (valueObj != null) { + if (valueObj.isVirtual()) { + if (endValueObj == null || !endValueObj.isVirtual() || valueObj.virtual != endValueObj.virtual) { + assert !additionalMaterializations.isEmpty(); + } else { + // endValue is also virtual and refers to the same virtual object, so we're + // good. + } + } else { + if ((endValueObj != null && endValueObj.getMaterializedValue() != valueObj.getMaterializedValue()) || (endValueObj == null && valueObj.getMaterializedValue() != endValue)) { + phis.add(new PhiDesc(state.virtual, i)); + } else { + // either endValue has the same materialized value as value or endValue is the + // same as the materialized value, so we're good. + } + } + } else { + if (value instanceof PhiNode && ((PhiNode) value).merge() == loopBegin) { + if (endValueObj != null) { + if (endValueObj.isVirtual()) { + assert !additionalMaterializations.isEmpty(); + } + successEffects.addPhiInput((PhiNode) value, endValueObj.getMaterializedValue()); + } else { + successEffects.addPhiInput((PhiNode) value, endValue); + } + } else if (value != endValue) { + phis.add(new PhiDesc(state.virtual, i)); + } + } + } + } else { + // endState.materializedValue != null + assert !additionalMaterializations.isEmpty(); + } + } else { + // state.materializedValue != null + if (endState.isVirtual()) { + // throw new GraalInternalError("un-materialized object state at %s", loopEnd); + } else { + if (state.getMaterializedValue() != endState.getMaterializedValue()) { + // throw new GraalInternalError("changed materialized value during loop: %s vs %s", + // state.materializedValue, endState.materializedValue); + } + } + } + } + } +}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PostOrderBlockIterator.java Fri Nov 09 13:32:53 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,183 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.virtual.phases.ea; - -import java.util.*; - -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.cfg.*; - -public abstract class PostOrderBlockIterator<T extends MergeableBlockState<T>> { - - private final NodeBitMap visitedEnds; - private final Deque<Block> blockQueue; - private final IdentityHashMap<FixedNode, T> blockEndStates; - private final IdentityHashMap<LoopBeginNode, T> loopBeginStates; - private final Block start; - - private T state; - - public PostOrderBlockIterator(StructuredGraph graph, Block start, T initialState) { - visitedEnds = graph.createNodeBitMap(); - blockQueue = new ArrayDeque<>(); - blockEndStates = new IdentityHashMap<>(); - loopBeginStates = new IdentityHashMap<>(); - this.start = start; - this.state = initialState; - } - - public void apply() { - Block current = start; - - do { - processBlock(current, state); - - if (current.getSuccessors().isEmpty()) { - // nothing to do... - } else if (current.getSuccessors().size() == 1) { - Block successor = current.getSuccessors().get(0); - if (successor.isLoopHeader()) { - if (current.getEndNode() instanceof LoopEndNode) { - finishLoopEnds((LoopEndNode) current.getEndNode()); - } else { - LoopBeginNode loopBegin = (LoopBeginNode) successor.getBeginNode(); - state = loopBegin(loopBegin, state); - loopBeginStates.put(loopBegin, state); - state = state.clone(); - current = successor; - continue; - } - } else { - if (successor.getBeginNode() instanceof LoopExitNode) { - assert successor.getPredecessors().size() == 1; - current = successor; - continue; - } else { - if (current.getEndNode() instanceof EndNode) { - assert successor.getPredecessors().size() > 1 : "invalid block schedule at " + successor.getBeginNode(); - queueMerge((EndNode) current.getEndNode(), successor); - } else { - assert successor.getPredecessors().size() == 1 : "invalid block schedule at " + successor.getBeginNode(); - current = successor; - continue; - } - } - } - } else { - assert current.getSuccessors().size() > 1; - queueSuccessors(current); - } - current = nextQueuedBlock(); - } while (current != null); - } - - protected abstract void processBlock(Block block, T currentState); - - protected abstract T merge(MergeNode merge, List<T> states); - - protected abstract T loopBegin(LoopBeginNode loopBegin, T beforeLoopState); - - protected abstract T loopEnds(LoopBeginNode loopBegin, T loopBeginState, List<T> loopEndStates); - - protected abstract T afterSplit(FixedNode node, T oldState); - - - private void queueSuccessors(Block current) { - blockEndStates.put(current.getEndNode(), state); - for (Block block : current.getSuccessors()) { - blockQueue.addFirst(block); - } - } - - private Block nextQueuedBlock() { - int maxIterations = blockQueue.size(); - while (maxIterations-- > 0) { - Block block = blockQueue.removeFirst(); - if (block.getPredecessors().size() > 1) { - MergeNode merge = (MergeNode) block.getBeginNode(); - ArrayList<T> states = new ArrayList<>(merge.forwardEndCount()); - for (int i = 0; i < merge.forwardEndCount(); i++) { - T other = blockEndStates.get(merge.forwardEndAt(i)); - assert other != null; - states.add(other); - } - state = merge(merge, states); - if (state != null) { - return block; - } else { - blockQueue.addLast(block); - } - } else { - assert block.getPredecessors().size() == 1; - assert block.getBeginNode().predecessor() != null; - state = afterSplit(block.getBeginNode(), blockEndStates.get(block.getBeginNode().predecessor())); - return block; - } - } - return null; - } - - private void queueMerge(EndNode end, Block mergeBlock) { - assert !visitedEnds.isMarked(end); - assert !blockEndStates.containsKey(end); - blockEndStates.put(end, state); - visitedEnds.mark(end); - MergeNode merge = end.merge(); - boolean endsVisited = true; - for (int i = 0; i < merge.forwardEndCount(); i++) { - if (!visitedEnds.isMarked(merge.forwardEndAt(i))) { - endsVisited = false; - break; - } - } - if (endsVisited) { - blockQueue.addFirst(mergeBlock); - } - } - - private void finishLoopEnds(LoopEndNode end) { - assert !visitedEnds.isMarked(end); - assert !blockEndStates.containsKey(end); - blockEndStates.put(end, state); - visitedEnds.mark(end); - LoopBeginNode begin = end.loopBegin(); - boolean endsVisited = true; - for (LoopEndNode le : begin.loopEnds()) { - if (!visitedEnds.isMarked(le)) { - endsVisited = false; - break; - } - } - if (endsVisited) { - ArrayList<T> states = new ArrayList<>(begin.loopEnds().count()); - for (LoopEndNode le : begin.orderedLoopEnds()) { - states.add(blockEndStates.get(le)); - } - T loopBeginState = loopBeginStates.get(begin); - if (loopBeginState != null) { - loopEnds(begin, loopBeginState, states); - } - } - } -}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/experimental/BlockIteratorClosure.java Fri Nov 09 13:32:53 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.virtual.phases.ea.experimental; - -import java.util.*; - -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.cfg.*; -import com.oracle.graal.virtual.phases.ea.*; - -public abstract class BlockIteratorClosure<T extends MergeableBlockState<T>> { - - public static class LoopInfo<T extends MergeableBlockState<T>> { - - public final List<T> endStates = new ArrayList<>(); - public final List<T> exitStates = new ArrayList<>(); - } - - protected abstract void processBlock(Block block, T currentState); - - protected abstract T merge(MergeNode merge, List<T> states); - - protected abstract T afterSplit(FixedNode node, T oldState); - - protected abstract List<T> processLoop(Loop loop, T initialState); -}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/experimental/EffectList.java Fri Nov 09 13:32:53 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.virtual.phases.ea.experimental; - -import java.lang.reflect.*; -import java.util.*; - -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; - -public class EffectList implements Iterable<EffectList.Effect> { - - public abstract static class Effect { - - public boolean isVisible() { - return true; - } - - @Override - public String toString() { - StringBuilder str = new StringBuilder(); - for (Field field : getClass().getDeclaredFields()) { - String name = field.getName(); - if (name.contains("$")) { - name = name.substring(name.indexOf('$') + 1); - } - if (!Modifier.isStatic(field.getModifiers()) && !name.equals("0")) { - try { - field.setAccessible(true); - str.append(str.length() > 0 ? ", " : "").append(name).append("=").append(format(field.get(this))); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - return name() + " [" + str + "]"; - } - - private static String format(Object object) { - if (object != null && Object[].class.isAssignableFrom(object.getClass())) { - return Arrays.toString((Object[]) object); - } - return "" + object; - } - - public abstract String name(); - - public abstract void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes); - } - - private Effect[] effects = new Effect[16]; - private int[] level = new int[16]; - private int size; - private int currentLevel; - - public void add(Effect effect) { - if (effects.length == size) { - effects = Arrays.copyOf(effects, effects.length * 2); - level = Arrays.copyOf(level, effects.length); - } - level[size] = currentLevel; - effects[size++] = effect; - } - - public void addAll(Collection< ? extends Effect> list) { - int length = effects.length; - if (size + list.size() > length) { - while (size + list.size() > length) { - length *= 2; - } - effects = Arrays.copyOf(effects, length); - level = Arrays.copyOf(level, effects.length); - } - for (Effect effect : list) { - level[size] = currentLevel; - effects[size++] = effect; - } - } - - public void addAll(EffectList list) { - int length = effects.length; - if (size + list.size > length) { - while (size + list.size > length) { - length *= 2; - } - effects = Arrays.copyOf(effects, length); - level = Arrays.copyOf(level, effects.length); - } - for (Effect effect : list) { - level[size] = currentLevel; - effects[size++] = effect; - } - } - - public int checkpoint() { - return size; - } - - public int size() { - return size; - } - - public void backtrack(int checkpoint) { - assert checkpoint <= size; - size = checkpoint; - } - - @Override - public Iterator<Effect> iterator() { - return new Iterator<Effect>() { - - int index; - final int listSize = EffectList.this.size; - - @Override - public boolean hasNext() { - return index < listSize; - } - - @Override - public Effect next() { - return effects[index++]; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - public void incLevel() { - currentLevel++; - } - - public void decLevel() { - currentLevel--; - } - - public Effect get(int index) { - if (index >= size) { - throw new IndexOutOfBoundsException(); - } - return effects[index]; - } - - public int levelAt(int index) { - if (index >= size) { - throw new IndexOutOfBoundsException(); - } - return level[index]; - } - - public void clear() { - size = 0; - } - - public boolean isEmpty() { - return size == 0; - } -}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/experimental/GraphEffectList.java Fri Nov 09 13:32:53 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.virtual.phases.ea.experimental; - -import java.util.*; - -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.virtual.nodes.*; - -public class GraphEffectList extends EffectList { - - public void addFixedNodeBefore(final FixedWithNextNode node, final FixedNode position) { - add(new Effect() { - - @Override - public String name() { - return "addFixedNodeBefore"; - } - - @Override - public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { - assert !node.isAlive() && !node.isDeleted() && position.isAlive(); - graph.addBeforeFixed(position, graph.add(node)); - node.setProbability(position.probability()); - } - }); - } - - public void addFloatingNode(final FloatingNode node) { - add(new Effect() { - - @Override - public String name() { - return "addFloatingNode"; - } - - @Override - public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { - assert !node.isAlive() && !node.isDeleted(); - graph.add(node); - } - }); - } - - public void addMaterialization(final MaterializeObjectNode node, final FixedNode position, final ValueNode[] values) { - add(new Effect() { - - @Override - public String name() { - return "addMaterialization"; - } - - @Override - public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { - assert !node.isAlive() && !node.isDeleted() && position.isAlive(); - graph.addBeforeFixed(position, graph.add(node)); - node.setProbability(position.probability()); - for (int i = 0; i < values.length; i++) { - node.values().set(i, values[i]); - } - } - }); - } - - public void addPhiInput(final PhiNode node, final ValueNode value) { - add(new Effect() { - - @Override - public String name() { - return "addPhiInput"; - } - - @Override - public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { - assert node.isAlive() && value.isAlive(); - node.addInput(value); - } - }); - } - - public void addVirtualMapping(final FrameState node, final EscapeObjectState state, final HashSet<VirtualObjectNode> reusedVirtualObjects) { - add(new Effect() { - - @Override - public String name() { - return "addVirtualMapping"; - } - - @Override - public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { - assert node.isAlive() && !state.isAlive() && !state.isDeleted(); - FrameState stateAfter = node; - for (int i = 0; i < stateAfter.virtualObjectMappingCount(); i++) { - if (stateAfter.virtualObjectMappingAt(i).object() == state.object()) { - if (reusedVirtualObjects.contains(state.object())) { - stateAfter.virtualObjectMappings().remove(i); - } else { - throw new GraalInternalError("unexpected duplicate virtual state at: %s for %s", stateAfter, state.object()); - } - } - } - stateAfter.addVirtualObjectMapping(graph.add(state)); - } - - @Override - public boolean isVisible() { - return false; - } - }); - } - - public void deleteFixedNode(final FixedWithNextNode node) { - add(new Effect() { - - @Override - public String name() { - return "deleteFixedNode"; - } - - @Override - public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { - assert node.isAlive(); - FixedNode next = node.next(); - node.setNext(null); - node.replaceAtPredecessor(next); - obsoleteNodes.add(node); - } - }); - } - - public void eliminateMonitor(final AccessMonitorNode node) { - add(new Effect() { - - @Override - public String name() { - return "eliminateMonitor"; - } - - @Override - public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { - assert node.isAlive() && node.object().isAlive() && (node.object() instanceof VirtualObjectNode); - node.eliminate(); - } - }); - } - - public void replaceAtUsages(final ValueNode node, final ValueNode replacement) { - add(new Effect() { - - @Override - public String name() { - return "replaceAtUsages"; - } - - @Override - public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { - assert node.isAlive() && replacement.isAlive(); - node.replaceAtUsages(replacement); - } - }); - } - - public void replaceFirstInput(final Node node, final ValueNode oldInput, final ValueNode newInput) { - add(new Effect() { - - @Override - public String name() { - return "replaceFirstInput"; - } - - @Override - public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { - assert node.isAlive() && oldInput.isAlive() && newInput.isAlive(); - node.replaceFirstInput(oldInput, newInput); - } - - @Override - public boolean isVisible() { - return !(node instanceof FrameState); - } - }); - } - - public void setPhiInput(final PhiNode node, final ValueNode value, final int index) { - add(new Effect() { - - @Override - public String name() { - return "setPhiInput"; - } - - @Override - public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { - assert node.isAlive() && value.isAlive() && index >= 0; - node.setValueAt(index, value); - } - }); - } -}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/experimental/ReentrantBlockIterator.java Fri Nov 09 13:32:53 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.virtual.phases.ea.experimental; - -import java.util.*; - -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.cfg.*; -import com.oracle.graal.virtual.phases.ea.*; -import com.oracle.graal.virtual.phases.ea.experimental.BlockIteratorClosure.*; - -public final class ReentrantBlockIterator { - - private ReentrantBlockIterator() { - // no instances allowed - } - - public static <T extends MergeableBlockState<T>> LoopInfo<T> processLoop(BlockIteratorClosure<T> closure, Loop loop, T initialState) { - IdentityHashMap<FixedNode, T> blockEndStates = apply(closure, loop.header, initialState, new HashSet<>(loop.blocks)); - - LoopInfo<T> info = new LoopInfo<>(); - List<Block> predecessors = loop.header.getPredecessors(); - for (int i = 1; i < predecessors.size(); i++) { - info.endStates.add(blockEndStates.get(predecessors.get(i).getEndNode())); - } - for (Block loopExit : loop.exits) { - assert loopExit.getPredecessors().size() == 1; - T exitState = blockEndStates.get(loopExit.getPredecessors().get(0).getEndNode()); - assert exitState != null; - info.exitStates.add(exitState); - } - return info; - } - - public static <T extends MergeableBlockState<T>> IdentityHashMap<FixedNode, T> apply(BlockIteratorClosure<T> closure, Block start, T initialState, Set<Block> boundary) { - Deque<Block> blockQueue = new ArrayDeque<>(); - IdentityHashMap<FixedNode, T> blockEndStates = new IdentityHashMap<>(); - - T state = initialState; - Block current = start; - - do { - if (boundary == null || boundary.contains(current)) { - closure.processBlock(current, state); - - if (current.getSuccessors().isEmpty()) { - // nothing to do... - } else if (current.getSuccessors().size() == 1) { - Block successor = current.getSuccessors().get(0); - if (successor.isLoopHeader()) { - if (current.isLoopEnd()) { - // nothing to do... loop ends only lead to loop begins we've already visited - blockEndStates.put(current.getEndNode(), state); - } else { - // recurse into the loop - Loop loop = successor.getLoop(); - LoopBeginNode loopBegin = loop.loopBegin(); - assert successor.getBeginNode() == loopBegin; - - List<T> exitStates = closure.processLoop(loop, state); - - int i = 0; - assert loop.exits.size() == exitStates.size(); - for (Block exit : loop.exits) { - blockEndStates.put(exit.getPredecessors().get(0).getEndNode(), exitStates.get(i++)); - blockQueue.addFirst(exit); - } - } - } else { - if (successor.getBeginNode() instanceof LoopExitNode) { - assert successor.getPredecessors().size() == 1; - blockEndStates.put(current.getEndNode(), state); - current = successor; - continue; - } else { - if (current.getEndNode() instanceof EndNode) { - assert successor.getPredecessors().size() > 1 : "invalid block schedule at " + successor.getBeginNode(); - EndNode end = (EndNode) current.getEndNode(); - - // add the end node and see if the merge is ready for processing - assert !blockEndStates.containsKey(end); - blockEndStates.put(end, state); - MergeNode merge = end.merge(); - boolean endsVisited = true; - for (int i = 0; i < merge.forwardEndCount(); i++) { - if (!blockEndStates.containsKey(merge.forwardEndAt(i))) { - endsVisited = false; - break; - } - } - if (endsVisited) { - blockQueue.addFirst(successor); - } - } else { - assert successor.getPredecessors().size() == 1 : "invalid block schedule at " + successor.getBeginNode(); - current = successor; - continue; - } - } - } - } else { - assert current.getSuccessors().size() > 1; - blockEndStates.put(current.getEndNode(), state); - for (Block block : current.getSuccessors()) { - blockQueue.addFirst(block); - } - } - } - - // get next queued block - if (blockQueue.isEmpty()) { - current = null; - } else { - int maxIterations = blockQueue.size(); - while (maxIterations-- > 0) { - current = blockQueue.removeFirst(); - if (current.getPredecessors().size() > 1) { - MergeNode merge = (MergeNode) current.getBeginNode(); - ArrayList<T> states = new ArrayList<>(merge.forwardEndCount()); - for (int i = 0; i < merge.forwardEndCount(); i++) { - T other = blockEndStates.get(merge.forwardEndAt(i)); - assert other != null; - states.add(other); - } - state = closure.merge(merge, states); - if (state != null) { - break; - } else { - blockQueue.addLast(current); - current = null; - } - } else { - assert current.getPredecessors().size() == 1; - assert current.getBeginNode().predecessor() != null; - if (boundary == null || boundary.contains(current)) { - state = closure.afterSplit(current.getBeginNode(), blockEndStates.get(current.getBeginNode().predecessor())); - break; - } - } - } - } - } while (current != null); - return blockEndStates; - } -}
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/experimental/SplitPartialEscapeAnalysisPhase.java Fri Nov 09 13:32:53 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1253 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.virtual.phases.ea.experimental; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.ResolvedJavaType.Representation; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.PhiNode.PhiType; -import com.oracle.graal.nodes.VirtualState.NodeClosure; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.cfg.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.common.*; -import com.oracle.graal.phases.schedule.*; -import com.oracle.graal.virtual.nodes.*; -import com.oracle.graal.virtual.phases.ea.*; -import com.oracle.graal.virtual.phases.ea.experimental.EffectList.*; - -class EscapeAnalysisIteration { - - public static final void trace(String format, Object... obj) { - if (GraalOptions.TraceEscapeAnalysis) { - Debug.log(format, obj); - } - } - - public static final void error(String format, Object... obj) { - System.out.print(String.format(format, obj)); - } - - private final StructuredGraph graph; - private final MetaAccessProvider runtime; - private final SchedulePhase schedule; - private final NodeBitMap usages; - - private final HashSet<VirtualObjectNode> reusedVirtualObjects = new HashSet<>(); - private int virtualIds = 0; - - public EscapeAnalysisIteration(StructuredGraph graph, SchedulePhase schedule, MetaAccessProvider runtime) { - this.graph = graph; - this.schedule = schedule; - this.runtime = runtime; - this.usages = graph.createNodeBitMap(); - } - - public void run() { - PartialEscapeClosure closure = new PartialEscapeClosure(); - ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock(), new BlockState(), null); - ArrayList<Node> obsoleteNodes = new ArrayList<>(); - for (int i = 0; i < closure.effects.size(); i++) { - Effect effect = closure.effects.get(i); - effect.apply(graph, obsoleteNodes); - if (GraalOptions.TraceEscapeAnalysis) { - if (effect.isVisible()) { - int level = closure.effects.levelAt(i); - StringBuilder str = new StringBuilder(); - for (int i2 = 0; i2 < level; i2++) { - str.append(" "); - } - trace(str.append(effect).toString()); - } - } - } - Debug.dump(graph, "after PartialEscapeAnalysis"); - - // helper code that determines the paths that keep obsolete nodes alive: - // - // NodeFlood flood = graph.createNodeFlood(); - // IdentityHashMap<Node, Node> path = new IdentityHashMap<>(); - // flood.add(graph.start()); - // for (Node current : flood) { - // if (current instanceof EndNode) { - // EndNode end = (EndNode) current; - // flood.add(end.merge()); - // if (!path.containsKey(end.merge())) { - // path.put(end.merge(), end); - // } - // } else { - // for (Node successor : current.successors()) { - // flood.add(successor); - // if (!path.containsKey(successor)) { - // path.put(successor, current); - // } - // } - // } - // } - // - // for (Node node : obsoleteNodes) { - // if (node instanceof FixedNode) { - // assert !flood.isMarked(node); - // } - // } - // - // for (Node node : graph.getNodes()) { - // if (node instanceof LocalNode) { - // flood.add(node); - // } - // if (flood.isMarked(node)) { - // for (Node input : node.inputs()) { - // flood.add(input); - // if (!path.containsKey(input)) { - // path.put(input, node); - // } - // } - // } - // } - // for (Node current : flood) { - // for (Node input : current.inputs()) { - // flood.add(input); - // if (!path.containsKey(input)) { - // path.put(input, current); - // } - // } - // } - // - // for (Node node : obsoleteNodes) { - // if (flood.isMarked(node)) { - // System.out.println("offending node path:"); - // Node current = node; - // while (current != null) { - // System.out.println(current); - // current = path.get(current); - // if (current != null && current instanceof FixedNode && !obsoleteNodes.contains(current)) { - // break; - // } - // } - // } - // } - - new DeadCodeEliminationPhase().apply(graph); - - } - - private static class ObjectState { - - public final VirtualObjectNode virtual; - public ValueNode[] fieldState; - public ValueNode materializedValue; - public int lockCount; - - public ObjectState(VirtualObjectNode virtual, ValueNode[] fieldState, int lockCount) { - this.virtual = virtual; - this.fieldState = fieldState; - this.lockCount = lockCount; - } - - public ObjectState(VirtualObjectNode virtual, ValueNode materializedValue, int lockCount) { - this.virtual = virtual; - this.materializedValue = materializedValue; - this.lockCount = lockCount; - } - - private ObjectState(ObjectState other) { - virtual = other.virtual; - fieldState = other.fieldState == null ? null : other.fieldState.clone(); - materializedValue = other.materializedValue; - lockCount = other.lockCount; - } - - @Override - public ObjectState clone() { - return new ObjectState(this); - } - - @Override - public String toString() { - StringBuilder str = new StringBuilder().append('{'); - if (lockCount > 0) { - str.append('l').append(lockCount).append(' '); - } - if (fieldState != null) { - for (int i = 0; i < fieldState.length; i++) { - str.append(virtual.fieldName(i)).append('=').append(fieldState[i]).append(' '); - } - } - if (materializedValue != null) { - str.append("mat=").append(materializedValue); - } - - return str.append('}').toString(); - } - } - - private class BlockState implements MergeableBlockState<BlockState> { - - private final HashMap<VirtualObjectNode, ObjectState> objectStates = new HashMap<>(); - private final HashMap<ValueNode, VirtualObjectNode> objectAliases = new HashMap<>(); - private final HashMap<ValueNode, ValueNode> scalarAliases = new HashMap<>(); - - public BlockState() { - } - - public BlockState(BlockState other) { - for (Map.Entry<VirtualObjectNode, ObjectState> entry : other.objectStates.entrySet()) { - objectStates.put(entry.getKey(), entry.getValue().clone()); - } - for (Map.Entry<ValueNode, VirtualObjectNode> entry : other.objectAliases.entrySet()) { - objectAliases.put(entry.getKey(), entry.getValue()); - } - for (Map.Entry<ValueNode, ValueNode> entry : other.scalarAliases.entrySet()) { - scalarAliases.put(entry.getKey(), entry.getValue()); - } - } - - public ObjectState objectState(VirtualObjectNode object) { - assert objectStates.containsKey(object); - return objectStates.get(object); - } - - public ObjectState objectStateOptional(VirtualObjectNode object) { - return objectStates.get(object); - } - - public ObjectState objectState(ValueNode value) { - VirtualObjectNode object = objectAliases.get(value); - return object == null ? null : objectState(object); - } - - @Override - public BlockState clone() { - return new BlockState(this); - } - - public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual, GraphEffectList materializeEffects) { - HashSet<VirtualObjectNode> deferred = new HashSet<>(); - GraphEffectList deferredStores = new GraphEffectList(); - materializeChangedBefore(fixed, virtual, deferred, deferredStores, materializeEffects); - materializeEffects.addAll(deferredStores); - } - - private void materializeChangedBefore(FixedNode fixed, VirtualObjectNode virtual, HashSet<VirtualObjectNode> deferred, GraphEffectList deferredStores, GraphEffectList materializeEffects) { - trace("materializing %s at %s", virtual, fixed); - ObjectState obj = objectState(virtual); - if (obj.lockCount > 0 && obj.virtual.type().isArrayClass()) { -// error("array materialized with lock: %s\n", virtual); - throw new BailoutException("array materialized with lock"); - } - - MaterializeObjectNode materialize = new MaterializeObjectNode(virtual, obj.lockCount > 0); - ValueNode[] values = new ValueNode[obj.fieldState.length]; - materialize.setProbability(fixed.probability()); - ValueNode[] fieldState = obj.fieldState; - obj.fieldState = null; - obj.materializedValue = materialize; - deferred.add(virtual); - for (int i = 0; i < fieldState.length; i++) { - ObjectState valueObj = objectState(fieldState[i]); - if (valueObj != null) { - if (valueObj.materializedValue == null) { - materializeChangedBefore(fixed, valueObj.virtual, deferred, deferredStores, materializeEffects); - } - if (deferred.contains(valueObj.virtual)) { - Kind fieldKind; - CyclicMaterializeStoreNode store; - if (virtual instanceof VirtualArrayNode) { - store = new CyclicMaterializeStoreNode(materialize, valueObj.materializedValue, i); - fieldKind = ((VirtualArrayNode) virtual).componentType().getKind(); - } else { - VirtualInstanceNode instanceObject = (VirtualInstanceNode) virtual; - store = new CyclicMaterializeStoreNode(materialize, valueObj.materializedValue, instanceObject.field(i)); - fieldKind = instanceObject.field(i).getType().getKind(); - } - deferredStores.addFixedNodeBefore(store, fixed); - values[i] = ConstantNode.defaultForKind(fieldKind, graph); - } else { - values[i] = valueObj.materializedValue; - } - } else { - values[i] = fieldState[i]; - } - } - deferred.remove(virtual); - - materializeEffects.addMaterialization(materialize, fixed, values); - } - - private void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node) { - objectAliases.put(node, virtual); - for (Node usage : node.usages()) { - markVirtualUsages(usage); - } - } - - private void markVirtualUsages(Node node) { - if (!usages.isNew(node)) { - usages.mark(node); - } - if (node instanceof VirtualState) { - for (Node usage : node.usages()) { - markVirtualUsages(usage); - } - } - } - - public void addObject(VirtualObjectNode virtual, ObjectState state) { - objectStates.put(virtual, state); - } - - public void addScalarAlias(ValueNode alias, ValueNode value) { - scalarAliases.put(alias, value); - } - - public ValueNode scalarAlias(ValueNode alias) { - ValueNode result = scalarAliases.get(alias); - return result == null ? alias : result; - } - - public Iterable<ObjectState> states() { - return objectStates.values(); - } - - @Override - public String toString() { - return objectStates.toString(); - } - } - - private class PartialEscapeClosure extends BlockIteratorClosure<BlockState> { - - private final GraphEffectList effects = new GraphEffectList(); - - @Override - protected void processBlock(Block block, BlockState state) { - trace("\nBlock: %s (", block); - List<ScheduledNode> nodeList = schedule.getBlockToNodesMap().get(block); - - FixedWithNextNode lastFixedNode = null; - for (Node node : nodeList) { - EscapeOp op = null; - if (node instanceof EscapeAnalyzable) { - op = ((EscapeAnalyzable) node).getEscapeOp(); - } - // if (node instanceof NewInstanceNode) { - // if (!((NewInstanceNode) node).instanceClass().name().contains("Key")) { - // op = null; - // } - // } else { - // op = null; - // } - - if (op != null) { - trace("{{%s}} ", node); - VirtualObjectNode virtualObject = op.virtualObject(virtualIds); - if (virtualObject.isAlive()) { - reusedVirtualObjects.add(virtualObject); - state.addAndMarkAlias(virtualObject, virtualObject); - } else { - effects.addFloatingNode(virtualObject); - } - state.addObject(virtualObject, new ObjectState(virtualObject, op.fieldState(), 0)); - state.addAndMarkAlias(virtualObject, (ValueNode) node); - effects.deleteFixedNode((FixedWithNextNode) node); - virtualIds++; - } else { - if (usages.isMarked(node)) { - trace("[[%s]] ", node); - processNode((ValueNode) node, lastFixedNode == null ? null : lastFixedNode.next(), state); - } else { - trace("%s ", node); - } - } - - if (node instanceof FixedWithNextNode && node.isAlive()) { - lastFixedNode = (FixedWithNextNode) node; - } - } - trace(")\n end state: %s\n", state); - } - - private void processNode(final ValueNode node, FixedNode insertBefore, final BlockState state) { - boolean usageFound = false; - if (node instanceof PiNode || node instanceof ValueProxyNode) { - ValueNode value = node instanceof PiNode ? ((PiNode) node).object() : ((ValueProxyNode) node).value(); - ObjectState obj = state.objectState(value); - if (obj != null) { - if (obj.materializedValue == null) { - state.addAndMarkAlias(obj.virtual, node); - } else { - effects.replaceFirstInput(node, value, obj.materializedValue); - } - usageFound = true; - } - } else if (node instanceof CheckCastNode) { - CheckCastNode x = (CheckCastNode) node; - ObjectState obj = state.objectState(x.object()); - if (obj != null) { - if (obj.materializedValue == null) { - if (x.targetClass() != null && obj.virtual.type().isSubtypeOf(x.targetClass())) { - state.addAndMarkAlias(obj.virtual, x); - effects.deleteFixedNode(x); - } else { - replaceWithMaterialized(x.object(), x, state, obj); - } - } else { - effects.replaceFirstInput(x, x.object(), obj.materializedValue); - } - usageFound = true; - } - } else if (node instanceof IsNullNode) { - IsNullNode x = (IsNullNode) node; - if (state.objectState(x.object()) != null) { - replaceAtUsages(state, x, graph.unique(ConstantNode.forBoolean(false, graph))); - usageFound = true; - } - } else if (node instanceof AccessMonitorNode) { - AccessMonitorNode x = (AccessMonitorNode) node; - ObjectState obj = state.objectState(x.object()); - if (obj != null) { - Debug.log("monitor operation %s on %s\n", x, obj.virtual); - if (node instanceof MonitorEnterNode) { - obj.lockCount++; - } else { - assert node instanceof MonitorExitNode; - obj.lockCount--; - } - if (obj.materializedValue == null) { - effects.replaceFirstInput(node, x.object(), obj.virtual); - effects.eliminateMonitor(x); - } else { - effects.replaceFirstInput(node, x.object(), obj.materializedValue); - } - usageFound = true; - } - } else if (node instanceof CyclicMaterializeStoreNode) { - CyclicMaterializeStoreNode x = (CyclicMaterializeStoreNode) node; - ObjectState obj = state.objectState(x.object()); - if (obj != null) { - if (obj.virtual instanceof VirtualArrayNode) { - obj.fieldState[x.targetIndex()] = x.value(); - } else { - VirtualInstanceNode instance = (VirtualInstanceNode) obj.virtual; - int index = instance.fieldIndex(x.targetField()); - obj.fieldState[index] = x.value(); - } - effects.deleteFixedNode(x); - usageFound = true; - } - } else if (node instanceof LoadFieldNode) { - LoadFieldNode x = (LoadFieldNode) node; - ObjectState obj = state.objectState(x.object()); - if (obj != null) { - VirtualInstanceNode virtual = (VirtualInstanceNode) obj.virtual; - int fieldIndex = virtual.fieldIndex(x.field()); - if (fieldIndex == -1) { - // the field does not exist in the virtual object - ensureMaterialized(state, obj, x); - } - if (obj.materializedValue == null) { - ValueNode result = obj.fieldState[fieldIndex]; - ObjectState resultObj = state.objectState(result); - if (resultObj != null) { - state.addAndMarkAlias(resultObj.virtual, x); - } else { - replaceAtUsages(state, x, result); - } - effects.deleteFixedNode(x); - } else { - effects.replaceFirstInput(x, x.object(), obj.materializedValue); - } - usageFound = true; - } - } else if (node instanceof StoreFieldNode) { - StoreFieldNode x = (StoreFieldNode) node; - ValueNode object = x.object(); - ValueNode value = x.value(); - ObjectState obj = state.objectState(object); - if (obj != null) { - VirtualInstanceNode virtual = (VirtualInstanceNode) obj.virtual; - int fieldIndex = virtual.fieldIndex(x.field()); - if (fieldIndex == -1) { - // the field does not exist in the virtual object - ensureMaterialized(state, obj, x); - } - if (obj.materializedValue == null) { - obj.fieldState[fieldIndex] = state.scalarAlias(value); - effects.deleteFixedNode(x); - } else { - effects.replaceFirstInput(x, object, obj.materializedValue); - ObjectState valueObj = state.objectState(value); - if (valueObj != null) { - replaceWithMaterialized(value, x, state, valueObj); - } - } - usageFound = true; - } else { - ObjectState valueObj = state.objectState(value); - if (valueObj != null) { - replaceWithMaterialized(value, x, state, valueObj); - usageFound = true; - } - } - } else if (node instanceof LoadIndexedNode) { - LoadIndexedNode x = (LoadIndexedNode) node; - ValueNode array = x.array(); - ObjectState arrayObj = state.objectState(array); - if (arrayObj != null) { - if (arrayObj.materializedValue == null) { - ValueNode indexValue = state.scalarAlias(x.index()); - int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1; - if (index < 0 || index >= arrayObj.fieldState.length) { - // out of bounds or not constant - replaceWithMaterialized(array, x, state, arrayObj); - } else { - ValueNode result = arrayObj.fieldState[index]; - ObjectState resultObj = state.objectState(result); - if (resultObj != null) { - state.addAndMarkAlias(resultObj.virtual, x); - } else { - replaceAtUsages(state, x, result); - } - effects.deleteFixedNode(x); - } - } else { - effects.replaceFirstInput(x, array, arrayObj.materializedValue); - } - usageFound = true; - } - } else if (node instanceof StoreIndexedNode) { - StoreIndexedNode x = (StoreIndexedNode) node; - ValueNode array = x.array(); - ValueNode value = x.value(); - ObjectState arrayObj = state.objectState(array); - ObjectState valueObj = state.objectState(value); - - if (arrayObj != null) { - if (arrayObj.materializedValue == null) { - ValueNode indexValue = state.scalarAlias(x.index()); - int index = indexValue.isConstant() ? indexValue.asConstant().asInt() : -1; - if (index < 0 || index >= arrayObj.fieldState.length) { - // out of bounds or not constant - replaceWithMaterialized(array, x, state, arrayObj); - if (valueObj != null) { - replaceWithMaterialized(value, x, state, valueObj); - } - } else { - arrayObj.fieldState[index] = state.scalarAlias(value); - effects.deleteFixedNode(x); - } - } else { - effects.replaceFirstInput(x, array, arrayObj.materializedValue); - if (valueObj != null) { - replaceWithMaterialized(value, x, state, valueObj); - } - } - usageFound = true; - } else { - if (valueObj != null) { - replaceWithMaterialized(value, x, state, valueObj); - usageFound = true; - } - } - } else if (node instanceof RegisterFinalizerNode) { - RegisterFinalizerNode x = (RegisterFinalizerNode) node; - ObjectState obj = state.objectState(x.object()); - if (obj != null) { - replaceWithMaterialized(x.object(), x, state, obj); - usageFound = true; - } - } else if (node instanceof ArrayLengthNode) { - ArrayLengthNode x = (ArrayLengthNode) node; - ObjectState obj = state.objectState(x.array()); - if (obj != null) { - replaceAtUsages(state, x, ConstantNode.forInt(((VirtualArrayNode) obj.virtual).entryCount(), graph)); - effects.deleteFixedNode(x); - usageFound = true; - } - } else if (node instanceof LoadHubNode) { - LoadHubNode x = (LoadHubNode) node; - ObjectState obj = state.objectState(x.object()); - if (obj != null) { - replaceAtUsages(state, x, ConstantNode.forConstant(obj.virtual.type().getEncoding(Representation.ObjectHub), runtime, graph)); - effects.deleteFixedNode(x); - usageFound = true; - } - } else if (node instanceof ReturnNode) { - ReturnNode x = (ReturnNode) node; - ObjectState obj = state.objectState(x.result()); - if (obj != null) { - replaceWithMaterialized(x.result(), x, state, obj); - usageFound = true; - } - } else if (node instanceof MethodCallTargetNode) { - for (ValueNode argument : ((MethodCallTargetNode) node).arguments()) { - ObjectState obj = state.objectState(argument); - if (obj != null) { - replaceWithMaterialized(argument, node, insertBefore, state, obj); - usageFound = true; - } - } - } else if (node instanceof ObjectEqualsNode) { - ObjectEqualsNode x = (ObjectEqualsNode) node; - ObjectState xObj = state.objectState(x.x()); - ObjectState yObj = state.objectState(x.y()); - boolean xVirtual = xObj != null && xObj.materializedValue == null; - boolean yVirtual = yObj != null && yObj.materializedValue == null; - - if (xVirtual ^ yVirtual) { - // one of them is virtual: they can never be the same objects - replaceAtUsages(state, x, ConstantNode.forBoolean(false, graph)); - usageFound = true; - } else if (xVirtual && yVirtual) { - // both are virtual: check if they refer to the same object - replaceAtUsages(state, x, ConstantNode.forBoolean(xObj == yObj, graph)); - usageFound = true; - } else { - if (xObj != null || yObj != null) { - if (xObj != null) { - assert xObj.materializedValue != null; - effects.replaceFirstInput(x, x.x(), xObj.materializedValue); - } - if (yObj != null) { - assert yObj.materializedValue != null; - effects.replaceFirstInput(x, x.y(), yObj.materializedValue); - } - usageFound = true; - } - } - } else if (node instanceof MergeNode) { - usageFound = true; - } else if (node instanceof UnsafeLoadNode || node instanceof UnsafeStoreNode || node instanceof CompareAndSwapNode || node instanceof SafeReadNode) { - for (ValueNode input : node.inputs().filter(ValueNode.class)) { - ObjectState obj = state.objectState(input); - if (obj != null) { - replaceWithMaterialized(input, node, insertBefore, state, obj); - usageFound = true; - } - } - } - if (node.isAlive() && node instanceof StateSplit) { - StateSplit split = (StateSplit) node; - FrameState stateAfter = split.stateAfter(); - if (stateAfter != null) { - if (stateAfter.usages().size() > 1) { - stateAfter = (FrameState) stateAfter.copyWithInputs(); - split.setStateAfter(stateAfter); - } - final HashSet<ObjectState> virtual = new HashSet<>(); - stateAfter.applyToNonVirtual(new NodeClosure<ValueNode>() { - - @Override - public void apply(Node usage, ValueNode value) { - ObjectState valueObj = state.objectState(value); - if (valueObj != null) { - virtual.add(valueObj); - effects.replaceFirstInput(usage, value, valueObj.virtual); - } else if (value instanceof VirtualObjectNode) { - ObjectState virtualObj = null; - for (ObjectState obj : state.states()) { - if (value == obj.virtual) { - virtualObj = obj; - break; - } - } - if (virtualObj != null) { - virtual.add(virtualObj); - } - } - } - }); - for (ObjectState obj : state.states()) { - if (obj.materializedValue == null && obj.lockCount > 0) { - virtual.add(obj); - } - } - - ArrayDeque<ObjectState> queue = new ArrayDeque<>(virtual); - while (!queue.isEmpty()) { - ObjectState obj = queue.removeLast(); - if (obj.materializedValue == null) { - for (ValueNode field : obj.fieldState) { - ObjectState fieldObj = state.objectState(field); - if (fieldObj != null) { - if (fieldObj.materializedValue == null && !virtual.contains(fieldObj)) { - virtual.add(fieldObj); - queue.addLast(fieldObj); - } - } - } - } - } - for (ObjectState obj : virtual) { - EscapeObjectState v; - if (obj.materializedValue == null) { - ValueNode[] fieldState = obj.fieldState.clone(); - for (int i = 0; i < fieldState.length; i++) { - ObjectState valueObj = state.objectState(fieldState[i]); - if (valueObj != null) { - if (valueObj.materializedValue == null) { - fieldState[i] = valueObj.virtual; - } else { - fieldState[i] = valueObj.materializedValue; - } - } - } - v = new VirtualObjectState(obj.virtual, fieldState); - } else { - v = new MaterializedObjectState(obj.virtual, obj.materializedValue); - } - effects.addVirtualMapping(stateAfter, v, reusedVirtualObjects); - } - } - usageFound = true; - } - if (!usageFound) { - for (ValueNode input : node.inputs().filter(ValueNode.class)) { - ObjectState obj = state.objectState(input); - if (obj != null) { - replaceWithMaterialized(input, node, insertBefore, state, obj); - usageFound = true; - } - } - Debug.log("unexpected usage of %s: %s\n", node, node.inputs().snapshot()); - } - } - - private void replaceAtUsages(final BlockState state, ValueNode x, ValueNode value) { - effects.replaceAtUsages(x, value); - state.addScalarAlias(x, value); - } - - private void ensureMaterialized(BlockState state, ObjectState obj, FixedNode materializeBefore) { - assert obj != null; - if (obj.materializedValue == null) { - state.materializeBefore(materializeBefore, obj.virtual, effects); - } - assert obj.materializedValue != null; - } - - private void replaceWithMaterialized(ValueNode value, FixedNode usage, BlockState state, ObjectState obj) { - ensureMaterialized(state, obj, usage); - effects.replaceFirstInput(usage, value, obj.materializedValue); - } - - private void replaceWithMaterialized(ValueNode value, Node usage, FixedNode materializeBefore, BlockState state, ObjectState obj) { - ensureMaterialized(state, obj, materializeBefore); - effects.replaceFirstInput(usage, value, obj.materializedValue); - } - - @Override - protected BlockState merge(MergeNode merge, List<BlockState> states) { - BlockState newState = new BlockState(); - - newState.objectAliases.putAll(states.get(0).objectAliases); - for (int i = 1; i < states.size(); i++) { - BlockState state = states.get(i); - for (Map.Entry<ValueNode, VirtualObjectNode> entry : states.get(0).objectAliases.entrySet()) { - if (state.objectAliases.containsKey(entry.getKey())) { - assert state.objectAliases.get(entry.getKey()) == entry.getValue(); - } else { - newState.objectAliases.remove(entry.getKey()); - } - } - } - - newState.scalarAliases.putAll(states.get(0).scalarAliases); - for (int i = 1; i < states.size(); i++) { - BlockState state = states.get(i); - for (Map.Entry<ValueNode, ValueNode> entry : states.get(0).scalarAliases.entrySet()) { - if (state.scalarAliases.containsKey(entry.getKey())) { - assert state.scalarAliases.get(entry.getKey()) == entry.getValue(); - } else { - newState.scalarAliases.remove(entry.getKey()); - } - } - } - - // Iterative processing: - // Merging the materialized/virtual state of virtual objects can lead to new materializations, which can - // lead to new materializations because of phis, and so on. - - boolean materialized; - do { - materialized = false; - // use a hash set to make the values distinct... - for (VirtualObjectNode object : new HashSet<>(newState.objectAliases.values())) { - ObjectState resultState = newState.objectStates.get(object); - if (resultState == null || resultState.materializedValue == null) { - int virtual = 0; - int lockCount = states.get(0).objectState(object).lockCount; - ValueNode singleValue = states.get(0).objectState(object).materializedValue; - for (BlockState state : states) { - ObjectState obj = state.objectState(object); - if (obj.materializedValue == null) { - virtual++; - singleValue = null; - } else { - if (obj.materializedValue != singleValue) { - singleValue = null; - } - } - assert obj.lockCount == lockCount : "mismatching lock counts"; - } - - if (virtual < states.size()) { - if (singleValue == null) { - PhiNode materializedValuePhi = new PhiNode(Kind.Object, merge); - effects.addFloatingNode(materializedValuePhi); - for (int i = 0; i < states.size(); i++) { - BlockState state = states.get(i); - ObjectState obj = state.objectState(object); - materialized |= obj.materializedValue == null; - ensureMaterialized(state, obj, merge.forwardEndAt(i)); - effects.addPhiInput(materializedValuePhi, obj.materializedValue); - } - newState.addObject(object, new ObjectState(object, materializedValuePhi, lockCount)); - } else { - newState.addObject(object, new ObjectState(object, singleValue, lockCount)); - } - } else { - assert virtual == states.size(); - ValueNode[] values = states.get(0).objectState(object).fieldState.clone(); - PhiNode[] phis = new PhiNode[values.length]; - int mismatch = 0; - for (int i = 1; i < states.size(); i++) { - BlockState state = states.get(i); - ValueNode[] fields = state.objectState(object).fieldState; - for (int index = 0; index < values.length; index++) { - if (phis[index] == null && values[index] != fields[index]) { - mismatch++; - phis[index] = new PhiNode(values[index].kind(), merge); - effects.addFloatingNode(phis[index]); - } - } - } - if (mismatch > 0) { - for (int i = 0; i < states.size(); i++) { - BlockState state = states.get(i); - ValueNode[] fields = state.objectState(object).fieldState; - for (int index = 0; index < values.length; index++) { - if (phis[index] != null) { - ObjectState obj = state.objectState(fields[index]); - if (obj != null) { - materialized |= obj.materializedValue == null; - ensureMaterialized(state, obj, merge.forwardEndAt(i)); - fields[index] = obj.materializedValue; - } - effects.addPhiInput(phis[index], fields[index]); - } - } - } - for (int index = 0; index < values.length; index++) { - if (phis[index] != null) { - values[index] = phis[index]; - } - } - } - newState.addObject(object, new ObjectState(object, values, lockCount)); - } - } - } - - for (PhiNode phi : merge.phis().snapshot()) { - if (usages.isMarked(phi) && phi.type() == PhiType.Value) { - materialized |= processPhi(newState, merge, phi, states); - } - } - } while (materialized); - - return newState; - } - - private boolean processPhi(BlockState newState, MergeNode merge, PhiNode phi, List<BlockState> states) { - assert states.size() == phi.valueCount(); - int virtualInputs = 0; - boolean materialized = false; - VirtualObjectNode sameObject = null; - ResolvedJavaType sameType = null; - int sameEntryCount = -1; - for (int i = 0; i < phi.valueCount(); i++) { - ValueNode value = phi.valueAt(i); - ObjectState obj = states.get(i).objectState(value); - if (obj != null) { - if (obj.materializedValue == null) { - virtualInputs++; - if (i == 0) { - sameObject = obj.virtual; - sameType = obj.virtual.type(); - sameEntryCount = obj.virtual.entryCount(); - } else { - if (sameObject != obj.virtual) { - sameObject = null; - } - if (sameType != obj.virtual.type()) { - sameType = null; - } - if (sameEntryCount != obj.virtual.entryCount()) { - sameEntryCount = -1; - } - } - } else { - effects.setPhiInput(phi, obj.materializedValue, i); - } - } - } - boolean materialize = false; - if (virtualInputs == 0) { - // nothing to do... - } else if (virtualInputs == phi.valueCount()) { - if (sameObject != null) { - newState.addAndMarkAlias(sameObject, phi); - } else if (sameType != null && sameEntryCount != -1) { - materialize = true; - // throw new GraalInternalError("merge required for %s", sameType); - } else { - materialize = true; - } - } else { - materialize = true; - } - - if (materialize) { - for (int i = 0; i < phi.valueCount(); i++) { - ValueNode value = phi.valueAt(i); - ObjectState obj = states.get(i).objectState(value); - if (obj != null) { - materialized |= obj.materializedValue == null; - replaceWithMaterialized(value, phi, merge.forwardEndAt(i), states.get(i), obj); - } - } - } - return materialized; - } - - @Override - protected BlockState afterSplit(FixedNode node, BlockState oldState) { - return oldState.clone(); - } - - @Override - protected List<BlockState> processLoop(Loop loop, BlockState initialState) { - GraphEffectList successEffects = new GraphEffectList(); - HashSet<PhiDesc> phis = new HashSet<>(); - for (int iteration = 0; iteration < 10; iteration++) { - BlockState state = initialState.clone(); - int checkpoint = effects.checkpoint(); - - for (PhiDesc desc : phis) { - ObjectState obj = state.objectState(desc.virtualObject); - if (obj.materializedValue == null) { - ValueNode value = obj.fieldState[desc.fieldIndex]; - ObjectState valueObj = state.objectState(value); - if (valueObj != null) { - assert valueObj.materializedValue != null; - value = valueObj.materializedValue; - } - - PhiNode phiNode = new PhiNode(value.kind(), loop.loopBegin()); - effects.addFloatingNode(phiNode); - effects.addPhiInput(phiNode, value); - obj.fieldState[desc.fieldIndex] = phiNode; - } - } - - for (PhiNode phi : loop.loopBegin().phis()) { - if (usages.isMarked(phi) && phi.type() == PhiType.Value) { - ObjectState initialObj = initialState.objectState(phi.valueAt(0)); - if (initialObj != null) { - if (initialObj.materializedValue == null) { - state.addAndMarkAlias(initialObj.virtual, phi); - } else { - successEffects.setPhiInput(phi, initialObj.materializedValue, 0); - } - } - } - } - - effects.incLevel(); - LoopInfo<BlockState> info = ReentrantBlockIterator.processLoop(this, loop, state.clone()); - - List<BlockState> loopEndStates = info.endStates; - List<Block> predecessors = loop.header.getPredecessors(); - HashSet<VirtualObjectNode> additionalMaterializations = new HashSet<>(); - int oldPhiCount = phis.size(); - for (int i = 1; i < predecessors.size(); i++) { - processLoopEnd(loop.loopBegin(), (LoopEndNode) predecessors.get(i).getEndNode(), state, loopEndStates.get(i - 1), successEffects, additionalMaterializations, phis); - } - if (additionalMaterializations.isEmpty() && oldPhiCount == phis.size()) { - effects.addAll(successEffects); - - assert info.exitStates.size() == loop.exits.size(); - for (int i = 0; i < loop.exits.size(); i++) { - BlockState exitState = info.exitStates.get(i); - assert exitState != null : "no loop exit state at " + loop.exits.get(i) + " / " + loop.header; - processLoopExit((LoopExitNode) loop.exits.get(i).getBeginNode(), state, exitState); - } - - effects.decLevel(); - return info.exitStates; - } else { - successEffects.clear(); - effects.backtrack(checkpoint); - effects.decLevel(); - for (VirtualObjectNode virtualObject : additionalMaterializations) { - ObjectState obj = initialState.objectState(virtualObject); - if (obj.materializedValue == null) { - initialState.materializeBefore(loop.loopBegin().forwardEnd(), virtualObject, effects); - } - } - } - } - - throw new GraalInternalError("too many iterations at %s", loop); - } - - private void processLoopExit(LoopExitNode exitNode, BlockState initialState, BlockState exitState) { - HashMap<VirtualObjectNode, ValueProxyNode> proxies = new HashMap<>(); - - for (ValueProxyNode proxy : exitNode.proxies()) { - ObjectState obj = exitState.objectState(proxy.value()); - if (obj != null) { - proxies.put(obj.virtual, proxy); - } - } - for (ObjectState obj : exitState.states()) { - ObjectState initialObj = initialState.objectStateOptional(obj.virtual); - if (obj.materializedValue == null) { - for (int i = 0; i < obj.fieldState.length; i++) { - ValueNode value = obj.fieldState[i]; - ObjectState valueObj = exitState.objectState(value); - if (valueObj == null) { - if ((value instanceof PhiNode && ((PhiNode) value).merge() == exitNode.loopBegin()) || initialObj == null || initialObj.materializedValue != null || - initialObj.fieldState[i] != value) { - ValueProxyNode proxy = new ValueProxyNode(value, exitNode, PhiType.Value); - obj.fieldState[i] = proxy; - effects.addFloatingNode(proxy); - } - } - } - } else { - if (initialObj == null || initialObj.materializedValue == null) { - ValueProxyNode proxy = proxies.get(obj.virtual); - if (proxy == null) { - proxy = new ValueProxyNode(obj.materializedValue, exitNode, PhiType.Value); - effects.addFloatingNode(proxy); - } else { - effects.replaceFirstInput(proxy, proxy.value(), obj.materializedValue); - // nothing to do - will be handled in processNode - } - obj.materializedValue = proxy; - } else { - assert initialObj.materializedValue == obj.materializedValue : "materialized value is not allowed to change within loops: " + initialObj.materializedValue + " vs. " + - obj.materializedValue; - } - } - } - } - - private final class PhiDesc { - - public final VirtualObjectNode virtualObject; - public final int fieldIndex; - - public PhiDesc(VirtualObjectNode virtualObject, int fieldIndex) { - this.virtualObject = virtualObject; - this.fieldIndex = fieldIndex; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = fieldIndex; - result = prime * result + ((virtualObject == null) ? 0 : virtualObject.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - PhiDesc other = (PhiDesc) obj; - return virtualObject == other.virtualObject && fieldIndex == other.fieldIndex; - } - } - - private void processLoopEnd(LoopBeginNode loopBegin, LoopEndNode loopEnd, BlockState initialState, BlockState loopEndState, GraphEffectList successEffects, - Set<VirtualObjectNode> additionalMaterializations, HashSet<PhiDesc> phis) { - assert loopEnd.loopBegin() == loopBegin; - boolean materialized; - do { - materialized = false; - for (ObjectState state : initialState.states()) { - ObjectState endState = loopEndState.objectState(state.virtual); - if (state.materializedValue == null) { - if (endState.materializedValue == null) { - assert state.fieldState.length == endState.fieldState.length; - for (int i = 0; endState.fieldState != null && i < state.fieldState.length; i++) { - ValueNode value = state.fieldState[i]; - ValueNode endValue = endState.fieldState[i]; - ObjectState valueObj = initialState.objectState(value); - ObjectState endValueObj = loopEndState.objectState(endValue); - - if (valueObj != null) { - if (valueObj.materializedValue == null) { - if (endValueObj == null || endValueObj.materializedValue != null || valueObj.virtual != endValueObj.virtual) { - additionalMaterializations.add(valueObj.virtual); - } else { - // endValue is also virtual and refers to the same virtual object, so we're - // good. - } - } - } else { - if (value instanceof PhiNode && ((PhiNode) value).merge() == loopBegin) { - if (endValueObj != null) { - if (endValueObj.materializedValue == null) { - loopEndState.materializeBefore(loopEnd, endValueObj.virtual, successEffects); - materialized = true; - } - } - } - } - } - } else { - additionalMaterializations.add(state.virtual); - } - } - } - for (PhiNode phi : loopBegin.phis().snapshot()) { - if (usages.isMarked(phi) && phi.type() == PhiType.Value) { - ObjectState initialObj = initialState.objectState(phi.valueAt(0)); - boolean initialMaterialized = initialObj == null || initialObj.materializedValue != null; - - ObjectState loopEndObj = loopEndState.objectState(phi.valueAt(loopEnd)); - if (loopEndObj == null || loopEndObj.materializedValue != null) { - if (loopEndObj != null) { - successEffects.setPhiInput(phi, loopEndObj.materializedValue, loopBegin.phiPredecessorIndex(loopEnd)); - } - if (!initialMaterialized) { - additionalMaterializations.add(initialObj.virtual); - } - } else { - if (initialMaterialized) { - loopEndState.materializeBefore(loopEnd, loopEndObj.virtual, successEffects); - materialized = true; - } else { - if (loopEndObj.virtual != initialObj.virtual) { - additionalMaterializations.add(initialObj.virtual); - } - } - } - } - } - } while (materialized); - - for (ObjectState state : initialState.states()) { - ObjectState endState = loopEndState.objectState(state.virtual); - if (state.materializedValue == null) { - if (endState.materializedValue == null) { - assert state.fieldState.length == endState.fieldState.length; - for (int i = 0; i < state.fieldState.length; i++) { - ValueNode value = state.fieldState[i]; - ValueNode endValue = endState.fieldState[i]; - ObjectState valueObj = initialState.objectState(value); - ObjectState endValueObj = loopEndState.objectState(endValue); - - if (valueObj != null) { - if (valueObj.materializedValue == null) { - if (endValueObj == null || endValueObj.materializedValue != null || valueObj.virtual != endValueObj.virtual) { - assert !additionalMaterializations.isEmpty(); - } else { - // endValue is also virtual and refers to the same virtual object, so we're - // good. - } - } else { - if ((endValueObj != null && endValueObj.materializedValue != valueObj.materializedValue) || (endValueObj == null && valueObj.materializedValue != endValue)) { - phis.add(new PhiDesc(state.virtual, i)); - } else { - // either endValue has the same materialized value as value or endValue is the - // same as the materialized value, so we're good. - } - } - } else { - if (value instanceof PhiNode && ((PhiNode) value).merge() == loopBegin) { - if (endValueObj != null) { - if (endValueObj.materializedValue == null) { - assert !additionalMaterializations.isEmpty(); - } - successEffects.addPhiInput((PhiNode) value, endValueObj.materializedValue); - } else { - successEffects.addPhiInput((PhiNode) value, endValue); - } - } else if (value != endValue) { - phis.add(new PhiDesc(state.virtual, i)); - } - } - } - } else { - // endState.materializedValue != null - assert !additionalMaterializations.isEmpty(); - } - } else { - // state.materializedValue != null - if (endState.materializedValue == null) { - // throw new GraalInternalError("un-materialized object state at %s", loopEnd); - } else { - if (state.materializedValue != endState.materializedValue) { - // throw new GraalInternalError("changed materialized value during loop: %s vs %s", - // state.materializedValue, endState.materializedValue); - } - } - } - } - } - } -} - -public class SplitPartialEscapeAnalysisPhase extends Phase { - - private final GraalCodeCacheProvider runtime; - - public SplitPartialEscapeAnalysisPhase(GraalCodeCacheProvider runtime) { - this.runtime = runtime; - } - - @Override - protected void run(StructuredGraph graph) { - SchedulePhase schedule = new SchedulePhase(); - schedule.apply(graph, false); - new EscapeAnalysisIteration(graph, schedule, runtime).run(); - } -}
--- a/make/defs.make Fri Nov 09 13:32:53 2012 +0100 +++ b/make/defs.make Fri Nov 09 13:35:26 2012 +0100 @@ -22,6 +22,14 @@ # # +ifeq ($(HS_ALT_MAKE),) + ifneq ($(OPENJDK),true) + HS_ALT_MAKE=$(GAMMADIR)/make/closed + else + HS_ALT_MAKE=NO_SUCH_PATH + endif +endif + # The common definitions for hotspot builds. # Optionally include SPEC file generated by configure. @@ -327,3 +335,4 @@ ifndef JAVASE_EMBEDDED EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jfr.h endif +
--- a/make/hotspot_version Fri Nov 09 13:32:53 2012 +0100 +++ b/make/hotspot_version Fri Nov 09 13:35:26 2012 +0100 @@ -35,7 +35,7 @@ HS_MAJOR_VER=24 HS_MINOR_VER=0 -HS_BUILD_NUMBER=20 +HS_BUILD_NUMBER=22 JDK_MAJOR_VER=1 JDK_MINOR_VER=8
--- a/make/jprt.properties Fri Nov 09 13:32:53 2012 +0100 +++ b/make/jprt.properties Fri Nov 09 13:35:26 2012 +0100 @@ -38,7 +38,7 @@ # This tells jprt what default release we want to build -jprt.hotspot.default.release=jdk7 +jprt.hotspot.default.release=jdk8 jprt.tools.default.release=${jprt.submit.option.release?${jprt.submit.option.release}:${jprt.hotspot.default.release}} @@ -54,77 +54,77 @@ # Define the Solaris platforms we want for the various releases jprt.my.solaris.sparc.jdk8=solaris_sparc_5.10 jprt.my.solaris.sparc.jdk7=solaris_sparc_5.10 -jprt.my.solaris.sparc.jdk7u6=${jprt.my.solaris.sparc.jdk7} +jprt.my.solaris.sparc.jdk7u8=${jprt.my.solaris.sparc.jdk7} jprt.my.solaris.sparc=${jprt.my.solaris.sparc.${jprt.tools.default.release}} jprt.my.solaris.sparcv9.jdk8=solaris_sparcv9_5.10 jprt.my.solaris.sparcv9.jdk7=solaris_sparcv9_5.10 -jprt.my.solaris.sparcv9.jdk7u6=${jprt.my.solaris.sparcv9.jdk7} +jprt.my.solaris.sparcv9.jdk7u8=${jprt.my.solaris.sparcv9.jdk7} jprt.my.solaris.sparcv9=${jprt.my.solaris.sparcv9.${jprt.tools.default.release}} jprt.my.solaris.i586.jdk8=solaris_i586_5.10 jprt.my.solaris.i586.jdk7=solaris_i586_5.10 -jprt.my.solaris.i586.jdk7u6=${jprt.my.solaris.i586.jdk7} +jprt.my.solaris.i586.jdk7u8=${jprt.my.solaris.i586.jdk7} jprt.my.solaris.i586=${jprt.my.solaris.i586.${jprt.tools.default.release}} jprt.my.solaris.x64.jdk8=solaris_x64_5.10 jprt.my.solaris.x64.jdk7=solaris_x64_5.10 -jprt.my.solaris.x64.jdk7u6=${jprt.my.solaris.x64.jdk7} +jprt.my.solaris.x64.jdk7u8=${jprt.my.solaris.x64.jdk7} jprt.my.solaris.x64=${jprt.my.solaris.x64.${jprt.tools.default.release}} jprt.my.linux.i586.jdk8=linux_i586_2.6 jprt.my.linux.i586.jdk7=linux_i586_2.6 -jprt.my.linux.i586.jdk7u6=${jprt.my.linux.i586.jdk7} +jprt.my.linux.i586.jdk7u8=${jprt.my.linux.i586.jdk7} jprt.my.linux.i586=${jprt.my.linux.i586.${jprt.tools.default.release}} jprt.my.linux.x64.jdk8=linux_x64_2.6 jprt.my.linux.x64.jdk7=linux_x64_2.6 -jprt.my.linux.x64.jdk7u6=${jprt.my.linux.x64.jdk7} +jprt.my.linux.x64.jdk7u8=${jprt.my.linux.x64.jdk7} jprt.my.linux.x64=${jprt.my.linux.x64.${jprt.tools.default.release}} jprt.my.linux.ppc.jdk8=linux_ppc_2.6 jprt.my.linux.ppc.jdk7=linux_ppc_2.6 -jprt.my.linux.ppc.jdk7u6=${jprt.my.linux.ppc.jdk7} +jprt.my.linux.ppc.jdk7u8=${jprt.my.linux.ppc.jdk7} jprt.my.linux.ppc=${jprt.my.linux.ppc.${jprt.tools.default.release}} jprt.my.linux.ppcv2.jdk8=linux_ppcv2_2.6 jprt.my.linux.ppcv2.jdk7=linux_ppcv2_2.6 -jprt.my.linux.ppcv2.jdk7u6=${jprt.my.linux.ppcv2.jdk7} +jprt.my.linux.ppcv2.jdk7u8=${jprt.my.linux.ppcv2.jdk7} jprt.my.linux.ppcv2=${jprt.my.linux.ppcv2.${jprt.tools.default.release}} jprt.my.linux.ppcsflt.jdk8=linux_ppcsflt_2.6 jprt.my.linux.ppcsflt.jdk7=linux_ppcsflt_2.6 -jprt.my.linux.ppcsflt.jdk7u6=${jprt.my.linux.ppcsflt.jdk7} +jprt.my.linux.ppcsflt.jdk7u8=${jprt.my.linux.ppcsflt.jdk7} jprt.my.linux.ppcsflt=${jprt.my.linux.ppcsflt.${jprt.tools.default.release}} jprt.my.linux.armvfp.jdk8=linux_armvfp_2.6 jprt.my.linux.armvfp.jdk7=linux_armvfp_2.6 -jprt.my.linux.armvfp.jdk7u6=${jprt.my.linux.armvfp.jdk7} +jprt.my.linux.armvfp.jdk7u8=${jprt.my.linux.armvfp.jdk7} jprt.my.linux.armvfp=${jprt.my.linux.armvfp.${jprt.tools.default.release}} jprt.my.linux.armv6.jdk8=linux_armv6_2.6 jprt.my.linux.armv6.jdk7=linux_armv6_2.6 -jprt.my.linux.armv6.jdk7u6=${jprt.my.linux.armv6.jdk7} +jprt.my.linux.armv6.jdk7u8=${jprt.my.linux.armv6.jdk7} jprt.my.linux.armv6=${jprt.my.linux.armv6.${jprt.tools.default.release}} jprt.my.linux.armsflt.jdk8=linux_armsflt_2.6 jprt.my.linux.armsflt.jdk7=linux_armsflt_2.6 -jprt.my.linux.armsflt.jdk7u6=${jprt.my.linux.armsflt.jdk7} +jprt.my.linux.armsflt.jdk7u8=${jprt.my.linux.armsflt.jdk7} jprt.my.linux.armsflt=${jprt.my.linux.armsflt.${jprt.tools.default.release}} jprt.my.macosx.x64.jdk8=macosx_x64_10.7 jprt.my.macosx.x64.jdk7=macosx_x64_10.7 -jprt.my.macosx.x64.jdk7u6=${jprt.my.macosx.x64.jdk7} +jprt.my.macosx.x64.jdk7u8=${jprt.my.macosx.x64.jdk7} jprt.my.macosx.x64=${jprt.my.macosx.x64.${jprt.tools.default.release}} jprt.my.windows.i586.jdk8=windows_i586_5.1 jprt.my.windows.i586.jdk7=windows_i586_5.1 -jprt.my.windows.i586.jdk7u6=${jprt.my.windows.i586.jdk7} +jprt.my.windows.i586.jdk7u8=${jprt.my.windows.i586.jdk7} jprt.my.windows.i586=${jprt.my.windows.i586.${jprt.tools.default.release}} jprt.my.windows.x64.jdk8=windows_x64_5.2 jprt.my.windows.x64.jdk7=windows_x64_5.2 -jprt.my.windows.x64.jdk7u6=${jprt.my.windows.x64.jdk7} +jprt.my.windows.x64.jdk7u8=${jprt.my.windows.x64.jdk7} jprt.my.windows.x64=${jprt.my.windows.x64.${jprt.tools.default.release}} # Standard list of jprt build targets for this source tree @@ -159,7 +159,7 @@ jprt.build.targets.jdk8=${jprt.build.targets.all} jprt.build.targets.jdk7=${jprt.build.targets.all} -jprt.build.targets.jdk7u6=${jprt.build.targets.all} +jprt.build.targets.jdk7u8=${jprt.build.targets.all} jprt.build.targets=${jprt.build.targets.${jprt.tools.default.release}} # Subset lists of test targets for this source tree @@ -452,7 +452,7 @@ jprt.test.targets.jdk8=${jprt.test.targets.standard} jprt.test.targets.jdk7=${jprt.test.targets.standard} -jprt.test.targets.jdk7u6=${jprt.test.targets.jdk7} +jprt.test.targets.jdk7u8=${jprt.test.targets.jdk7} jprt.test.targets=${jprt.test.targets.${jprt.tools.default.release}} # The default test/Makefile targets that should be run @@ -512,7 +512,7 @@ jprt.make.rule.test.targets.jdk8=${jprt.make.rule.test.targets.standard} jprt.make.rule.test.targets.jdk7=${jprt.make.rule.test.targets.standard} -jprt.make.rule.test.targets.jdk7u6=${jprt.make.rule.test.targets.jdk7} +jprt.make.rule.test.targets.jdk7u8=${jprt.make.rule.test.targets.jdk7} jprt.make.rule.test.targets=${jprt.make.rule.test.targets.${jprt.tools.default.release}} # 7155453: Work-around to prevent popups on OSX from blocking test completion
--- a/make/linux/makefiles/adlc.make Fri Nov 09 13:32:53 2012 +0100 +++ b/make/linux/makefiles/adlc.make Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -133,8 +133,10 @@ # Note that product files are updated via "mv", which is atomic. TEMPDIR := $(OUTDIR)/mktmp$(shell echo $$$$) -# Debuggable by default -CFLAGS += -g +ifneq ($(DEBUG_BINARIES), true) + # Debuggable by default (unless already done by DEBUG_BINARIES) + CFLAGS += -g +endif # Pass -D flags into ADLC. ADLCFLAGS += $(SYSDEFS)
--- a/make/linux/makefiles/defs.make Fri Nov 09 13:32:53 2012 +0100 +++ b/make/linux/makefiles/defs.make Fri Nov 09 13:35:26 2012 +0100 @@ -295,6 +295,8 @@ ADD_SA_BINARIES/arm = ADD_SA_BINARIES/zero = +-include $(HS_ALT_MAKE)/linux/makefiles/defs.make + EXPORT_LIST += $(ADD_SA_BINARIES/$(HS_ARCH))
--- a/make/linux/makefiles/gcc.make Fri Nov 09 13:32:53 2012 +0100 +++ b/make/linux/makefiles/gcc.make Fri Nov 09 13:35:26 2012 +0100 @@ -215,47 +215,46 @@ #------------------------------------------------------------------------ # Debug flags -# Use the stabs format for debugging information (this is the default -# on gcc-2.91). It's good enough, has all the information about line -# numbers and local variables, and libjvm_g.so is only about 16M. -# Change this back to "-g" if you want the most expressive format. -# (warning: that could easily inflate libjvm_g.so to 150M!) -# Note: The Itanium gcc compiler crashes when using -gstabs. -DEBUG_CFLAGS/ia64 = -g -DEBUG_CFLAGS/amd64 = -g -DEBUG_CFLAGS/arm = -g -DEBUG_CFLAGS/ppc = -g -DEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH)) -ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),) -DEBUG_CFLAGS += -gstabs -endif - -ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) - FASTDEBUG_CFLAGS/ia64 = -g - FASTDEBUG_CFLAGS/amd64 = -g - FASTDEBUG_CFLAGS/arm = -g - FASTDEBUG_CFLAGS/ppc = -g - FASTDEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH)) - ifeq ($(FASTDEBUG_CFLAGS/$(BUILDARCH)),) - FASTDEBUG_CFLAGS += -gstabs +# DEBUG_BINARIES uses full -g debug information for all configs +ifeq ($(DEBUG_BINARIES), true) + CFLAGS += -g +else + # Use the stabs format for debugging information (this is the default + # on gcc-2.91). It's good enough, has all the information about line + # numbers and local variables, and libjvm_g.so is only about 16M. + # Change this back to "-g" if you want the most expressive format. + # (warning: that could easily inflate libjvm_g.so to 150M!) + # Note: The Itanium gcc compiler crashes when using -gstabs. + DEBUG_CFLAGS/ia64 = -g + DEBUG_CFLAGS/amd64 = -g + DEBUG_CFLAGS/arm = -g + DEBUG_CFLAGS/ppc = -g + DEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH)) + ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),) + DEBUG_CFLAGS += -gstabs endif - - OPT_CFLAGS/ia64 = -g - OPT_CFLAGS/amd64 = -g - OPT_CFLAGS/arm = -g - OPT_CFLAGS/ppc = -g - OPT_CFLAGS += $(OPT_CFLAGS/$(BUILDARCH)) - ifeq ($(OPT_CFLAGS/$(BUILDARCH)),) - OPT_CFLAGS += -gstabs + + ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + FASTDEBUG_CFLAGS/ia64 = -g + FASTDEBUG_CFLAGS/amd64 = -g + FASTDEBUG_CFLAGS/arm = -g + FASTDEBUG_CFLAGS/ppc = -g + FASTDEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH)) + ifeq ($(FASTDEBUG_CFLAGS/$(BUILDARCH)),) + FASTDEBUG_CFLAGS += -gstabs + endif + + OPT_CFLAGS/ia64 = -g + OPT_CFLAGS/amd64 = -g + OPT_CFLAGS/arm = -g + OPT_CFLAGS/ppc = -g + OPT_CFLAGS += $(OPT_CFLAGS/$(BUILDARCH)) + ifeq ($(OPT_CFLAGS/$(BUILDARCH)),) + OPT_CFLAGS += -gstabs + endif endif endif -# DEBUG_BINARIES overrides everything, use full -g debug information -ifeq ($(DEBUG_BINARIES), true) - DEBUG_CFLAGS = -g - CFLAGS += $(DEBUG_CFLAGS) -endif - # If we are building HEADLESS, pass on to VM # so it can set the java.awt.headless property ifdef HEADLESS
--- a/make/linux/makefiles/sa.make Fri Nov 09 13:32:53 2012 +0100 +++ b/make/linux/makefiles/sa.make Fri Nov 09 13:35:26 2012 +0100 @@ -30,10 +30,16 @@ include $(GAMMADIR)/make/linux/makefiles/rules.make +include $(GAMMADIR)/make/defs.make +include $(GAMMADIR)/make/altsrc.make + AGENT_DIR = $(GAMMADIR)/agent include $(GAMMADIR)/make/sa.files +-include $(HS_ALT_MAKE)/linux/makefiles/sa.make + + TOPDIR = $(shell echo `pwd`) GENERATED = $(TOPDIR)/../generated @@ -52,17 +58,15 @@ SA_PROPERTIES = $(SA_CLASSDIR)/sa.properties # if $(AGENT_DIR) does not exist, we don't build SA -# also, we don't build SA on Itanium, PowerPC, ARM or zero. +# also, we don't build SA on Itanium or zero. all: if [ -d $(AGENT_DIR) -a "$(SRCARCH)" != "ia64" \ - -a "$(SRCARCH)" != "arm" \ - -a "$(SRCARCH)" != "ppc" \ -a "$(SRCARCH)" != "zero" ] ; then \ $(MAKE) -f sa.make $(GENERATED)/sa-jdi.jar; \ fi -$(GENERATED)/sa-jdi.jar: $(AGENT_FILES) +$(GENERATED)/sa-jdi.jar:: $(AGENT_FILES) $(QUIETLY) echo "Making $@" $(QUIETLY) if [ "$(BOOT_JAVA_HOME)" = "" ]; then \ echo "ALT_BOOTDIR, BOOTDIR or JAVA_HOME needs to be defined to build SA"; \ @@ -111,3 +115,5 @@ rm -rf $(SA_CLASSDIR) rm -rf $(GENERATED)/sa-jdi.jar rm -rf $(AGENT_FILES_LIST) + +-include $(HS_ALT_MAKE)/linux/makefiles/sa-rules.make
--- a/make/linux/makefiles/saproc.make Fri Nov 09 13:32:53 2012 +0100 +++ b/make/linux/makefiles/saproc.make Fri Nov 09 13:35:26 2012 +0100 @@ -21,6 +21,8 @@ # questions. # # +include $(GAMMADIR)/make/defs.make +include $(GAMMADIR)/make/altsrc.make # Rules to build serviceability agent library, used by vm.make @@ -48,6 +50,8 @@ $(SASRCDIR)/ps_core.c \ $(SASRCDIR)/LinuxDebuggerLocal.c +-include $(HS_ALT_MAKE)/linux/makefiles/saproc.make + SAMAPFILE = $(SASRCDIR)/mapfile DEST_SAPROC = $(JDK_LIBDIR)/$(LIBSAPROC) @@ -60,15 +64,19 @@ endif # if $(AGENT_DIR) does not exist, we don't build SA -# also, we don't build SA on Itanium, PPC, ARM or zero. +# also, we don't build SA on Itanium or zero. ifneq ($(wildcard $(AGENT_DIR)),) -ifneq ($(filter-out ia64 arm ppc zero,$(SRCARCH)),) +ifneq ($(filter-out ia64 zero,$(SRCARCH)),) BUILDLIBSAPROC = $(LIBSAPROC) endif endif - +ifneq ($(ALT_SASRCDIR),) +ALT_SAINCDIR=-I$(ALT_SASRCDIR) +else +ALT_SAINCDIR= +endif SA_LFLAGS = $(MAPFLAG:FILENAME=$(SAMAPFILE)) $(LDFLAGS_HASH_STYLE) $(LIBSAPROC): $(SASRCFILES) $(SAMAPFILE) @@ -84,6 +92,7 @@ -I$(GENERATED) \ -I$(BOOT_JAVA_HOME)/include \ -I$(BOOT_JAVA_HOME)/include/$(Platform_os_family) \ + $(ALT_SAINCDIR) \ $(SASRCFILES) \ $(SA_LFLAGS) \ $(SA_DEBUG_CFLAGS) \
--- a/make/pic.make Fri Nov 09 13:32:53 2012 +0100 +++ b/make/pic.make Fri Nov 09 13:35:26 2012 +0100 @@ -32,7 +32,7 @@ ifndef LP64 PARTIAL_NONPIC=1 endif - PIC_ARCH = ppc + PIC_ARCH = ppc arm ifneq ("$(filter $(PIC_ARCH),$(BUILDARCH))","") PARTIAL_NONPIC=0 endif
--- a/make/windows/makefiles/defs.make Fri Nov 09 13:32:53 2012 +0100 +++ b/make/windows/makefiles/defs.make Fri Nov 09 13:35:26 2012 +0100 @@ -188,14 +188,22 @@ MAKE_ARGS += JDK_BUILD_NUMBER=$(COOKED_BUILD_NUMBER) endif -NMAKE= MAKEFLAGS= MFLAGS= nmake /NOLOGO +NMAKE= MAKEFLAGS= MFLAGS= nmake -NOLOGO +ifndef SYSTEM_UNAME + SYSTEM_UNAME := $(shell uname) + export SYSTEM_UNAME +endif # Check for CYGWIN -ifneq (,$(findstring CYGWIN,$(shell uname))) +ifneq (,$(findstring CYGWIN,$(SYSTEM_UNAME))) USING_CYGWIN=true else USING_CYGWIN=false endif +# Check for MinGW +ifneq (,$(findstring MINGW,$(SYSTEM_UNAME))) + USING_MINGW=true +endif # FIXUP: The subdirectory for a debug build is NOT the same on all platforms VM_DEBUG=debug @@ -208,11 +216,16 @@ ABS_BOOTDIR := $(subst /,\\,$(shell /bin/cygpath -m -a "$(BOOTDIR)")) ABS_GAMMADIR := $(subst /,\\,$(shell /bin/cygpath -m -a "$(GAMMADIR)")) ABS_OS_MAKEFILE := $(shell /bin/cygpath -m -a "$(HS_MAKE_DIR)/$(OSNAME)")/build.make -else - ABS_OUTPUTDIR := $(subst /,\\,$(shell $(CD) $(OUTPUTDIR);$(PWD))) - ABS_BOOTDIR := $(subst /,\\,$(shell $(CD) $(BOOTDIR);$(PWD))) - ABS_GAMMADIR := $(subst /,\\,$(shell $(CD) $(GAMMADIR);$(PWD))) - ABS_OS_MAKEFILE := $(subst /,\\,$(shell $(CD) $(HS_MAKE_DIR)/$(OSNAME);$(PWD))/build.make) +else ifeq ($(USING_MINGW), true) + ABS_OUTPUTDIR := $(shell $(CD) $(OUTPUTDIR);$(PWD)) + ABS_BOOTDIR := $(shell $(CD) $(BOOTDIR);$(PWD)) + ABS_GAMMADIR := $(shell $(CD) $(GAMMADIR);$(PWD)) + ABS_OS_MAKEFILE := $(shell $(CD) $(HS_MAKE_DIR)/$(OSNAME);$(PWD))/build.make + else + ABS_OUTPUTDIR := $(subst /,\\,$(shell $(CD) $(OUTPUTDIR);$(PWD))) + ABS_BOOTDIR := $(subst /,\\,$(shell $(CD) $(BOOTDIR);$(PWD))) + ABS_GAMMADIR := $(subst /,\\,$(shell $(CD) $(GAMMADIR);$(PWD))) + ABS_OS_MAKEFILE := $(subst /,\\,$(shell $(CD) $(HS_MAKE_DIR)/$(OSNAME);$(PWD))/build.make) endif # Disable building SA on windows until we are sure
--- a/make/windows/makefiles/rules.make Fri Nov 09 13:32:53 2012 +0100 +++ b/make/windows/makefiles/rules.make Fri Nov 09 13:35:26 2012 +0100 @@ -23,14 +23,15 @@ # # These are the commands used externally to compile and run. - +# The \ are used here for traditional Windows apps and " quoted to get +# past the Unix-like shell: !ifdef BootStrapDir -RUN_JAVA=$(BootStrapDir)\bin\java -RUN_JAVAP=$(BootStrapDir)\bin\javap -RUN_JAVAH=$(BootStrapDir)\bin\javah -RUN_JAR=$(BootStrapDir)\bin\jar -COMPILE_JAVAC=$(BootStrapDir)\bin\javac $(BOOTSTRAP_JAVAC_FLAGS) -COMPILE_RMIC=$(BootStrapDir)\bin\rmic +RUN_JAVA="$(BootStrapDir)\bin\java" +RUN_JAVAP="$(BootStrapDir)\bin\javap" +RUN_JAVAH="$(BootStrapDir)\bin\javah" +RUN_JAR="$(BootStrapDir)\bin\jar" +COMPILE_JAVAC="$(BootStrapDir)\bin\javac" $(BOOTSTRAP_JAVAC_FLAGS) +COMPILE_RMIC="$(BootStrapDir)\bin\rmic" BOOT_JAVA_HOME=$(BootStrapDir) !else RUN_JAVA=java
--- a/make/windows/makefiles/sa.make Fri Nov 09 13:32:53 2012 +0100 +++ b/make/windows/makefiles/sa.make Fri Nov 09 13:35:26 2012 +0100 @@ -36,37 +36,37 @@ !include $(WorkSpace)/make/windows/makefiles/rules.make !include $(WorkSpace)/make/sa.files -GENERATED = ..\generated +GENERATED = ../generated # tools.jar is needed by the JDI - SA binding -SA_CLASSPATH = $(BOOT_JAVA_HOME)\lib\tools.jar +SA_CLASSPATH = $(BOOT_JAVA_HOME)/lib/tools.jar -SA_CLASSDIR = $(GENERATED)\saclasses +SA_CLASSDIR = $(GENERATED)/saclasses SA_BUILD_VERSION_PROP = sun.jvm.hotspot.runtime.VM.saBuildVersion=$(SA_BUILD_VERSION) -SA_PROPERTIES = $(SA_CLASSDIR)\sa.properties +SA_PROPERTIES = $(SA_CLASSDIR)/sa.properties -default:: $(GENERATED)\sa-jdi.jar +default:: $(GENERATED)/sa-jdi.jar # Remove the space between $(SA_BUILD_VERSION_PROP) and > below as it adds a white space # at the end of SA version string and causes a version mismatch with the target VM version. -$(GENERATED)\sa-jdi.jar: $(AGENT_FILES:/=\) - @if not exist $(SA_CLASSDIR) mkdir $(SA_CLASSDIR) - @echo ...Building sa-jdi.jar +$(GENERATED)/sa-jdi.jar: $(AGENT_FILES) + $(QUIETLY) mkdir -p $(SA_CLASSDIR) + @echo ...Building sa-jdi.jar into $(SA_CLASSDIR) @echo ...$(COMPILE_JAVAC) -classpath $(SA_CLASSPATH) -d $(SA_CLASSDIR) .... - @$(COMPILE_JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES:/=\) + @$(COMPILE_JAVAC) -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES) $(COMPILE_RMIC) -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer $(QUIETLY) echo $(SA_BUILD_VERSION_PROP)> $(SA_PROPERTIES) $(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js $(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/utilities/soql/sa.js $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql $(QUIETLY) rm -rf $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources - $(QUIETLY) mkdir $(SA_CLASSDIR)\sun\jvm\hotspot\ui\resources + $(QUIETLY) mkdir $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources $(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/ui/resources/*.png $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources $(QUIETLY) cp -r $(AGENT_SRC_DIR)/images/* $(SA_CLASSDIR) $(RUN_JAR) cf $@ -C $(SA_CLASSDIR) . - $(RUN_JAR) uf $@ -C $(AGENT_SRC_DIR:/=\) META-INF\services\com.sun.jdi.connect.Connector + $(RUN_JAR) uf $@ -C $(AGENT_SRC_DIR) META-INF/services/com.sun.jdi.connect.Connector $(RUN_JAVAH) -classpath $(SA_CLASSDIR) -jni sun.jvm.hotspot.debugger.windbg.WindbgDebuggerLocal $(RUN_JAVAH) -classpath $(SA_CLASSDIR) -jni sun.jvm.hotspot.debugger.x86.X86ThreadContext $(RUN_JAVAH) -classpath $(SA_CLASSDIR) -jni sun.jvm.hotspot.debugger.ia64.IA64ThreadContext @@ -85,27 +85,27 @@ # will be useful to have the assertion checks in place !if "$(BUILDARCH)" == "ia64" -SA_CFLAGS = /nologo $(MS_RUNTIME_OPTION) /W3 $(GX_OPTION) /Od /D "WIN32" /D "WIN64" /D "_WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +SA_CFLAGS = -nologo $(MS_RUNTIME_OPTION) -W3 $(GX_OPTION) -Od -D "WIN32" -D "WIN64" -D "_WINDOWS" -D "_DEBUG" -D "_CONSOLE" -D "_MBCS" -YX -FD -c !elseif "$(BUILDARCH)" == "amd64" -SA_CFLAGS = /nologo $(MS_RUNTIME_OPTION) /W3 $(GX_OPTION) /Od /D "WIN32" /D "WIN64" /D "_WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +SA_CFLAGS = -nologo $(MS_RUNTIME_OPTION) -W3 $(GX_OPTION) -Od -D "WIN32" -D "WIN64" -D "_WINDOWS" -D "_DEBUG" -D "_CONSOLE" -D "_MBCS" -YX -FD -c !if "$(COMPILER_NAME)" == "VS2005" # On amd64, VS2005 compiler requires bufferoverflowU.lib on the link command line, # otherwise we get missing __security_check_cookie externals at link time. SA_LD_FLAGS = bufferoverflowU.lib !endif !else -SA_CFLAGS = /nologo $(MS_RUNTIME_OPTION) /W3 /Gm $(GX_OPTION) /Od /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +SA_CFLAGS = -nologo $(MS_RUNTIME_OPTION) -W3 -Gm $(GX_OPTION) -Od -D "WIN32" -D "_WINDOWS" -D "_DEBUG" -D "_CONSOLE" -D "_MBCS" -YX -FD -GZ -c !if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1" -SA_CFLAGS = $(SA_CFLAGS) /ZI +SA_CFLAGS = $(SA_CFLAGS) -ZI !endif !endif !if "$(MT)" != "" -SA_LD_FLAGS = /manifest $(SA_LD_FLAGS) +SA_LD_FLAGS = -manifest $(SA_LD_FLAGS) !endif SASRCFILE = $(AGENT_DIR)/src/os/win32/windbg/sawindbg.cpp -SA_LFLAGS = $(SA_LD_FLAGS) /nologo /subsystem:console /machine:$(MACHINE) +SA_LFLAGS = $(SA_LD_FLAGS) -nologo -subsystem:console -machine:$(MACHINE) !if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1" -SA_LFLAGS = $(SA_LFLAGS) /map /debug +SA_LFLAGS = $(SA_LFLAGS) -map -debug !endif # Note that we do not keep sawindbj.obj around as it would then @@ -117,15 +117,15 @@ $(SAWINDBG): $(SASRCFILE) set INCLUDE=$(SA_INCLUDE)$(INCLUDE) $(CXX) @<< - /I"$(BootStrapDir)/include" /I"$(BootStrapDir)/include/win32" - /I"$(GENERATED)" $(SA_CFLAGS) + -I"$(BootStrapDir)/include" -I"$(BootStrapDir)/include/win32" + -I"$(GENERATED)" $(SA_CFLAGS) $(SASRCFILE) - /out:$*.obj + -out:$*.obj << set LIB=$(SA_LIB)$(LIB) - $(LD) /out:$@ /DLL $*.obj dbgeng.lib $(SA_LFLAGS) + $(LD) -out:$@ -DLL $*.obj dbgeng.lib $(SA_LFLAGS) !if "$(MT)" != "" - $(MT) /manifest $(@F).manifest /outputresource:$(@F);#2 + $(MT) -manifest $(@F).manifest -outputresource:$(@F);#2 !endif !if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1" !if "$(ZIP_DEBUGINFO_FILES)" == "1" @@ -136,6 +136,6 @@ -@rm -f $*.obj cleanall : - rm -rf $(GENERATED:\=/)/saclasses - rm -rf $(GENERATED:\=/)/sa-jdi.jar + rm -rf $(GENERATED)/saclasses + rm -rf $(GENERATED)/sa-jdi.jar !endif
--- a/make/windows/makefiles/shared.make Fri Nov 09 13:32:53 2012 +0100 +++ b/make/windows/makefiles/shared.make Fri Nov 09 13:35:26 2012 +0100 @@ -36,11 +36,12 @@ !ifdef SUBDIRS +# \ is used below because $(MAKE) is nmake here, which expects Windows paths $(SUBDIRS): FORCE @if not exist $@ mkdir $@ - @if not exist $@\local.make echo # Empty > $@\local.make - @echo nmake $(ACTION) in $(DIR)\$@ - cd $@ && $(MAKE) /NOLOGO /f $(WorkSpace)\make\windows\makefiles\$@.make $(ACTION) DIR=$(DIR)\$@ BUILD_FLAVOR=$(BUILD_FLAVOR) + @if not exist $@/local.make echo # Empty > $@/local.make + @echo nmake $(ACTION) in $(DIR)/$@ + cd $@ && $(MAKE) -NOLOGO -f $(WorkSpace)\make\windows\makefiles\$@.make $(ACTION) DIR=$(DIR)\$@ BUILD_FLAVOR=$(BUILD_FLAVOR) !endif # Creates the needed directory
--- a/make/windows/projectfiles/common/Makefile Fri Nov 09 13:32:53 2012 +0100 +++ b/make/windows/projectfiles/common/Makefile Fri Nov 09 13:35:26 2012 +0100 @@ -108,7 +108,7 @@ -define HOTSPOT_VM_DISTRO=\\\"$(HOTSPOT_VM_DISTRO)\\\" $(HOTSPOTBUILDSPACE)/$(ProjectFile): $(HOTSPOTBUILDSPACE)/classes/ProjectCreator.class - @$(RUN_JAVA) -Djava.class.path=$(HOTSPOTBUILDSPACE)/classes ProjectCreator WinGammaPlatform$(VcVersion) $(ProjectCreatorIDEOptions) + @$(RUN_JAVA) -Djava.class.path="$(HOTSPOTBUILDSPACE)/classes" ProjectCreator WinGammaPlatform$(VcVersion) $(ProjectCreatorIDEOptions) clean: @rm -rf $(HOTSPOTBUILDSPACE)/classes
--- a/mx/projects Fri Nov 09 13:32:53 2012 +0100 +++ b/mx/projects Fri Nov 09 13:35:26 2012 +0100 @@ -55,6 +55,13 @@ project@com.oracle.graal.api.interpreter@checkstyle=com.oracle.graal.graph project@com.oracle.graal.api.interpreter@javaCompliance=1.7 +# graal.amd64 +project@com.oracle.graal.amd64@subDir=graal +project@com.oracle.graal.amd64@sourceDirs=src +project@com.oracle.graal.amd64@dependencies=com.oracle.graal.api.code +project@com.oracle.graal.amd64@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.amd64@javaCompliance=1.7 + # graal.hotspot project@com.oracle.graal.hotspot@subDir=graal project@com.oracle.graal.hotspot@sourceDirs=src @@ -230,6 +237,6 @@ # graal.asm.amd64 project@com.oracle.graal.asm.amd64@subDir=graal project@com.oracle.graal.asm.amd64@sourceDirs=src -project@com.oracle.graal.asm.amd64@dependencies=com.oracle.graal.asm +project@com.oracle.graal.asm.amd64@dependencies=com.oracle.graal.asm,com.oracle.graal.amd64 project@com.oracle.graal.asm.amd64@checkstyle=com.oracle.graal.graph project@com.oracle.graal.asm.amd64@javaCompliance=1.7
--- a/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -435,85 +435,6 @@ } -void G1UnsafeGetObjSATBBarrierStub::emit_code(LIR_Assembler* ce) { - // At this point we know that offset == referent_offset. - // - // So we might have to emit: - // if (src == null) goto continuation. - // - // and we definitely have to emit: - // if (klass(src).reference_type == REF_NONE) goto continuation - // if (!marking_active) goto continuation - // if (pre_val == null) goto continuation - // call pre_barrier(pre_val) - // goto continuation - // - __ bind(_entry); - - assert(src()->is_register(), "sanity"); - Register src_reg = src()->as_register(); - - if (gen_src_check()) { - // The original src operand was not a constant. - // Generate src == null? - if (__ is_in_wdisp16_range(_continuation)) { - __ br_null(src_reg, /*annul*/false, Assembler::pt, _continuation); - } else { - __ cmp(src_reg, G0); - __ brx(Assembler::equal, false, Assembler::pt, _continuation); - } - __ delayed()->nop(); - } - - // Generate src->_klass->_reference_type() == REF_NONE)? - assert(tmp()->is_register(), "sanity"); - Register tmp_reg = tmp()->as_register(); - - __ load_klass(src_reg, tmp_reg); - - Address ref_type_adr(tmp_reg, instanceKlass::reference_type_offset()); - __ ldub(ref_type_adr, tmp_reg); - - // _reference_type field is of type ReferenceType (enum) - assert(REF_NONE == 0, "check this code"); - __ cmp_zero_and_br(Assembler::equal, tmp_reg, _continuation, /*annul*/false, Assembler::pt); - __ delayed()->nop(); - - // Is marking active? - assert(thread()->is_register(), "precondition"); - Register thread_reg = thread()->as_pointer_register(); - - Address in_progress(thread_reg, in_bytes(JavaThread::satb_mark_queue_offset() + - PtrQueue::byte_offset_of_active())); - - if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { - __ ld(in_progress, tmp_reg); - } else { - assert(in_bytes(PtrQueue::byte_width_of_active()) == 1, "Assumption"); - __ ldsb(in_progress, tmp_reg); - } - - __ cmp_zero_and_br(Assembler::equal, tmp_reg, _continuation, /*annul*/false, Assembler::pt); - __ delayed()->nop(); - - // val == null? - assert(val()->is_register(), "Precondition."); - Register val_reg = val()->as_register(); - - if (__ is_in_wdisp16_range(_continuation)) { - __ br_null(val_reg, /*annul*/false, Assembler::pt, _continuation); - } else { - __ cmp(val_reg, G0); - __ brx(Assembler::equal, false, Assembler::pt, _continuation); - } - __ delayed()->nop(); - - __ call(Runtime1::entry_for(Runtime1::Runtime1::g1_pre_barrier_slow_id)); - __ delayed()->mov(val_reg, G4); - __ br(Assembler::always, false, Assembler::pt, _continuation); - __ delayed()->nop(); -} - jbyte* G1PostBarrierStub::_byte_map_base = NULL; jbyte* G1PostBarrierStub::byte_map_base_slow() {
--- a/src/cpu/sparc/vm/globals_sparc.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/cpu/sparc/vm/globals_sparc.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -75,4 +75,43 @@ // GC Ergo Flags define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread + +#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \ + \ + product(intx, UseVIS, 99, \ + "Highest supported VIS instructions set on Sparc") \ + \ + product(bool, UseCBCond, false, \ + "Use compare and branch instruction on SPARC") \ + \ + product(bool, UseBlockZeroing, false, \ + "Use special cpu instructions for block zeroing") \ + \ + product(intx, BlockZeroingLowLimit, 2048, \ + "Minimum size in bytes when block zeroing will be used") \ + \ + product(bool, UseBlockCopy, false, \ + "Use special cpu instructions for block copy") \ + \ + product(intx, BlockCopyLowLimit, 2048, \ + "Minimum size in bytes when block copy will be used") \ + \ + develop(bool, UseV8InstrsOnly, false, \ + "Use SPARC-V8 Compliant instruction subset") \ + \ + product(bool, UseNiagaraInstrs, false, \ + "Use Niagara-efficient instruction subset") \ + \ + develop(bool, UseCASForSwap, false, \ + "Do not use swap instructions, but only CAS (in a loop) on SPARC")\ + \ + product(uintx, ArraycopySrcPrefetchDistance, 0, \ + "Distance to prefetch source array in arracopy") \ + \ + product(uintx, ArraycopyDstPrefetchDistance, 0, \ + "Distance to prefetch destination array in arracopy") \ + \ + develop(intx, V8AtomicOperationUnderLockSpinCount, 50, \ + "Number of times to spin wait on a v8 atomic operation lock") \ + #endif // CPU_SPARC_VM_GLOBALS_SPARC_HPP
--- a/src/cpu/sparc/vm/vm_version_sparc.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/cpu/sparc/vm/vm_version_sparc.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -106,10 +106,10 @@ if (FLAG_IS_DEFAULT(OptoLoopAlignment)) { FLAG_SET_DEFAULT(OptoLoopAlignment, 4); } - // When using CMS, we cannot use memset() in BOT updates because - // the sun4v/CMT version in libc_psr uses BIS which exposes - // "phantom zeros" to concurrent readers. See 6948537. - if (FLAG_IS_DEFAULT(UseMemSetInBOT) && UseConcMarkSweepGC) { + // When using CMS or G1, we cannot use memset() in BOT updates + // because the sun4v/CMT version in libc_psr uses BIS which + // exposes "phantom zeros" to concurrent readers. See 6948537. + if (FLAG_IS_DEFAULT(UseMemSetInBOT) && (UseConcMarkSweepGC || UseG1GC)) { FLAG_SET_DEFAULT(UseMemSetInBOT, false); } #ifdef _LP64
--- a/src/cpu/x86/vm/assembler_x86.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/cpu/x86/vm/assembler_x86.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -999,32 +999,22 @@ void Assembler::addsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); - emit_byte(0x58); - emit_byte(0xC0 | encode); + emit_simd_arith(0x58, dst, src, VEX_SIMD_F2); } void Assembler::addsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_F2); - emit_byte(0x58); - emit_operand(dst, src); + emit_simd_arith(0x58, dst, src, VEX_SIMD_F2); } void Assembler::addss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); - emit_byte(0x58); - emit_byte(0xC0 | encode); + emit_simd_arith(0x58, dst, src, VEX_SIMD_F3); } void Assembler::addss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_F3); - emit_byte(0x58); - emit_operand(dst, src); + emit_simd_arith(0x58, dst, src, VEX_SIMD_F3); } void Assembler::andl(Address dst, int32_t imm32) { @@ -1052,36 +1042,6 @@ emit_arith(0x23, 0xC0, dst, src); } -void Assembler::andpd(XMMRegister dst, Address src) { - NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_66); - emit_byte(0x54); - emit_operand(dst, src); -} - -void Assembler::andpd(XMMRegister dst, XMMRegister src) { - NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); - emit_byte(0x54); - emit_byte(0xC0 | encode); -} - -void Assembler::andps(XMMRegister dst, Address src) { - NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_NONE); - emit_byte(0x54); - emit_operand(dst, src); -} - -void Assembler::andps(XMMRegister dst, XMMRegister src) { - NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_NONE); - emit_byte(0x54); - emit_byte(0xC0 | encode); -} - void Assembler::bsfl(Register dst, Register src) { int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); @@ -1246,61 +1206,42 @@ // NOTE: dbx seems to decode this as comiss even though the // 0x66 is there. Strangly ucomisd comes out correct NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_66); - emit_byte(0x2F); - emit_operand(dst, src); + emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_66); } void Assembler::comisd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66); - emit_byte(0x2F); - emit_byte(0xC0 | encode); + emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_66); } void Assembler::comiss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_NONE); - emit_byte(0x2F); - emit_operand(dst, src); + emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_NONE); } void Assembler::comiss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_NONE); - emit_byte(0x2F); - emit_byte(0xC0 | encode); + emit_simd_arith_nonds(0x2F, dst, src, VEX_SIMD_NONE); } void Assembler::cvtdq2pd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F3); - emit_byte(0xE6); - emit_byte(0xC0 | encode); + emit_simd_arith_nonds(0xE6, dst, src, VEX_SIMD_F3); } void Assembler::cvtdq2ps(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_NONE); - emit_byte(0x5B); - emit_byte(0xC0 | encode); + emit_simd_arith_nonds(0x5B, dst, src, VEX_SIMD_NONE); } void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); - emit_byte(0x5A); - emit_byte(0xC0 | encode); + emit_simd_arith(0x5A, dst, src, VEX_SIMD_F2); } void Assembler::cvtsd2ss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_F2); - emit_byte(0x5A); - emit_operand(dst, src); + emit_simd_arith(0x5A, dst, src, VEX_SIMD_F2); } void Assembler::cvtsi2sdl(XMMRegister dst, Register src) { @@ -1312,10 +1253,7 @@ void Assembler::cvtsi2sdl(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_F2); - emit_byte(0x2A); - emit_operand(dst, src); + emit_simd_arith(0x2A, dst, src, VEX_SIMD_F2); } void Assembler::cvtsi2ssl(XMMRegister dst, Register src) { @@ -1327,25 +1265,17 @@ void Assembler::cvtsi2ssl(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_F3); - emit_byte(0x2A); - emit_operand(dst, src); + emit_simd_arith(0x2A, dst, src, VEX_SIMD_F3); } void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); - emit_byte(0x5A); - emit_byte(0xC0 | encode); + emit_simd_arith(0x5A, dst, src, VEX_SIMD_F3); } void Assembler::cvtss2sd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_F3); - emit_byte(0x5A); - emit_operand(dst, src); + emit_simd_arith(0x5A, dst, src, VEX_SIMD_F3); } @@ -1373,32 +1303,22 @@ void Assembler::divsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_F2); - emit_byte(0x5E); - emit_operand(dst, src); + emit_simd_arith(0x5E, dst, src, VEX_SIMD_F2); } void Assembler::divsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); - emit_byte(0x5E); - emit_byte(0xC0 | encode); + emit_simd_arith(0x5E, dst, src, VEX_SIMD_F2); } void Assembler::divss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_F3); - emit_byte(0x5E); - emit_operand(dst, src); + emit_simd_arith(0x5E, dst, src, VEX_SIMD_F3); } void Assembler::divss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); - emit_byte(0x5E); - emit_byte(0xC0 | encode); + emit_simd_arith(0x5E, dst, src, VEX_SIMD_F3); } void Assembler::emms() { @@ -1634,16 +1554,12 @@ void Assembler::movapd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66); - emit_byte(0x28); - emit_byte(0xC0 | encode); + emit_simd_arith_nonds(0x28, dst, src, VEX_SIMD_66); } void Assembler::movaps(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_NONE); - emit_byte(0x28); - emit_byte(0xC0 | encode); + emit_simd_arith_nonds(0x28, dst, src, VEX_SIMD_NONE); } void Assembler::movlhps(XMMRegister dst, XMMRegister src) { @@ -1712,24 +1628,17 @@ void Assembler::movdqa(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66); - emit_byte(0x6F); - emit_byte(0xC0 | encode); + emit_simd_arith_nonds(0x6F, dst, src, VEX_SIMD_66); } void Assembler::movdqu(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_F3); - emit_byte(0x6F); - emit_operand(dst, src); + emit_simd_arith_nonds(0x6F, dst, src, VEX_SIMD_F3); } void Assembler::movdqu(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F3); - emit_byte(0x6F); - emit_byte(0xC0 | encode); + emit_simd_arith_nonds(0x6F, dst, src, VEX_SIMD_F3); } void Assembler::movdqu(Address dst, XMMRegister src) { @@ -1810,10 +1719,7 @@ // The selection is done in MacroAssembler::movdbl() and movflt(). void Assembler::movlpd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_66); - emit_byte(0x12); - emit_operand(dst, src); + emit_simd_arith(0x12, dst, src, VEX_SIMD_66); } void Assembler::movq( MMXRegister dst, Address src ) { @@ -1870,17 +1776,12 @@ void Assembler::movsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); - emit_byte(0x10); - emit_byte(0xC0 | encode); + emit_simd_arith(0x10, dst, src, VEX_SIMD_F2); } void Assembler::movsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_F2); - emit_byte(0x10); - emit_operand(dst, src); + emit_simd_arith_nonds(0x10, dst, src, VEX_SIMD_F2); } void Assembler::movsd(Address dst, XMMRegister src) { @@ -1893,17 +1794,12 @@ void Assembler::movss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); - emit_byte(0x10); - emit_byte(0xC0 | encode); + emit_simd_arith(0x10, dst, src, VEX_SIMD_F3); } void Assembler::movss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_F3); - emit_byte(0x10); - emit_operand(dst, src); + emit_simd_arith_nonds(0x10, dst, src, VEX_SIMD_F3); } void Assembler::movss(Address dst, XMMRegister src) { @@ -2001,32 +1897,22 @@ void Assembler::mulsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_F2); - emit_byte(0x59); - emit_operand(dst, src); + emit_simd_arith(0x59, dst, src, VEX_SIMD_F2); } void Assembler::mulsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); - emit_byte(0x59); - emit_byte(0xC0 | encode); + emit_simd_arith(0x59, dst, src, VEX_SIMD_F2); } void Assembler::mulss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_F3); - emit_byte(0x59); - emit_operand(dst, src); + emit_simd_arith(0x59, dst, src, VEX_SIMD_F3); } void Assembler::mulss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); - emit_byte(0x59); - emit_byte(0xC0 | encode); + emit_simd_arith(0x59, dst, src, VEX_SIMD_F3); } void Assembler::negl(Register dst) { @@ -2315,17 +2201,12 @@ void Assembler::packuswb(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_66); - emit_byte(0x67); - emit_operand(dst, src); + emit_simd_arith(0x67, dst, src, VEX_SIMD_66); } void Assembler::packuswb(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); - emit_byte(0x67); - emit_byte(0xC0 | encode); + emit_simd_arith(0x67, dst, src, VEX_SIMD_66); } void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) { @@ -2339,7 +2220,7 @@ void Assembler::pcmpestri(XMMRegister dst, XMMRegister src, int imm8) { assert(VM_Version::supports_sse4_2(), ""); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66, VEX_OPCODE_0F_3A); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A); emit_byte(0x61); emit_byte(0xC0 | encode); emit_byte(imm8); @@ -2355,7 +2236,7 @@ void Assembler::pmovzxbw(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_sse4_1(), ""); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_38); emit_byte(0x30); emit_byte(0xC0 | encode); } @@ -2456,28 +2337,10 @@ a_byte(p); } -void Assembler::por(XMMRegister dst, XMMRegister src) { - NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); - emit_byte(0xEB); - emit_byte(0xC0 | encode); -} - -void Assembler::por(XMMRegister dst, Address src) { - NOT_LP64(assert(VM_Version::supports_sse2(), "")); - assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_66); - emit_byte(0xEB); - emit_operand(dst, src); -} - void Assembler::pshufd(XMMRegister dst, XMMRegister src, int mode) { assert(isByte(mode), "invalid value"); NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66); - emit_byte(0x70); - emit_byte(0xC0 | encode); + emit_simd_arith_nonds(0x70, dst, src, VEX_SIMD_66); emit_byte(mode & 0xFF); } @@ -2496,9 +2359,7 @@ void Assembler::pshuflw(XMMRegister dst, XMMRegister src, int mode) { assert(isByte(mode), "invalid value"); NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_F2); - emit_byte(0x70); - emit_byte(0xC0 | encode); + emit_simd_arith_nonds(0x70, dst, src, VEX_SIMD_F2); emit_byte(mode & 0xFF); } @@ -2513,18 +2374,6 @@ emit_byte(mode & 0xFF); } -void Assembler::psrlq(XMMRegister dst, int shift) { - // Shift 64 bit value logically right by specified number of bits. - // HMM Table D-1 says sse2 or mmx. - // Do not confuse it with psrldq SSE2 instruction which - // shifts 128 bit value in xmm register by number of bytes. - NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66); - emit_byte(0x73); - emit_byte(0xC0 | encode); - emit_byte(shift); -} - void Assembler::psrldq(XMMRegister dst, int shift) { // Shift 128 bit value in xmm register by number of bytes. NOT_LP64(assert(VM_Version::supports_sse2(), "")); @@ -2545,7 +2394,7 @@ void Assembler::ptest(XMMRegister dst, XMMRegister src) { assert(VM_Version::supports_sse4_1(), ""); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_38); emit_byte(0x17); emit_byte(0xC0 | encode); } @@ -2553,40 +2402,28 @@ void Assembler::punpcklbw(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_66); - emit_byte(0x60); - emit_operand(dst, src); + emit_simd_arith(0x60, dst, src, VEX_SIMD_66); } void Assembler::punpcklbw(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); - emit_byte(0x60); - emit_byte(0xC0 | encode); + emit_simd_arith(0x60, dst, src, VEX_SIMD_66); } void Assembler::punpckldq(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_66); - emit_byte(0x62); - emit_operand(dst, src); + emit_simd_arith(0x62, dst, src, VEX_SIMD_66); } void Assembler::punpckldq(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); - emit_byte(0x62); - emit_byte(0xC0 | encode); + emit_simd_arith(0x62, dst, src, VEX_SIMD_66); } void Assembler::punpcklqdq(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); - emit_byte(0x6C); - emit_byte(0xC0 | encode); + emit_simd_arith(0x6C, dst, src, VEX_SIMD_66); } void Assembler::push(int32_t imm32) { @@ -2616,22 +2453,6 @@ } #endif -void Assembler::pxor(XMMRegister dst, Address src) { - NOT_LP64(assert(VM_Version::supports_sse2(), "")); - assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_66); - emit_byte(0xEF); - emit_operand(dst, src); -} - -void Assembler::pxor(XMMRegister dst, XMMRegister src) { - NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); - emit_byte(0xEF); - emit_byte(0xC0 | encode); -} - void Assembler::rcll(Register dst, int imm8) { assert(isShiftCount(imm8), "illegal shift count"); int encode = prefix_and_encode(dst->encoding()); @@ -2790,32 +2611,22 @@ void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); - emit_byte(0x51); - emit_byte(0xC0 | encode); + emit_simd_arith(0x51, dst, src, VEX_SIMD_F2); } void Assembler::sqrtsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_F2); - emit_byte(0x51); - emit_operand(dst, src); + emit_simd_arith(0x51, dst, src, VEX_SIMD_F2); } void Assembler::sqrtss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); - emit_byte(0x51); - emit_byte(0xC0 | encode); + emit_simd_arith(0x51, dst, src, VEX_SIMD_F3); } void Assembler::sqrtss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_F3); - emit_byte(0x51); - emit_operand(dst, src); + emit_simd_arith(0x51, dst, src, VEX_SIMD_F3); } void Assembler::stmxcsr( Address dst) { @@ -2865,32 +2676,22 @@ void Assembler::subsd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F2); - emit_byte(0x5C); - emit_byte(0xC0 | encode); + emit_simd_arith(0x5C, dst, src, VEX_SIMD_F2); } void Assembler::subsd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_F2); - emit_byte(0x5C); - emit_operand(dst, src); + emit_simd_arith(0x5C, dst, src, VEX_SIMD_F2); } void Assembler::subss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3); - emit_byte(0x5C); - emit_byte(0xC0 | encode); + emit_simd_arith(0x5C, dst, src, VEX_SIMD_F3); } void Assembler::subss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_F3); - emit_byte(0x5C); - emit_operand(dst, src); + emit_simd_arith(0x5C, dst, src, VEX_SIMD_F3); } void Assembler::testb(Register dst, int imm8) { @@ -2928,32 +2729,22 @@ void Assembler::ucomisd(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_66); - emit_byte(0x2E); - emit_operand(dst, src); + emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_66); } void Assembler::ucomisd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_66); - emit_byte(0x2E); - emit_byte(0xC0 | encode); + emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_66); } void Assembler::ucomiss(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - simd_prefix(dst, src, VEX_SIMD_NONE); - emit_byte(0x2E); - emit_operand(dst, src); + emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE); } void Assembler::ucomiss(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = simd_prefix_and_encode(dst, src, VEX_SIMD_NONE); - emit_byte(0x2E); - emit_byte(0xC0 | encode); + emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE); } @@ -2995,211 +2786,714 @@ emit_arith(0x33, 0xC0, dst, src); } -void Assembler::xorpd(XMMRegister dst, XMMRegister src) { - NOT_LP64(assert(VM_Version::supports_sse2(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66); - emit_byte(0x57); - emit_byte(0xC0 | encode); -} - -void Assembler::xorpd(XMMRegister dst, Address src) { - NOT_LP64(assert(VM_Version::supports_sse2(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_66); - emit_byte(0x57); - emit_operand(dst, src); -} - - -void Assembler::xorps(XMMRegister dst, XMMRegister src) { - NOT_LP64(assert(VM_Version::supports_sse(), "")); - int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_NONE); - emit_byte(0x57); - emit_byte(0xC0 | encode); -} - -void Assembler::xorps(XMMRegister dst, Address src) { - NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - simd_prefix(dst, dst, src, VEX_SIMD_NONE); - emit_byte(0x57); - emit_operand(dst, src); -} - -// AVX 3-operands non destructive source instructions (encoded with VEX prefix) + +// AVX 3-operands scalar float-point arithmetic instructions void Assembler::vaddsd(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); - InstructionMark im(this); - vex_prefix(dst, nds, src, VEX_SIMD_F2); - emit_byte(0x58); - emit_operand(dst, src); + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); } void Assembler::vaddsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_F2); - emit_byte(0x58); - emit_byte(0xC0 | encode); + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); } void Assembler::vaddss(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); - InstructionMark im(this); - vex_prefix(dst, nds, src, VEX_SIMD_F3); - emit_byte(0x58); - emit_operand(dst, src); + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); } void Assembler::vaddss(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_F3); - emit_byte(0x58); - emit_byte(0xC0 | encode); -} - -void Assembler::vandpd(XMMRegister dst, XMMRegister nds, Address src) { - assert(VM_Version::supports_avx(), ""); - InstructionMark im(this); - vex_prefix(dst, nds, src, VEX_SIMD_66); // 128-bit vector - emit_byte(0x54); - emit_operand(dst, src); -} - -void Assembler::vandps(XMMRegister dst, XMMRegister nds, Address src) { - assert(VM_Version::supports_avx(), ""); - InstructionMark im(this); - vex_prefix(dst, nds, src, VEX_SIMD_NONE); // 128-bit vector - emit_byte(0x54); - emit_operand(dst, src); + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); } void Assembler::vdivsd(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); - InstructionMark im(this); - vex_prefix(dst, nds, src, VEX_SIMD_F2); - emit_byte(0x5E); - emit_operand(dst, src); + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); } void Assembler::vdivsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_F2); - emit_byte(0x5E); - emit_byte(0xC0 | encode); + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); } void Assembler::vdivss(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); - InstructionMark im(this); - vex_prefix(dst, nds, src, VEX_SIMD_F3); - emit_byte(0x5E); - emit_operand(dst, src); + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); } void Assembler::vdivss(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_F3); - emit_byte(0x5E); - emit_byte(0xC0 | encode); + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); } void Assembler::vmulsd(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); - InstructionMark im(this); - vex_prefix(dst, nds, src, VEX_SIMD_F2); - emit_byte(0x59); - emit_operand(dst, src); + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); } void Assembler::vmulsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_F2); - emit_byte(0x59); - emit_byte(0xC0 | encode); + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); } void Assembler::vmulss(XMMRegister dst, XMMRegister nds, Address src) { - InstructionMark im(this); - vex_prefix(dst, nds, src, VEX_SIMD_F3); - emit_byte(0x59); - emit_operand(dst, src); + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); } void Assembler::vmulss(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_F3); - emit_byte(0x59); - emit_byte(0xC0 | encode); -} - + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); +} void Assembler::vsubsd(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); - InstructionMark im(this); - vex_prefix(dst, nds, src, VEX_SIMD_F2); - emit_byte(0x5C); - emit_operand(dst, src); + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); } void Assembler::vsubsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_F2); - emit_byte(0x5C); - emit_byte(0xC0 | encode); + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F2, /* vector256 */ false); } void Assembler::vsubss(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); - InstructionMark im(this); - vex_prefix(dst, nds, src, VEX_SIMD_F3); - emit_byte(0x5C); - emit_operand(dst, src); + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); } void Assembler::vsubss(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_F3); - emit_byte(0x5C); - emit_byte(0xC0 | encode); -} - -void Assembler::vxorpd(XMMRegister dst, XMMRegister nds, Address src) { + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_F3, /* vector256 */ false); +} + +//====================VECTOR ARITHMETIC===================================== + +// Float-point vector arithmetic + +void Assembler::addpd(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0x58, dst, src, VEX_SIMD_66); +} + +void Assembler::addps(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0x58, dst, src, VEX_SIMD_NONE); +} + +void Assembler::vaddpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vaddps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_NONE, vector256); +} + +void Assembler::vaddpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vaddps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x58, dst, nds, src, VEX_SIMD_NONE, vector256); +} + +void Assembler::subpd(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0x5C, dst, src, VEX_SIMD_66); +} + +void Assembler::subps(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0x5C, dst, src, VEX_SIMD_NONE); +} + +void Assembler::vsubpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vsubps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_NONE, vector256); +} + +void Assembler::vsubpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vsubps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x5C, dst, nds, src, VEX_SIMD_NONE, vector256); +} + +void Assembler::mulpd(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0x59, dst, src, VEX_SIMD_66); +} + +void Assembler::mulps(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0x59, dst, src, VEX_SIMD_NONE); +} + +void Assembler::vmulpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vmulps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_NONE, vector256); +} + +void Assembler::vmulpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { assert(VM_Version::supports_avx(), ""); - InstructionMark im(this); - vex_prefix(dst, nds, src, VEX_SIMD_66); // 128-bit vector - emit_byte(0x57); - emit_operand(dst, src); + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vmulps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x59, dst, nds, src, VEX_SIMD_NONE, vector256); +} + +void Assembler::divpd(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0x5E, dst, src, VEX_SIMD_66); +} + +void Assembler::divps(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0x5E, dst, src, VEX_SIMD_NONE); +} + +void Assembler::vdivpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vdivps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_NONE, vector256); +} + +void Assembler::vdivpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vdivps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x5E, dst, nds, src, VEX_SIMD_NONE, vector256); +} + +void Assembler::andpd(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0x54, dst, src, VEX_SIMD_66); +} + +void Assembler::andps(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse(), "")); + emit_simd_arith(0x54, dst, src, VEX_SIMD_NONE); +} + +void Assembler::andps(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse(), "")); + emit_simd_arith(0x54, dst, src, VEX_SIMD_NONE); +} + +void Assembler::andpd(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0x54, dst, src, VEX_SIMD_66); +} + +void Assembler::vandpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vandps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_NONE, vector256); +} + +void Assembler::vandpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vandps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_NONE, vector256); +} + +void Assembler::xorpd(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0x57, dst, src, VEX_SIMD_66); +} + +void Assembler::xorps(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse(), "")); + emit_simd_arith(0x57, dst, src, VEX_SIMD_NONE); +} + +void Assembler::xorpd(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0x57, dst, src, VEX_SIMD_66); +} + +void Assembler::xorps(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse(), "")); + emit_simd_arith(0x57, dst, src, VEX_SIMD_NONE); } void Assembler::vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { assert(VM_Version::supports_avx(), ""); - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector256); - emit_byte(0x57); - emit_byte(0xC0 | encode); -} - -void Assembler::vxorps(XMMRegister dst, XMMRegister nds, Address src) { - assert(VM_Version::supports_avx(), ""); - InstructionMark im(this); - vex_prefix(dst, nds, src, VEX_SIMD_NONE); // 128-bit vector - emit_byte(0x57); - emit_operand(dst, src); + emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_66, vector256); } void Assembler::vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { assert(VM_Version::supports_avx(), ""); - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_NONE, vector256); - emit_byte(0x57); + emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_NONE, vector256); +} + +void Assembler::vxorpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vxorps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx(), ""); + emit_vex_arith(0x57, dst, nds, src, VEX_SIMD_NONE, vector256); +} + + +// Integer vector arithmetic +void Assembler::paddb(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xFC, dst, src, VEX_SIMD_66); +} + +void Assembler::paddw(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xFD, dst, src, VEX_SIMD_66); +} + +void Assembler::paddd(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xFE, dst, src, VEX_SIMD_66); +} + +void Assembler::paddq(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xD4, dst, src, VEX_SIMD_66); +} + +void Assembler::vpaddb(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xFC, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xFD, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpaddd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xFE, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpaddq(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xD4, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpaddb(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xFC, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpaddw(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xFD, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpaddd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xFE, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpaddq(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xD4, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::psubb(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xF8, dst, src, VEX_SIMD_66); +} + +void Assembler::psubw(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xF9, dst, src, VEX_SIMD_66); +} + +void Assembler::psubd(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xFA, dst, src, VEX_SIMD_66); +} + +void Assembler::psubq(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xFB, dst, src, VEX_SIMD_66); +} + +void Assembler::vpsubb(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xF8, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpsubw(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xF9, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpsubd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xFA, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpsubq(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xFB, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpsubb(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xF8, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpsubw(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xF9, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpsubd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xFA, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpsubq(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xFB, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::pmullw(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xD5, dst, src, VEX_SIMD_66); +} + +void Assembler::pmulld(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sse4_1(), ""); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_38); + emit_byte(0x40); + emit_byte(0xC0 | encode); +} + +void Assembler::vpmullw(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xD5, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpmulld(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector256, VEX_OPCODE_0F_38); + emit_byte(0x40); + emit_byte(0xC0 | encode); +} + +void Assembler::vpmullw(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xD5, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpmulld(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + InstructionMark im(this); + int dst_enc = dst->encoding(); + int nds_enc = nds->is_valid() ? nds->encoding() : 0; + vex_prefix(src, nds_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector256); + emit_byte(0x40); + emit_operand(dst, src); +} + +// Shift packed integers left by specified number of bits. +void Assembler::psllw(XMMRegister dst, int shift) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + // XMM6 is for /6 encoding: 66 0F 71 /6 ib + int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66); + emit_byte(0x71); + emit_byte(0xC0 | encode); + emit_byte(shift & 0xFF); +} + +void Assembler::pslld(XMMRegister dst, int shift) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + // XMM6 is for /6 encoding: 66 0F 72 /6 ib + int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66); + emit_byte(0x72); + emit_byte(0xC0 | encode); + emit_byte(shift & 0xFF); +} + +void Assembler::psllq(XMMRegister dst, int shift) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + // XMM6 is for /6 encoding: 66 0F 73 /6 ib + int encode = simd_prefix_and_encode(xmm6, dst, dst, VEX_SIMD_66); + emit_byte(0x73); emit_byte(0xC0 | encode); + emit_byte(shift & 0xFF); +} + +void Assembler::psllw(XMMRegister dst, XMMRegister shift) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xF1, dst, shift, VEX_SIMD_66); +} + +void Assembler::pslld(XMMRegister dst, XMMRegister shift) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xF2, dst, shift, VEX_SIMD_66); +} + +void Assembler::psllq(XMMRegister dst, XMMRegister shift) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xF3, dst, shift, VEX_SIMD_66); +} + +void Assembler::vpsllw(XMMRegister dst, XMMRegister src, int shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + // XMM6 is for /6 encoding: 66 0F 71 /6 ib + emit_vex_arith(0x71, xmm6, dst, src, VEX_SIMD_66, vector256); + emit_byte(shift & 0xFF); +} + +void Assembler::vpslld(XMMRegister dst, XMMRegister src, int shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + // XMM6 is for /6 encoding: 66 0F 72 /6 ib + emit_vex_arith(0x72, xmm6, dst, src, VEX_SIMD_66, vector256); + emit_byte(shift & 0xFF); +} + +void Assembler::vpsllq(XMMRegister dst, XMMRegister src, int shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + // XMM6 is for /6 encoding: 66 0F 73 /6 ib + emit_vex_arith(0x73, xmm6, dst, src, VEX_SIMD_66, vector256); + emit_byte(shift & 0xFF); +} + +void Assembler::vpsllw(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xF1, dst, src, shift, VEX_SIMD_66, vector256); +} + +void Assembler::vpslld(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xF2, dst, src, shift, VEX_SIMD_66, vector256); +} + +void Assembler::vpsllq(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xF3, dst, src, shift, VEX_SIMD_66, vector256); +} + +// Shift packed integers logically right by specified number of bits. +void Assembler::psrlw(XMMRegister dst, int shift) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + // XMM2 is for /2 encoding: 66 0F 71 /2 ib + int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66); + emit_byte(0x71); + emit_byte(0xC0 | encode); + emit_byte(shift & 0xFF); +} + +void Assembler::psrld(XMMRegister dst, int shift) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + // XMM2 is for /2 encoding: 66 0F 72 /2 ib + int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66); + emit_byte(0x72); + emit_byte(0xC0 | encode); + emit_byte(shift & 0xFF); +} + +void Assembler::psrlq(XMMRegister dst, int shift) { + // Do not confuse it with psrldq SSE2 instruction which + // shifts 128 bit value in xmm register by number of bytes. + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + // XMM2 is for /2 encoding: 66 0F 73 /2 ib + int encode = simd_prefix_and_encode(xmm2, dst, dst, VEX_SIMD_66); + emit_byte(0x73); + emit_byte(0xC0 | encode); + emit_byte(shift & 0xFF); +} + +void Assembler::psrlw(XMMRegister dst, XMMRegister shift) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xD1, dst, shift, VEX_SIMD_66); +} + +void Assembler::psrld(XMMRegister dst, XMMRegister shift) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xD2, dst, shift, VEX_SIMD_66); +} + +void Assembler::psrlq(XMMRegister dst, XMMRegister shift) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xD3, dst, shift, VEX_SIMD_66); +} + +void Assembler::vpsrlw(XMMRegister dst, XMMRegister src, int shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + // XMM2 is for /2 encoding: 66 0F 73 /2 ib + emit_vex_arith(0x71, xmm2, dst, src, VEX_SIMD_66, vector256); + emit_byte(shift & 0xFF); +} + +void Assembler::vpsrld(XMMRegister dst, XMMRegister src, int shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + // XMM2 is for /2 encoding: 66 0F 73 /2 ib + emit_vex_arith(0x72, xmm2, dst, src, VEX_SIMD_66, vector256); + emit_byte(shift & 0xFF); +} + +void Assembler::vpsrlq(XMMRegister dst, XMMRegister src, int shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + // XMM2 is for /2 encoding: 66 0F 73 /2 ib + emit_vex_arith(0x73, xmm2, dst, src, VEX_SIMD_66, vector256); + emit_byte(shift & 0xFF); +} + +void Assembler::vpsrlw(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xD1, dst, src, shift, VEX_SIMD_66, vector256); +} + +void Assembler::vpsrld(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xD2, dst, src, shift, VEX_SIMD_66, vector256); +} + +void Assembler::vpsrlq(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xD3, dst, src, shift, VEX_SIMD_66, vector256); +} + +// Shift packed integers arithmetically right by specified number of bits. +void Assembler::psraw(XMMRegister dst, int shift) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + // XMM4 is for /4 encoding: 66 0F 71 /4 ib + int encode = simd_prefix_and_encode(xmm4, dst, dst, VEX_SIMD_66); + emit_byte(0x71); + emit_byte(0xC0 | encode); + emit_byte(shift & 0xFF); +} + +void Assembler::psrad(XMMRegister dst, int shift) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + // XMM4 is for /4 encoding: 66 0F 72 /4 ib + int encode = simd_prefix_and_encode(xmm4, dst, dst, VEX_SIMD_66); + emit_byte(0x72); + emit_byte(0xC0 | encode); + emit_byte(shift & 0xFF); +} + +void Assembler::psraw(XMMRegister dst, XMMRegister shift) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xE1, dst, shift, VEX_SIMD_66); +} + +void Assembler::psrad(XMMRegister dst, XMMRegister shift) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xE2, dst, shift, VEX_SIMD_66); +} + +void Assembler::vpsraw(XMMRegister dst, XMMRegister src, int shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + // XMM4 is for /4 encoding: 66 0F 71 /4 ib + emit_vex_arith(0x71, xmm4, dst, src, VEX_SIMD_66, vector256); + emit_byte(shift & 0xFF); +} + +void Assembler::vpsrad(XMMRegister dst, XMMRegister src, int shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + // XMM4 is for /4 encoding: 66 0F 71 /4 ib + emit_vex_arith(0x72, xmm4, dst, src, VEX_SIMD_66, vector256); + emit_byte(shift & 0xFF); +} + +void Assembler::vpsraw(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xE1, dst, src, shift, VEX_SIMD_66, vector256); +} + +void Assembler::vpsrad(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xE2, dst, src, shift, VEX_SIMD_66, vector256); +} + + +// AND packed integers +void Assembler::pand(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xDB, dst, src, VEX_SIMD_66); +} + +void Assembler::vpand(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xDB, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpand(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xDB, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::por(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xEB, dst, src, VEX_SIMD_66); +} + +void Assembler::vpor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xEB, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpor(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xEB, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::pxor(XMMRegister dst, XMMRegister src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + emit_simd_arith(0xEF, dst, src, VEX_SIMD_66); } void Assembler::vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { - assert(VM_Version::supports_avx2() || (!vector256) && VM_Version::supports_avx(), ""); - int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector256); - emit_byte(0xEF); - emit_byte(0xC0 | encode); -} + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xEF, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpxor(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0xEF, dst, nds, src, VEX_SIMD_66, vector256); +} + void Assembler::vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src) { assert(VM_Version::supports_avx(), ""); @@ -3805,6 +4099,49 @@ } } +void Assembler::emit_simd_arith(int opcode, XMMRegister dst, Address src, VexSimdPrefix pre) { + InstructionMark im(this); + simd_prefix(dst, dst, src, pre); + emit_byte(opcode); + emit_operand(dst, src); +} + +void Assembler::emit_simd_arith(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre) { + int encode = simd_prefix_and_encode(dst, dst, src, pre); + emit_byte(opcode); + emit_byte(0xC0 | encode); +} + +// Versions with no second source register (non-destructive source). +void Assembler::emit_simd_arith_nonds(int opcode, XMMRegister dst, Address src, VexSimdPrefix pre) { + InstructionMark im(this); + simd_prefix(dst, xnoreg, src, pre); + emit_byte(opcode); + emit_operand(dst, src); +} + +void Assembler::emit_simd_arith_nonds(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre) { + int encode = simd_prefix_and_encode(dst, xnoreg, src, pre); + emit_byte(opcode); + emit_byte(0xC0 | encode); +} + +// 3-operands AVX instructions +void Assembler::emit_vex_arith(int opcode, XMMRegister dst, XMMRegister nds, + Address src, VexSimdPrefix pre, bool vector256) { + InstructionMark im(this); + vex_prefix(dst, nds, src, pre, vector256); + emit_byte(opcode); + emit_operand(dst, src); +} + +void Assembler::emit_vex_arith(int opcode, XMMRegister dst, XMMRegister nds, + XMMRegister src, VexSimdPrefix pre, bool vector256) { + int encode = vex_prefix_and_encode(dst, nds, src, pre, vector256); + emit_byte(opcode); + emit_byte(0xC0 | encode); +} + #ifndef _LP64 void Assembler::incl(Register dst) { @@ -7968,21 +8305,21 @@ } } -void MacroAssembler::vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src) { +void MacroAssembler::vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) { if (reachable(src)) { - vandpd(dst, nds, as_Address(src)); + vandpd(dst, nds, as_Address(src), vector256); } else { lea(rscratch1, src); - vandpd(dst, nds, Address(rscratch1, 0)); - } -} - -void MacroAssembler::vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src) { + vandpd(dst, nds, Address(rscratch1, 0), vector256); + } +} + +void MacroAssembler::vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) { if (reachable(src)) { - vandps(dst, nds, as_Address(src)); + vandps(dst, nds, as_Address(src), vector256); } else { lea(rscratch1, src); - vandps(dst, nds, Address(rscratch1, 0)); + vandps(dst, nds, Address(rscratch1, 0), vector256); } } @@ -8040,21 +8377,21 @@ } } -void MacroAssembler::vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src) { +void MacroAssembler::vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) { if (reachable(src)) { - vxorpd(dst, nds, as_Address(src)); + vxorpd(dst, nds, as_Address(src), vector256); } else { lea(rscratch1, src); - vxorpd(dst, nds, Address(rscratch1, 0)); - } -} - -void MacroAssembler::vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src) { + vxorpd(dst, nds, Address(rscratch1, 0), vector256); + } +} + +void MacroAssembler::vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) { if (reachable(src)) { - vxorps(dst, nds, as_Address(src)); + vxorps(dst, nds, as_Address(src), vector256); } else { lea(rscratch1, src); - vxorps(dst, nds, Address(rscratch1, 0)); + vxorps(dst, nds, Address(rscratch1, 0), vector256); } }
--- a/src/cpu/x86/vm/assembler_x86.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/cpu/x86/vm/assembler_x86.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -617,6 +617,7 @@ VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F) { simd_prefix(dst, xnoreg, src, pre, opc); } + void simd_prefix(Address dst, XMMRegister src, VexSimdPrefix pre) { simd_prefix(src, dst, pre); } @@ -626,16 +627,10 @@ simd_prefix(dst, nds, src, pre, VEX_OPCODE_0F, rex_w); } - int simd_prefix_and_encode(XMMRegister dst, XMMRegister nds, XMMRegister src, VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F, bool rex_w = false, bool vector256 = false); - int simd_prefix_and_encode(XMMRegister dst, XMMRegister src, - VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F) { - return simd_prefix_and_encode(dst, xnoreg, src, pre, opc); - } - // Move/convert 32-bit integer value. int simd_prefix_and_encode(XMMRegister dst, XMMRegister nds, Register src, VexSimdPrefix pre) { @@ -677,6 +672,15 @@ void emit_arith(int op1, int op2, Register dst, jobject obj); void emit_arith(int op1, int op2, Register dst, Register src); + void emit_simd_arith(int opcode, XMMRegister dst, Address src, VexSimdPrefix pre); + void emit_simd_arith(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre); + void emit_simd_arith_nonds(int opcode, XMMRegister dst, Address src, VexSimdPrefix pre); + void emit_simd_arith_nonds(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre); + void emit_vex_arith(int opcode, XMMRegister dst, XMMRegister nds, + Address src, VexSimdPrefix pre, bool vector256); + void emit_vex_arith(int opcode, XMMRegister dst, XMMRegister nds, + XMMRegister src, VexSimdPrefix pre, bool vector256); + void emit_operand(Register reg, Register base, Register index, Address::ScaleFactor scale, int disp, @@ -891,12 +895,6 @@ void andq(Register dst, Address src); void andq(Register dst, Register src); - // Bitwise Logical AND of Packed Double-Precision Floating-Point Values - void andpd(XMMRegister dst, XMMRegister src); - - // Bitwise Logical AND of Packed Single-Precision Floating-Point Values - void andps(XMMRegister dst, XMMRegister src); - void bsfl(Register dst, Register src); void bsrl(Register dst, Register src); @@ -1436,10 +1434,6 @@ void prefetcht2(Address src); void prefetchw(Address src); - // POR - Bitwise logical OR - void por(XMMRegister dst, XMMRegister src); - void por(XMMRegister dst, Address src); - // Shuffle Packed Doublewords void pshufd(XMMRegister dst, XMMRegister src, int mode); void pshufd(XMMRegister dst, Address src, int mode); @@ -1448,9 +1442,6 @@ void pshuflw(XMMRegister dst, XMMRegister src, int mode); void pshuflw(XMMRegister dst, Address src, int mode); - // Shift Right by bits Logical Quadword Immediate - void psrlq(XMMRegister dst, int shift); - // Shift Right by bytes Logical DoubleQuadword Immediate void psrldq(XMMRegister dst, int shift); @@ -1475,10 +1466,6 @@ void pushq(Address src); - // Xor Packed Byte Integer Values - void pxor(XMMRegister dst, Address src); - void pxor(XMMRegister dst, XMMRegister src); - void rcll(Register dst, int imm8); void rclq(Register dst, int imm8); @@ -1601,15 +1588,10 @@ void xorq(Register dst, Address src); void xorq(Register dst, Register src); - // Bitwise Logical XOR of Packed Double-Precision Floating-Point Values - void xorpd(XMMRegister dst, XMMRegister src); - - // Bitwise Logical XOR of Packed Single-Precision Floating-Point Values - void xorps(XMMRegister dst, XMMRegister src); - void set_byte_if_not_zero(Register dst); // sets reg to 1 if not zero, otherwise 0 // AVX 3-operands scalar instructions (encoded with VEX prefix) + void vaddsd(XMMRegister dst, XMMRegister nds, Address src); void vaddsd(XMMRegister dst, XMMRegister nds, XMMRegister src); void vaddss(XMMRegister dst, XMMRegister nds, Address src); @@ -1627,14 +1609,147 @@ void vsubss(XMMRegister dst, XMMRegister nds, Address src); void vsubss(XMMRegister dst, XMMRegister nds, XMMRegister src); - // AVX Vector instrucitons. - void vandpd(XMMRegister dst, XMMRegister nds, Address src); - void vandps(XMMRegister dst, XMMRegister nds, Address src); - void vxorpd(XMMRegister dst, XMMRegister nds, Address src); - void vxorps(XMMRegister dst, XMMRegister nds, Address src); + + //====================VECTOR ARITHMETIC===================================== + + // Add Packed Floating-Point Values + void addpd(XMMRegister dst, XMMRegister src); + void addps(XMMRegister dst, XMMRegister src); + void vaddpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vaddps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vaddpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + void vaddps(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + + // Subtract Packed Floating-Point Values + void subpd(XMMRegister dst, XMMRegister src); + void subps(XMMRegister dst, XMMRegister src); + void vsubpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vsubps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vsubpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + void vsubps(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + + // Multiply Packed Floating-Point Values + void mulpd(XMMRegister dst, XMMRegister src); + void mulps(XMMRegister dst, XMMRegister src); + void vmulpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vmulps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vmulpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + void vmulps(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + + // Divide Packed Floating-Point Values + void divpd(XMMRegister dst, XMMRegister src); + void divps(XMMRegister dst, XMMRegister src); + void vdivpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vdivps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vdivpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + void vdivps(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + + // Bitwise Logical AND of Packed Floating-Point Values + void andpd(XMMRegister dst, XMMRegister src); + void andps(XMMRegister dst, XMMRegister src); + void vandpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vandps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vandpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + void vandps(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + + // Bitwise Logical XOR of Packed Floating-Point Values + void xorpd(XMMRegister dst, XMMRegister src); + void xorps(XMMRegister dst, XMMRegister src); void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); void vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vxorpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + void vxorps(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + + // Add packed integers + void paddb(XMMRegister dst, XMMRegister src); + void paddw(XMMRegister dst, XMMRegister src); + void paddd(XMMRegister dst, XMMRegister src); + void paddq(XMMRegister dst, XMMRegister src); + void vpaddb(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vpaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vpaddd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vpaddq(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vpaddb(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + void vpaddw(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + void vpaddd(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + void vpaddq(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + + // Sub packed integers + void psubb(XMMRegister dst, XMMRegister src); + void psubw(XMMRegister dst, XMMRegister src); + void psubd(XMMRegister dst, XMMRegister src); + void psubq(XMMRegister dst, XMMRegister src); + void vpsubb(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vpsubw(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vpsubd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vpsubq(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vpsubb(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + void vpsubw(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + void vpsubd(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + void vpsubq(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + + // Multiply packed integers (only shorts and ints) + void pmullw(XMMRegister dst, XMMRegister src); + void pmulld(XMMRegister dst, XMMRegister src); + void vpmullw(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vpmulld(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vpmullw(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + void vpmulld(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + + // Shift left packed integers + void psllw(XMMRegister dst, int shift); + void pslld(XMMRegister dst, int shift); + void psllq(XMMRegister dst, int shift); + void psllw(XMMRegister dst, XMMRegister shift); + void pslld(XMMRegister dst, XMMRegister shift); + void psllq(XMMRegister dst, XMMRegister shift); + void vpsllw(XMMRegister dst, XMMRegister src, int shift, bool vector256); + void vpslld(XMMRegister dst, XMMRegister src, int shift, bool vector256); + void vpsllq(XMMRegister dst, XMMRegister src, int shift, bool vector256); + void vpsllw(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256); + void vpslld(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256); + void vpsllq(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256); + + // Logical shift right packed integers + void psrlw(XMMRegister dst, int shift); + void psrld(XMMRegister dst, int shift); + void psrlq(XMMRegister dst, int shift); + void psrlw(XMMRegister dst, XMMRegister shift); + void psrld(XMMRegister dst, XMMRegister shift); + void psrlq(XMMRegister dst, XMMRegister shift); + void vpsrlw(XMMRegister dst, XMMRegister src, int shift, bool vector256); + void vpsrld(XMMRegister dst, XMMRegister src, int shift, bool vector256); + void vpsrlq(XMMRegister dst, XMMRegister src, int shift, bool vector256); + void vpsrlw(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256); + void vpsrld(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256); + void vpsrlq(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256); + + // Arithmetic shift right packed integers (only shorts and ints, no instructions for longs) + void psraw(XMMRegister dst, int shift); + void psrad(XMMRegister dst, int shift); + void psraw(XMMRegister dst, XMMRegister shift); + void psrad(XMMRegister dst, XMMRegister shift); + void vpsraw(XMMRegister dst, XMMRegister src, int shift, bool vector256); + void vpsrad(XMMRegister dst, XMMRegister src, int shift, bool vector256); + void vpsraw(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256); + void vpsrad(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256); + + // And packed integers + void pand(XMMRegister dst, XMMRegister src); + void vpand(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vpand(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + + // Or packed integers + void por(XMMRegister dst, XMMRegister src); + void vpor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vpor(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + + // Xor packed integers + void pxor(XMMRegister dst, XMMRegister src); void vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + void vpxor(XMMRegister dst, XMMRegister nds, Address src, bool vector256); + + // Copy low 128bit into high 128bit of YMM registers. void vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src); void vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src); @@ -2532,11 +2647,13 @@ void vaddss(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vaddss(dst, nds, src); } void vaddss(XMMRegister dst, XMMRegister nds, AddressLiteral src); - void vandpd(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vandpd(dst, nds, src); } - void vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src); - - void vandps(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vandps(dst, nds, src); } - void vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src); + void vandpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vandpd(dst, nds, src, vector256); } + void vandpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vandpd(dst, nds, src, vector256); } + void vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256); + + void vandps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vandps(dst, nds, src, vector256); } + void vandps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vandps(dst, nds, src, vector256); } + void vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256); void vdivsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vdivsd(dst, nds, src); } void vdivsd(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vdivsd(dst, nds, src); } @@ -2565,12 +2682,12 @@ // AVX Vector instructions void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vxorpd(dst, nds, src, vector256); } - void vxorpd(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vxorpd(dst, nds, src); } - void vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src); + void vxorpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vxorpd(dst, nds, src, vector256); } + void vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256); void vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vxorps(dst, nds, src, vector256); } - void vxorps(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vxorps(dst, nds, src); } - void vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src); + void vxorps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vxorps(dst, nds, src, vector256); } + void vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256); void vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { if (UseAVX > 1 || !vector256) // vpxor 256 bit is available only in AVX2 @@ -2578,6 +2695,12 @@ else Assembler::vxorpd(dst, nds, src, vector256); } + void vpxor(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { + if (UseAVX > 1 || !vector256) // vpxor 256 bit is available only in AVX2 + Assembler::vpxor(dst, nds, src, vector256); + else + Assembler::vxorpd(dst, nds, src, vector256); + } // Move packed integer values from low 128 bit to hign 128 bit in 256 bit vector. void vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) {
--- a/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -488,68 +488,6 @@ } -void G1UnsafeGetObjSATBBarrierStub::emit_code(LIR_Assembler* ce) { - // At this point we know that offset == referent_offset. - // - // So we might have to emit: - // if (src == null) goto continuation. - // - // and we definitely have to emit: - // if (klass(src).reference_type == REF_NONE) goto continuation - // if (!marking_active) goto continuation - // if (pre_val == null) goto continuation - // call pre_barrier(pre_val) - // goto continuation - // - __ bind(_entry); - - assert(src()->is_register(), "sanity"); - Register src_reg = src()->as_register(); - - if (gen_src_check()) { - // The original src operand was not a constant. - // Generate src == null? - __ cmpptr(src_reg, (int32_t) NULL_WORD); - __ jcc(Assembler::equal, _continuation); - } - - // Generate src->_klass->_reference_type == REF_NONE)? - assert(tmp()->is_register(), "sanity"); - Register tmp_reg = tmp()->as_register(); - - __ load_klass(tmp_reg, src_reg); - - Address ref_type_adr(tmp_reg, instanceKlass::reference_type_offset()); - __ cmpb(ref_type_adr, REF_NONE); - __ jcc(Assembler::equal, _continuation); - - // Is marking active? - assert(thread()->is_register(), "precondition"); - Register thread_reg = thread()->as_pointer_register(); - - Address in_progress(thread_reg, in_bytes(JavaThread::satb_mark_queue_offset() + - PtrQueue::byte_offset_of_active())); - - if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { - __ cmpl(in_progress, 0); - } else { - assert(in_bytes(PtrQueue::byte_width_of_active()) == 1, "Assumption"); - __ cmpb(in_progress, 0); - } - __ jcc(Assembler::equal, _continuation); - - // val == null? - assert(val()->is_register(), "Precondition."); - Register val_reg = val()->as_register(); - - __ cmpptr(val_reg, (int32_t) NULL_WORD); - __ jcc(Assembler::equal, _continuation); - - ce->store_parameter(val()->as_register(), 0); - __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::g1_pre_barrier_slow_id))); - __ jmp(_continuation); -} - jbyte* G1PostBarrierStub::_byte_map_base = NULL; jbyte* G1PostBarrierStub::byte_map_base_slow() {
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -1889,6 +1889,17 @@ break; } + case graal_OSR_migration_end_id: { + __ enter(); + save_live_registers(sasm, 0); + __ movptr(c_rarg0, j_rarg0); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_end))); + restore_live_registers(sasm); + __ leave(); + __ ret(0); + break; + } + case graal_set_deopt_info_id: { __ movptr(Address(r15_thread, JavaThread::graal_deopt_info_offset()), rscratch1); __ ret(0);
--- a/src/cpu/x86/vm/c1_globals_x86.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/cpu/x86/vm/c1_globals_x86.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -51,7 +51,7 @@ #ifdef GRAAL define_pd_global(bool, ProfileTraps, true ); -define_pd_global(bool, UseOnStackReplacement, false); +define_pd_global(bool, UseOnStackReplacement, true); define_pd_global(intx, CompileThreshold, 2500 ); define_pd_global(intx, InitialCodeCacheSize, 4*M ); define_pd_global(intx, ReservedCodeCacheSize, 64*M );
--- a/src/cpu/x86/vm/globals_x86.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/cpu/x86/vm/globals_x86.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -78,4 +78,53 @@ // GC Ergo Flags define_pd_global(intx, CMSYoungGenPerWorker, 64*M); // default max size of CMS young gen, per GC worker thread + +#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \ + \ + develop(bool, IEEEPrecision, true, \ + "Enables IEEE precision (for INTEL only)") \ + \ + product(intx, FenceInstruction, 0, \ + "(Unsafe,Unstable) Experimental") \ + \ + product(intx, ReadPrefetchInstr, 0, \ + "Prefetch instruction to prefetch ahead") \ + \ + product(bool, UseStoreImmI16, true, \ + "Use store immediate 16-bits value instruction on x86") \ + \ + product(intx, UseAVX, 99, \ + "Highest supported AVX instructions set on x86/x64") \ + \ + diagnostic(bool, UseIncDec, true, \ + "Use INC, DEC instructions on x86") \ + \ + product(bool, UseNewLongLShift, false, \ + "Use optimized bitwise shift left") \ + \ + product(bool, UseAddressNop, false, \ + "Use '0F 1F [addr]' NOP instructions on x86 cpus") \ + \ + product(bool, UseXmmLoadAndClearUpper, true, \ + "Load low part of XMM register and clear upper part") \ + \ + product(bool, UseXmmRegToRegMoveAll, false, \ + "Copy all XMM register bits when moving value between registers") \ + \ + product(bool, UseXmmI2D, false, \ + "Use SSE2 CVTDQ2PD instruction to convert Integer to Double") \ + \ + product(bool, UseXmmI2F, false, \ + "Use SSE2 CVTDQ2PS instruction to convert Integer to Float") \ + \ + product(bool, UseUnalignedLoadStores, false, \ + "Use SSE2 MOVDQU instruction for Arraycopy") \ + \ + /* assembler */ \ + product(bool, Use486InstrsOnly, false, \ + "Use 80486 Compliant instruction subset") \ + \ + product(bool, UseCountLeadingZerosInstruction, false, \ + "Use count leading zeros instruction") \ + #endif // CPU_X86_VM_GLOBALS_X86_HPP
--- a/src/cpu/x86/vm/x86.ad Fri Nov 09 13:32:53 2012 +0100 +++ b/src/cpu/x86/vm/x86.ad Fri Nov 09 13:35:26 2012 +0100 @@ -500,6 +500,24 @@ 0 /*bottom*/ }; +const bool Matcher::match_rule_supported(int opcode) { + if (!has_match_rule(opcode)) + return false; + + switch (opcode) { + case Op_PopCountI: + case Op_PopCountL: + if (!UsePopCountInstruction) + return false; + case Op_MulVI: + if ((UseSSE < 4) && (UseAVX < 1)) // only with SSE4_1 or AVX + return false; + break; + } + + return true; // Per default match rules are supported. +} + // Max vector size in bytes. 0 if not supported. const int Matcher::vector_width_in_bytes(BasicType bt) { assert(is_java_primitive(bt), "only primitive type vectors"); @@ -1439,8 +1457,9 @@ ins_cost(150); format %{ "vandps $dst, $src, [0x7fffffff]\t# abs float by sign masking" %} ins_encode %{ + bool vector256 = false; __ vandps($dst$$XMMRegister, $src$$XMMRegister, - ExternalAddress(float_signmask())); + ExternalAddress(float_signmask()), vector256); %} ins_pipe(pipe_slow); %} @@ -1464,8 +1483,9 @@ format %{ "vandpd $dst, $src, [0x7fffffffffffffff]\t" "# abs double by sign masking" %} ins_encode %{ + bool vector256 = false; __ vandpd($dst$$XMMRegister, $src$$XMMRegister, - ExternalAddress(double_signmask())); + ExternalAddress(double_signmask()), vector256); %} ins_pipe(pipe_slow); %} @@ -1487,8 +1507,9 @@ ins_cost(150); format %{ "vxorps $dst, $src, [0x80000000]\t# neg float by sign flipping" %} ins_encode %{ + bool vector256 = false; __ vxorps($dst$$XMMRegister, $src$$XMMRegister, - ExternalAddress(float_signflip())); + ExternalAddress(float_signflip()), vector256); %} ins_pipe(pipe_slow); %} @@ -1512,8 +1533,9 @@ format %{ "vxorpd $dst, $src, [0x8000000000000000]\t" "# neg double by sign flipping" %} ins_encode %{ + bool vector256 = false; __ vxorpd($dst$$XMMRegister, $src$$XMMRegister, - ExternalAddress(double_signflip())); + ExternalAddress(double_signflip()), vector256); %} ins_pipe(pipe_slow); %} @@ -2382,3 +2404,2416 @@ ins_pipe( fpu_reg_reg ); %} +// ====================VECTOR ARITHMETIC======================================= + +// --------------------------------- ADD -------------------------------------- + +// Bytes vector add +instruct vadd4B(vecS dst, vecS src) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (AddVB dst src)); + format %{ "paddb $dst,$src\t! add packed4B" %} + ins_encode %{ + __ paddb($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd4B_reg(vecS dst, vecS src1, vecS src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (AddVB src1 src2)); + format %{ "vpaddb $dst,$src1,$src2\t! add packed4B" %} + ins_encode %{ + bool vector256 = false; + __ vpaddb($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd8B(vecD dst, vecD src) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (AddVB dst src)); + format %{ "paddb $dst,$src\t! add packed8B" %} + ins_encode %{ + __ paddb($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd8B_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (AddVB src1 src2)); + format %{ "vpaddb $dst,$src1,$src2\t! add packed8B" %} + ins_encode %{ + bool vector256 = false; + __ vpaddb($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd16B(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 16); + match(Set dst (AddVB dst src)); + format %{ "paddb $dst,$src\t! add packed16B" %} + ins_encode %{ + __ paddb($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 16); + match(Set dst (AddVB src1 src2)); + format %{ "vpaddb $dst,$src1,$src2\t! add packed16B" %} + ins_encode %{ + bool vector256 = false; + __ vpaddb($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd16B_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 16); + match(Set dst (AddVB src (LoadVector mem))); + format %{ "vpaddb $dst,$src,$mem\t! add packed16B" %} + ins_encode %{ + bool vector256 = false; + __ vpaddb($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd32B_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 32); + match(Set dst (AddVB src1 src2)); + format %{ "vpaddb $dst,$src1,$src2\t! add packed32B" %} + ins_encode %{ + bool vector256 = true; + __ vpaddb($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd32B_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 32); + match(Set dst (AddVB src (LoadVector mem))); + format %{ "vpaddb $dst,$src,$mem\t! add packed32B" %} + ins_encode %{ + bool vector256 = true; + __ vpaddb($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Shorts/Chars vector add +instruct vadd2S(vecS dst, vecS src) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVS dst src)); + format %{ "paddw $dst,$src\t! add packed2S" %} + ins_encode %{ + __ paddw($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd2S_reg(vecS dst, vecS src1, vecS src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (AddVS src1 src2)); + format %{ "vpaddw $dst,$src1,$src2\t! add packed2S" %} + ins_encode %{ + bool vector256 = false; + __ vpaddw($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd4S(vecD dst, vecD src) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (AddVS dst src)); + format %{ "paddw $dst,$src\t! add packed4S" %} + ins_encode %{ + __ paddw($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd4S_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (AddVS src1 src2)); + format %{ "vpaddw $dst,$src1,$src2\t! add packed4S" %} + ins_encode %{ + bool vector256 = false; + __ vpaddw($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd8S(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (AddVS dst src)); + format %{ "paddw $dst,$src\t! add packed8S" %} + ins_encode %{ + __ paddw($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (AddVS src1 src2)); + format %{ "vpaddw $dst,$src1,$src2\t! add packed8S" %} + ins_encode %{ + bool vector256 = false; + __ vpaddw($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd8S_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (AddVS src (LoadVector mem))); + format %{ "vpaddw $dst,$src,$mem\t! add packed8S" %} + ins_encode %{ + bool vector256 = false; + __ vpaddw($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd16S_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 16); + match(Set dst (AddVS src1 src2)); + format %{ "vpaddw $dst,$src1,$src2\t! add packed16S" %} + ins_encode %{ + bool vector256 = true; + __ vpaddw($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd16S_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 16); + match(Set dst (AddVS src (LoadVector mem))); + format %{ "vpaddw $dst,$src,$mem\t! add packed16S" %} + ins_encode %{ + bool vector256 = true; + __ vpaddw($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Integers vector add +instruct vadd2I(vecD dst, vecD src) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVI dst src)); + format %{ "paddd $dst,$src\t! add packed2I" %} + ins_encode %{ + __ paddd($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd2I_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (AddVI src1 src2)); + format %{ "vpaddd $dst,$src1,$src2\t! add packed2I" %} + ins_encode %{ + bool vector256 = false; + __ vpaddd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd4I(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (AddVI dst src)); + format %{ "paddd $dst,$src\t! add packed4I" %} + ins_encode %{ + __ paddd($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (AddVI src1 src2)); + format %{ "vpaddd $dst,$src1,$src2\t! add packed4I" %} + ins_encode %{ + bool vector256 = false; + __ vpaddd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd4I_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (AddVI src (LoadVector mem))); + format %{ "vpaddd $dst,$src,$mem\t! add packed4I" %} + ins_encode %{ + bool vector256 = false; + __ vpaddd($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd8I_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 8); + match(Set dst (AddVI src1 src2)); + format %{ "vpaddd $dst,$src1,$src2\t! add packed8I" %} + ins_encode %{ + bool vector256 = true; + __ vpaddd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd8I_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 8); + match(Set dst (AddVI src (LoadVector mem))); + format %{ "vpaddd $dst,$src,$mem\t! add packed8I" %} + ins_encode %{ + bool vector256 = true; + __ vpaddd($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Longs vector add +instruct vadd2L(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVL dst src)); + format %{ "paddq $dst,$src\t! add packed2L" %} + ins_encode %{ + __ paddq($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (AddVL src1 src2)); + format %{ "vpaddq $dst,$src1,$src2\t! add packed2L" %} + ins_encode %{ + bool vector256 = false; + __ vpaddq($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd2L_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (AddVL src (LoadVector mem))); + format %{ "vpaddq $dst,$src,$mem\t! add packed2L" %} + ins_encode %{ + bool vector256 = false; + __ vpaddq($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd4L_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 4); + match(Set dst (AddVL src1 src2)); + format %{ "vpaddq $dst,$src1,$src2\t! add packed4L" %} + ins_encode %{ + bool vector256 = true; + __ vpaddq($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd4L_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 4); + match(Set dst (AddVL src (LoadVector mem))); + format %{ "vpaddq $dst,$src,$mem\t! add packed4L" %} + ins_encode %{ + bool vector256 = true; + __ vpaddq($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Floats vector add +instruct vadd2F(vecD dst, vecD src) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVF dst src)); + format %{ "addps $dst,$src\t! add packed2F" %} + ins_encode %{ + __ addps($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd2F_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (AddVF src1 src2)); + format %{ "vaddps $dst,$src1,$src2\t! add packed2F" %} + ins_encode %{ + bool vector256 = false; + __ vaddps($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd4F(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (AddVF dst src)); + format %{ "addps $dst,$src\t! add packed4F" %} + ins_encode %{ + __ addps($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd4F_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (AddVF src1 src2)); + format %{ "vaddps $dst,$src1,$src2\t! add packed4F" %} + ins_encode %{ + bool vector256 = false; + __ vaddps($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd4F_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (AddVF src (LoadVector mem))); + format %{ "vaddps $dst,$src,$mem\t! add packed4F" %} + ins_encode %{ + bool vector256 = false; + __ vaddps($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd8F_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (AddVF src1 src2)); + format %{ "vaddps $dst,$src1,$src2\t! add packed8F" %} + ins_encode %{ + bool vector256 = true; + __ vaddps($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd8F_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (AddVF src (LoadVector mem))); + format %{ "vaddps $dst,$src,$mem\t! add packed8F" %} + ins_encode %{ + bool vector256 = true; + __ vaddps($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Doubles vector add +instruct vadd2D(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVD dst src)); + format %{ "addpd $dst,$src\t! add packed2D" %} + ins_encode %{ + __ addpd($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd2D_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (AddVD src1 src2)); + format %{ "vaddpd $dst,$src1,$src2\t! add packed2D" %} + ins_encode %{ + bool vector256 = false; + __ vaddpd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd2D_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (AddVD src (LoadVector mem))); + format %{ "vaddpd $dst,$src,$mem\t! add packed2D" %} + ins_encode %{ + bool vector256 = false; + __ vaddpd($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd4D_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (AddVD src1 src2)); + format %{ "vaddpd $dst,$src1,$src2\t! add packed4D" %} + ins_encode %{ + bool vector256 = true; + __ vaddpd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vadd4D_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (AddVD src (LoadVector mem))); + format %{ "vaddpd $dst,$src,$mem\t! add packed4D" %} + ins_encode %{ + bool vector256 = true; + __ vaddpd($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// --------------------------------- SUB -------------------------------------- + +// Bytes vector sub +instruct vsub4B(vecS dst, vecS src) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (SubVB dst src)); + format %{ "psubb $dst,$src\t! sub packed4B" %} + ins_encode %{ + __ psubb($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub4B_reg(vecS dst, vecS src1, vecS src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (SubVB src1 src2)); + format %{ "vpsubb $dst,$src1,$src2\t! sub packed4B" %} + ins_encode %{ + bool vector256 = false; + __ vpsubb($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub8B(vecD dst, vecD src) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (SubVB dst src)); + format %{ "psubb $dst,$src\t! sub packed8B" %} + ins_encode %{ + __ psubb($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub8B_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (SubVB src1 src2)); + format %{ "vpsubb $dst,$src1,$src2\t! sub packed8B" %} + ins_encode %{ + bool vector256 = false; + __ vpsubb($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub16B(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 16); + match(Set dst (SubVB dst src)); + format %{ "psubb $dst,$src\t! sub packed16B" %} + ins_encode %{ + __ psubb($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 16); + match(Set dst (SubVB src1 src2)); + format %{ "vpsubb $dst,$src1,$src2\t! sub packed16B" %} + ins_encode %{ + bool vector256 = false; + __ vpsubb($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub16B_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 16); + match(Set dst (SubVB src (LoadVector mem))); + format %{ "vpsubb $dst,$src,$mem\t! sub packed16B" %} + ins_encode %{ + bool vector256 = false; + __ vpsubb($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub32B_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 32); + match(Set dst (SubVB src1 src2)); + format %{ "vpsubb $dst,$src1,$src2\t! sub packed32B" %} + ins_encode %{ + bool vector256 = true; + __ vpsubb($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub32B_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 32); + match(Set dst (SubVB src (LoadVector mem))); + format %{ "vpsubb $dst,$src,$mem\t! sub packed32B" %} + ins_encode %{ + bool vector256 = true; + __ vpsubb($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Shorts/Chars vector sub +instruct vsub2S(vecS dst, vecS src) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (SubVS dst src)); + format %{ "psubw $dst,$src\t! sub packed2S" %} + ins_encode %{ + __ psubw($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub2S_reg(vecS dst, vecS src1, vecS src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (SubVS src1 src2)); + format %{ "vpsubw $dst,$src1,$src2\t! sub packed2S" %} + ins_encode %{ + bool vector256 = false; + __ vpsubw($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub4S(vecD dst, vecD src) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (SubVS dst src)); + format %{ "psubw $dst,$src\t! sub packed4S" %} + ins_encode %{ + __ psubw($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub4S_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (SubVS src1 src2)); + format %{ "vpsubw $dst,$src1,$src2\t! sub packed4S" %} + ins_encode %{ + bool vector256 = false; + __ vpsubw($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub8S(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (SubVS dst src)); + format %{ "psubw $dst,$src\t! sub packed8S" %} + ins_encode %{ + __ psubw($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub8S_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (SubVS src1 src2)); + format %{ "vpsubw $dst,$src1,$src2\t! sub packed8S" %} + ins_encode %{ + bool vector256 = false; + __ vpsubw($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub8S_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (SubVS src (LoadVector mem))); + format %{ "vpsubw $dst,$src,$mem\t! sub packed8S" %} + ins_encode %{ + bool vector256 = false; + __ vpsubw($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub16S_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 16); + match(Set dst (SubVS src1 src2)); + format %{ "vpsubw $dst,$src1,$src2\t! sub packed16S" %} + ins_encode %{ + bool vector256 = true; + __ vpsubw($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub16S_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 16); + match(Set dst (SubVS src (LoadVector mem))); + format %{ "vpsubw $dst,$src,$mem\t! sub packed16S" %} + ins_encode %{ + bool vector256 = true; + __ vpsubw($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Integers vector sub +instruct vsub2I(vecD dst, vecD src) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (SubVI dst src)); + format %{ "psubd $dst,$src\t! sub packed2I" %} + ins_encode %{ + __ psubd($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub2I_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (SubVI src1 src2)); + format %{ "vpsubd $dst,$src1,$src2\t! sub packed2I" %} + ins_encode %{ + bool vector256 = false; + __ vpsubd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub4I(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (SubVI dst src)); + format %{ "psubd $dst,$src\t! sub packed4I" %} + ins_encode %{ + __ psubd($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (SubVI src1 src2)); + format %{ "vpsubd $dst,$src1,$src2\t! sub packed4I" %} + ins_encode %{ + bool vector256 = false; + __ vpsubd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub4I_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (SubVI src (LoadVector mem))); + format %{ "vpsubd $dst,$src,$mem\t! sub packed4I" %} + ins_encode %{ + bool vector256 = false; + __ vpsubd($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub8I_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 8); + match(Set dst (SubVI src1 src2)); + format %{ "vpsubd $dst,$src1,$src2\t! sub packed8I" %} + ins_encode %{ + bool vector256 = true; + __ vpsubd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub8I_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 8); + match(Set dst (SubVI src (LoadVector mem))); + format %{ "vpsubd $dst,$src,$mem\t! sub packed8I" %} + ins_encode %{ + bool vector256 = true; + __ vpsubd($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Longs vector sub +instruct vsub2L(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (SubVL dst src)); + format %{ "psubq $dst,$src\t! sub packed2L" %} + ins_encode %{ + __ psubq($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (SubVL src1 src2)); + format %{ "vpsubq $dst,$src1,$src2\t! sub packed2L" %} + ins_encode %{ + bool vector256 = false; + __ vpsubq($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub2L_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (SubVL src (LoadVector mem))); + format %{ "vpsubq $dst,$src,$mem\t! sub packed2L" %} + ins_encode %{ + bool vector256 = false; + __ vpsubq($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub4L_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 4); + match(Set dst (SubVL src1 src2)); + format %{ "vpsubq $dst,$src1,$src2\t! sub packed4L" %} + ins_encode %{ + bool vector256 = true; + __ vpsubq($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub4L_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 4); + match(Set dst (SubVL src (LoadVector mem))); + format %{ "vpsubq $dst,$src,$mem\t! sub packed4L" %} + ins_encode %{ + bool vector256 = true; + __ vpsubq($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Floats vector sub +instruct vsub2F(vecD dst, vecD src) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (SubVF dst src)); + format %{ "subps $dst,$src\t! sub packed2F" %} + ins_encode %{ + __ subps($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub2F_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (SubVF src1 src2)); + format %{ "vsubps $dst,$src1,$src2\t! sub packed2F" %} + ins_encode %{ + bool vector256 = false; + __ vsubps($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub4F(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (SubVF dst src)); + format %{ "subps $dst,$src\t! sub packed4F" %} + ins_encode %{ + __ subps($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (SubVF src1 src2)); + format %{ "vsubps $dst,$src1,$src2\t! sub packed4F" %} + ins_encode %{ + bool vector256 = false; + __ vsubps($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub4F_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (SubVF src (LoadVector mem))); + format %{ "vsubps $dst,$src,$mem\t! sub packed4F" %} + ins_encode %{ + bool vector256 = false; + __ vsubps($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub8F_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (SubVF src1 src2)); + format %{ "vsubps $dst,$src1,$src2\t! sub packed8F" %} + ins_encode %{ + bool vector256 = true; + __ vsubps($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub8F_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (SubVF src (LoadVector mem))); + format %{ "vsubps $dst,$src,$mem\t! sub packed8F" %} + ins_encode %{ + bool vector256 = true; + __ vsubps($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Doubles vector sub +instruct vsub2D(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (SubVD dst src)); + format %{ "subpd $dst,$src\t! sub packed2D" %} + ins_encode %{ + __ subpd($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub2D_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (SubVD src1 src2)); + format %{ "vsubpd $dst,$src1,$src2\t! sub packed2D" %} + ins_encode %{ + bool vector256 = false; + __ vsubpd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub2D_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (SubVD src (LoadVector mem))); + format %{ "vsubpd $dst,$src,$mem\t! sub packed2D" %} + ins_encode %{ + bool vector256 = false; + __ vsubpd($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub4D_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (SubVD src1 src2)); + format %{ "vsubpd $dst,$src1,$src2\t! sub packed4D" %} + ins_encode %{ + bool vector256 = true; + __ vsubpd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsub4D_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (SubVD src (LoadVector mem))); + format %{ "vsubpd $dst,$src,$mem\t! sub packed4D" %} + ins_encode %{ + bool vector256 = true; + __ vsubpd($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// --------------------------------- MUL -------------------------------------- + +// Shorts/Chars vector mul +instruct vmul2S(vecS dst, vecS src) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (MulVS dst src)); + format %{ "pmullw $dst,$src\t! mul packed2S" %} + ins_encode %{ + __ pmullw($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul2S_reg(vecS dst, vecS src1, vecS src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (MulVS src1 src2)); + format %{ "vpmullw $dst,$src1,$src2\t! mul packed2S" %} + ins_encode %{ + bool vector256 = false; + __ vpmullw($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul4S(vecD dst, vecD src) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (MulVS dst src)); + format %{ "pmullw $dst,$src\t! mul packed4S" %} + ins_encode %{ + __ pmullw($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul4S_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (MulVS src1 src2)); + format %{ "vpmullw $dst,$src1,$src2\t! mul packed4S" %} + ins_encode %{ + bool vector256 = false; + __ vpmullw($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul8S(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (MulVS dst src)); + format %{ "pmullw $dst,$src\t! mul packed8S" %} + ins_encode %{ + __ pmullw($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (MulVS src1 src2)); + format %{ "vpmullw $dst,$src1,$src2\t! mul packed8S" %} + ins_encode %{ + bool vector256 = false; + __ vpmullw($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul8S_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (MulVS src (LoadVector mem))); + format %{ "vpmullw $dst,$src,$mem\t! mul packed8S" %} + ins_encode %{ + bool vector256 = false; + __ vpmullw($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul16S_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 16); + match(Set dst (MulVS src1 src2)); + format %{ "vpmullw $dst,$src1,$src2\t! mul packed16S" %} + ins_encode %{ + bool vector256 = true; + __ vpmullw($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul16S_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 16); + match(Set dst (MulVS src (LoadVector mem))); + format %{ "vpmullw $dst,$src,$mem\t! mul packed16S" %} + ins_encode %{ + bool vector256 = true; + __ vpmullw($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Integers vector mul (sse4_1) +instruct vmul2I(vecD dst, vecD src) %{ + predicate(UseSSE > 3 && n->as_Vector()->length() == 2); + match(Set dst (MulVI dst src)); + format %{ "pmulld $dst,$src\t! mul packed2I" %} + ins_encode %{ + __ pmulld($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul2I_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (MulVI src1 src2)); + format %{ "vpmulld $dst,$src1,$src2\t! mul packed2I" %} + ins_encode %{ + bool vector256 = false; + __ vpmulld($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul4I(vecX dst, vecX src) %{ + predicate(UseSSE > 3 && n->as_Vector()->length() == 4); + match(Set dst (MulVI dst src)); + format %{ "pmulld $dst,$src\t! mul packed4I" %} + ins_encode %{ + __ pmulld($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (MulVI src1 src2)); + format %{ "vpmulld $dst,$src1,$src2\t! mul packed4I" %} + ins_encode %{ + bool vector256 = false; + __ vpmulld($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul4I_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (MulVI src (LoadVector mem))); + format %{ "vpmulld $dst,$src,$mem\t! mul packed4I" %} + ins_encode %{ + bool vector256 = false; + __ vpmulld($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul8I_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 8); + match(Set dst (MulVI src1 src2)); + format %{ "vpmulld $dst,$src1,$src2\t! mul packed8I" %} + ins_encode %{ + bool vector256 = true; + __ vpmulld($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul8I_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 8); + match(Set dst (MulVI src (LoadVector mem))); + format %{ "vpmulld $dst,$src,$mem\t! mul packed8I" %} + ins_encode %{ + bool vector256 = true; + __ vpmulld($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Floats vector mul +instruct vmul2F(vecD dst, vecD src) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (MulVF dst src)); + format %{ "mulps $dst,$src\t! mul packed2F" %} + ins_encode %{ + __ mulps($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul2F_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (MulVF src1 src2)); + format %{ "vmulps $dst,$src1,$src2\t! mul packed2F" %} + ins_encode %{ + bool vector256 = false; + __ vmulps($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul4F(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (MulVF dst src)); + format %{ "mulps $dst,$src\t! mul packed4F" %} + ins_encode %{ + __ mulps($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (MulVF src1 src2)); + format %{ "vmulps $dst,$src1,$src2\t! mul packed4F" %} + ins_encode %{ + bool vector256 = false; + __ vmulps($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul4F_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (MulVF src (LoadVector mem))); + format %{ "vmulps $dst,$src,$mem\t! mul packed4F" %} + ins_encode %{ + bool vector256 = false; + __ vmulps($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul8F_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (MulVF src1 src2)); + format %{ "vmulps $dst,$src1,$src2\t! mul packed8F" %} + ins_encode %{ + bool vector256 = true; + __ vmulps($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul8F_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (MulVF src (LoadVector mem))); + format %{ "vmulps $dst,$src,$mem\t! mul packed8F" %} + ins_encode %{ + bool vector256 = true; + __ vmulps($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Doubles vector mul +instruct vmul2D(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (MulVD dst src)); + format %{ "mulpd $dst,$src\t! mul packed2D" %} + ins_encode %{ + __ mulpd($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul2D_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (MulVD src1 src2)); + format %{ "vmulpd $dst,$src1,$src2\t! mul packed2D" %} + ins_encode %{ + bool vector256 = false; + __ vmulpd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul2D_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (MulVD src (LoadVector mem))); + format %{ "vmulpd $dst,$src,$mem\t! mul packed2D" %} + ins_encode %{ + bool vector256 = false; + __ vmulpd($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul4D_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (MulVD src1 src2)); + format %{ "vmulpd $dst,$src1,$src2\t! mul packed4D" %} + ins_encode %{ + bool vector256 = true; + __ vmulpd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul4D_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (MulVD src (LoadVector mem))); + format %{ "vmulpd $dst,$src,$mem\t! mul packed4D" %} + ins_encode %{ + bool vector256 = true; + __ vmulpd($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// --------------------------------- DIV -------------------------------------- + +// Floats vector div +instruct vdiv2F(vecD dst, vecD src) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (DivVF dst src)); + format %{ "divps $dst,$src\t! div packed2F" %} + ins_encode %{ + __ divps($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vdiv2F_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (DivVF src1 src2)); + format %{ "vdivps $dst,$src1,$src2\t! div packed2F" %} + ins_encode %{ + bool vector256 = false; + __ vdivps($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vdiv4F(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (DivVF dst src)); + format %{ "divps $dst,$src\t! div packed4F" %} + ins_encode %{ + __ divps($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vdiv4F_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (DivVF src1 src2)); + format %{ "vdivps $dst,$src1,$src2\t! div packed4F" %} + ins_encode %{ + bool vector256 = false; + __ vdivps($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vdiv4F_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (DivVF src (LoadVector mem))); + format %{ "vdivps $dst,$src,$mem\t! div packed4F" %} + ins_encode %{ + bool vector256 = false; + __ vdivps($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vdiv8F_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (DivVF src1 src2)); + format %{ "vdivps $dst,$src1,$src2\t! div packed8F" %} + ins_encode %{ + bool vector256 = true; + __ vdivps($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vdiv8F_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (DivVF src (LoadVector mem))); + format %{ "vdivps $dst,$src,$mem\t! div packed8F" %} + ins_encode %{ + bool vector256 = true; + __ vdivps($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Doubles vector div +instruct vdiv2D(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (DivVD dst src)); + format %{ "divpd $dst,$src\t! div packed2D" %} + ins_encode %{ + __ divpd($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vdiv2D_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (DivVD src1 src2)); + format %{ "vdivpd $dst,$src1,$src2\t! div packed2D" %} + ins_encode %{ + bool vector256 = false; + __ vdivpd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vdiv2D_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (DivVD src (LoadVector mem))); + format %{ "vdivpd $dst,$src,$mem\t! div packed2D" %} + ins_encode %{ + bool vector256 = false; + __ vdivpd($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vdiv4D_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (DivVD src1 src2)); + format %{ "vdivpd $dst,$src1,$src2\t! div packed4D" %} + ins_encode %{ + bool vector256 = true; + __ vdivpd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vdiv4D_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (DivVD src (LoadVector mem))); + format %{ "vdivpd $dst,$src,$mem\t! div packed4D" %} + ins_encode %{ + bool vector256 = true; + __ vdivpd($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// ------------------------------ LeftShift ----------------------------------- + +// Shorts/Chars vector left shift +instruct vsll2S(vecS dst, regF shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVS dst shift)); + format %{ "psllw $dst,$shift\t! left shift packed2S" %} + ins_encode %{ + __ psllw($dst$$XMMRegister, $shift$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll2S_imm(vecS dst, immI8 shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVS dst shift)); + format %{ "psllw $dst,$shift\t! left shift packed2S" %} + ins_encode %{ + __ psllw($dst$$XMMRegister, (int)$shift$$constant); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll2S_reg(vecS dst, vecS src, regF shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (LShiftVS src shift)); + format %{ "vpsllw $dst,$src,$shift\t! left shift packed2S" %} + ins_encode %{ + bool vector256 = false; + __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll2S_reg_imm(vecS dst, vecS src, immI8 shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (LShiftVS src shift)); + format %{ "vpsllw $dst,$src,$shift\t! left shift packed2S" %} + ins_encode %{ + bool vector256 = false; + __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll4S(vecD dst, regF shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (LShiftVS dst shift)); + format %{ "psllw $dst,$shift\t! left shift packed4S" %} + ins_encode %{ + __ psllw($dst$$XMMRegister, $shift$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll4S_imm(vecD dst, immI8 shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (LShiftVS dst shift)); + format %{ "psllw $dst,$shift\t! left shift packed4S" %} + ins_encode %{ + __ psllw($dst$$XMMRegister, (int)$shift$$constant); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll4S_reg(vecD dst, vecD src, regF shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (LShiftVS src shift)); + format %{ "vpsllw $dst,$src,$shift\t! left shift packed4S" %} + ins_encode %{ + bool vector256 = false; + __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll4S_reg_imm(vecD dst, vecD src, immI8 shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (LShiftVS src shift)); + format %{ "vpsllw $dst,$src,$shift\t! left shift packed4S" %} + ins_encode %{ + bool vector256 = false; + __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll8S(vecX dst, regF shift) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (LShiftVS dst shift)); + format %{ "psllw $dst,$shift\t! left shift packed8S" %} + ins_encode %{ + __ psllw($dst$$XMMRegister, $shift$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll8S_imm(vecX dst, immI8 shift) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (LShiftVS dst shift)); + format %{ "psllw $dst,$shift\t! left shift packed8S" %} + ins_encode %{ + __ psllw($dst$$XMMRegister, (int)$shift$$constant); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll8S_reg(vecX dst, vecX src, regF shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (LShiftVS src shift)); + format %{ "vpsllw $dst,$src,$shift\t! left shift packed8S" %} + ins_encode %{ + bool vector256 = false; + __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll8S_reg_imm(vecX dst, vecX src, immI8 shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (LShiftVS src shift)); + format %{ "vpsllw $dst,$src,$shift\t! left shift packed8S" %} + ins_encode %{ + bool vector256 = false; + __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll16S_reg(vecY dst, vecY src, regF shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 16); + match(Set dst (LShiftVS src shift)); + format %{ "vpsllw $dst,$src,$shift\t! left shift packed16S" %} + ins_encode %{ + bool vector256 = true; + __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll16S_reg_imm(vecY dst, vecY src, immI8 shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 16); + match(Set dst (LShiftVS src shift)); + format %{ "vpsllw $dst,$src,$shift\t! left shift packed16S" %} + ins_encode %{ + bool vector256 = true; + __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Integers vector left shift +instruct vsll2I(vecD dst, regF shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVI dst shift)); + format %{ "pslld $dst,$shift\t! left shift packed2I" %} + ins_encode %{ + __ pslld($dst$$XMMRegister, $shift$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll2I_imm(vecD dst, immI8 shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVI dst shift)); + format %{ "pslld $dst,$shift\t! left shift packed2I" %} + ins_encode %{ + __ pslld($dst$$XMMRegister, (int)$shift$$constant); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll2I_reg(vecD dst, vecD src, regF shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (LShiftVI src shift)); + format %{ "vpslld $dst,$src,$shift\t! left shift packed2I" %} + ins_encode %{ + bool vector256 = false; + __ vpslld($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll2I_reg_imm(vecD dst, vecD src, immI8 shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (LShiftVI src shift)); + format %{ "vpslld $dst,$src,$shift\t! left shift packed2I" %} + ins_encode %{ + bool vector256 = false; + __ vpslld($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll4I(vecX dst, regF shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (LShiftVI dst shift)); + format %{ "pslld $dst,$shift\t! left shift packed4I" %} + ins_encode %{ + __ pslld($dst$$XMMRegister, $shift$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll4I_imm(vecX dst, immI8 shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (LShiftVI dst shift)); + format %{ "pslld $dst,$shift\t! left shift packed4I" %} + ins_encode %{ + __ pslld($dst$$XMMRegister, (int)$shift$$constant); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll4I_reg(vecX dst, vecX src, regF shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (LShiftVI src shift)); + format %{ "vpslld $dst,$src,$shift\t! left shift packed4I" %} + ins_encode %{ + bool vector256 = false; + __ vpslld($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll4I_reg_imm(vecX dst, vecX src, immI8 shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (LShiftVI src shift)); + format %{ "vpslld $dst,$src,$shift\t! left shift packed4I" %} + ins_encode %{ + bool vector256 = false; + __ vpslld($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll8I_reg(vecY dst, vecY src, regF shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 8); + match(Set dst (LShiftVI src shift)); + format %{ "vpslld $dst,$src,$shift\t! left shift packed8I" %} + ins_encode %{ + bool vector256 = true; + __ vpslld($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll8I_reg_imm(vecY dst, vecY src, immI8 shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 8); + match(Set dst (LShiftVI src shift)); + format %{ "vpslld $dst,$src,$shift\t! left shift packed8I" %} + ins_encode %{ + bool vector256 = true; + __ vpslld($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Longs vector left shift +instruct vsll2L(vecX dst, regF shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVL dst shift)); + format %{ "psllq $dst,$shift\t! left shift packed2L" %} + ins_encode %{ + __ psllq($dst$$XMMRegister, $shift$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll2L_imm(vecX dst, immI8 shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVL dst shift)); + format %{ "psllq $dst,$shift\t! left shift packed2L" %} + ins_encode %{ + __ psllq($dst$$XMMRegister, (int)$shift$$constant); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll2L_reg(vecX dst, vecX src, regF shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (LShiftVL src shift)); + format %{ "vpsllq $dst,$src,$shift\t! left shift packed2L" %} + ins_encode %{ + bool vector256 = false; + __ vpsllq($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll2L_reg_imm(vecX dst, vecX src, immI8 shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (LShiftVL src shift)); + format %{ "vpsllq $dst,$src,$shift\t! left shift packed2L" %} + ins_encode %{ + bool vector256 = false; + __ vpsllq($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll4L_reg(vecY dst, vecY src, regF shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 4); + match(Set dst (LShiftVL src shift)); + format %{ "vpsllq $dst,$src,$shift\t! left shift packed4L" %} + ins_encode %{ + bool vector256 = true; + __ vpsllq($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsll4L_reg_imm(vecY dst, vecY src, immI8 shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 4); + match(Set dst (LShiftVL src shift)); + format %{ "vpsllq $dst,$src,$shift\t! left shift packed4L" %} + ins_encode %{ + bool vector256 = true; + __ vpsllq($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// ----------------------- LogicalRightShift ----------------------------------- + +// Shorts/Chars vector logical right shift produces incorrect Java result +// for negative data because java code convert short value into int with +// sign extension before a shift. + +// Integers vector logical right shift +instruct vsrl2I(vecD dst, regF shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (URShiftVI dst shift)); + format %{ "psrld $dst,$shift\t! logical right shift packed2I" %} + ins_encode %{ + __ psrld($dst$$XMMRegister, $shift$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsrl2I_imm(vecD dst, immI8 shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (URShiftVI dst shift)); + format %{ "psrld $dst,$shift\t! logical right shift packed2I" %} + ins_encode %{ + __ psrld($dst$$XMMRegister, (int)$shift$$constant); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsrl2I_reg(vecD dst, vecD src, regF shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (URShiftVI src shift)); + format %{ "vpsrld $dst,$src,$shift\t! logical right shift packed2I" %} + ins_encode %{ + bool vector256 = false; + __ vpsrld($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsrl2I_reg_imm(vecD dst, vecD src, immI8 shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (URShiftVI src shift)); + format %{ "vpsrld $dst,$src,$shift\t! logical right shift packed2I" %} + ins_encode %{ + bool vector256 = false; + __ vpsrld($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsrl4I(vecX dst, regF shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (URShiftVI dst shift)); + format %{ "psrld $dst,$shift\t! logical right shift packed4I" %} + ins_encode %{ + __ psrld($dst$$XMMRegister, $shift$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsrl4I_imm(vecX dst, immI8 shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (URShiftVI dst shift)); + format %{ "psrld $dst,$shift\t! logical right shift packed4I" %} + ins_encode %{ + __ psrld($dst$$XMMRegister, (int)$shift$$constant); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsrl4I_reg(vecX dst, vecX src, regF shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (URShiftVI src shift)); + format %{ "vpsrld $dst,$src,$shift\t! logical right shift packed4I" %} + ins_encode %{ + bool vector256 = false; + __ vpsrld($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsrl4I_reg_imm(vecX dst, vecX src, immI8 shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (URShiftVI src shift)); + format %{ "vpsrld $dst,$src,$shift\t! logical right shift packed4I" %} + ins_encode %{ + bool vector256 = false; + __ vpsrld($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsrl8I_reg(vecY dst, vecY src, regF shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 8); + match(Set dst (URShiftVI src shift)); + format %{ "vpsrld $dst,$src,$shift\t! logical right shift packed8I" %} + ins_encode %{ + bool vector256 = true; + __ vpsrld($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsrl8I_reg_imm(vecY dst, vecY src, immI8 shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 8); + match(Set dst (URShiftVI src shift)); + format %{ "vpsrld $dst,$src,$shift\t! logical right shift packed8I" %} + ins_encode %{ + bool vector256 = true; + __ vpsrld($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Longs vector logical right shift +instruct vsrl2L(vecX dst, regF shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (URShiftVL dst shift)); + format %{ "psrlq $dst,$shift\t! logical right shift packed2L" %} + ins_encode %{ + __ psrlq($dst$$XMMRegister, $shift$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsrl2L_imm(vecX dst, immI8 shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (URShiftVL dst shift)); + format %{ "psrlq $dst,$shift\t! logical right shift packed2L" %} + ins_encode %{ + __ psrlq($dst$$XMMRegister, (int)$shift$$constant); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsrl2L_reg(vecX dst, vecX src, regF shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (URShiftVL src shift)); + format %{ "vpsrlq $dst,$src,$shift\t! logical right shift packed2L" %} + ins_encode %{ + bool vector256 = false; + __ vpsrlq($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsrl2L_reg_imm(vecX dst, vecX src, immI8 shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (URShiftVL src shift)); + format %{ "vpsrlq $dst,$src,$shift\t! logical right shift packed2L" %} + ins_encode %{ + bool vector256 = false; + __ vpsrlq($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsrl4L_reg(vecY dst, vecY src, regF shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 4); + match(Set dst (URShiftVL src shift)); + format %{ "vpsrlq $dst,$src,$shift\t! logical right shift packed4L" %} + ins_encode %{ + bool vector256 = true; + __ vpsrlq($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsrl4L_reg_imm(vecY dst, vecY src, immI8 shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 4); + match(Set dst (URShiftVL src shift)); + format %{ "vpsrlq $dst,$src,$shift\t! logical right shift packed4L" %} + ins_encode %{ + bool vector256 = true; + __ vpsrlq($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// ------------------- ArithmeticRightShift ----------------------------------- + +// Shorts/Chars vector arithmetic right shift +instruct vsra2S(vecS dst, regF shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (RShiftVS dst shift)); + format %{ "psraw $dst,$shift\t! arithmetic right shift packed2S" %} + ins_encode %{ + __ psraw($dst$$XMMRegister, $shift$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra2S_imm(vecS dst, immI8 shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (RShiftVS dst shift)); + format %{ "psraw $dst,$shift\t! arithmetic right shift packed2S" %} + ins_encode %{ + __ psraw($dst$$XMMRegister, (int)$shift$$constant); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra2S_reg(vecS dst, vecS src, regF shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (RShiftVS src shift)); + format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed2S" %} + ins_encode %{ + bool vector256 = false; + __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra2S_reg_imm(vecS dst, vecS src, immI8 shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (RShiftVS src shift)); + format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed2S" %} + ins_encode %{ + bool vector256 = false; + __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra4S(vecD dst, regF shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (RShiftVS dst shift)); + format %{ "psraw $dst,$shift\t! arithmetic right shift packed4S" %} + ins_encode %{ + __ psraw($dst$$XMMRegister, $shift$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra4S_imm(vecD dst, immI8 shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (RShiftVS dst shift)); + format %{ "psraw $dst,$shift\t! arithmetic right shift packed4S" %} + ins_encode %{ + __ psraw($dst$$XMMRegister, (int)$shift$$constant); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra4S_reg(vecD dst, vecD src, regF shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (RShiftVS src shift)); + format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed4S" %} + ins_encode %{ + bool vector256 = false; + __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra4S_reg_imm(vecD dst, vecD src, immI8 shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (RShiftVS src shift)); + format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed4S" %} + ins_encode %{ + bool vector256 = false; + __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra8S(vecX dst, regF shift) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (RShiftVS dst shift)); + format %{ "psraw $dst,$shift\t! arithmetic right shift packed8S" %} + ins_encode %{ + __ psraw($dst$$XMMRegister, $shift$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra8S_imm(vecX dst, immI8 shift) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (RShiftVS dst shift)); + format %{ "psraw $dst,$shift\t! arithmetic right shift packed8S" %} + ins_encode %{ + __ psraw($dst$$XMMRegister, (int)$shift$$constant); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra8S_reg(vecX dst, vecX src, regF shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (RShiftVS src shift)); + format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed8S" %} + ins_encode %{ + bool vector256 = false; + __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra8S_reg_imm(vecX dst, vecX src, immI8 shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (RShiftVS src shift)); + format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed8S" %} + ins_encode %{ + bool vector256 = false; + __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra16S_reg(vecY dst, vecY src, regF shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 16); + match(Set dst (RShiftVS src shift)); + format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed16S" %} + ins_encode %{ + bool vector256 = true; + __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra16S_reg_imm(vecY dst, vecY src, immI8 shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 16); + match(Set dst (RShiftVS src shift)); + format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed16S" %} + ins_encode %{ + bool vector256 = true; + __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// Integers vector arithmetic right shift +instruct vsra2I(vecD dst, regF shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (RShiftVI dst shift)); + format %{ "psrad $dst,$shift\t! arithmetic right shift packed2I" %} + ins_encode %{ + __ psrad($dst$$XMMRegister, $shift$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra2I_imm(vecD dst, immI8 shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (RShiftVI dst shift)); + format %{ "psrad $dst,$shift\t! arithmetic right shift packed2I" %} + ins_encode %{ + __ psrad($dst$$XMMRegister, (int)$shift$$constant); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra2I_reg(vecD dst, vecD src, regF shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (RShiftVI src shift)); + format %{ "vpsrad $dst,$src,$shift\t! arithmetic right shift packed2I" %} + ins_encode %{ + bool vector256 = false; + __ vpsrad($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra2I_reg_imm(vecD dst, vecD src, immI8 shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + match(Set dst (RShiftVI src shift)); + format %{ "vpsrad $dst,$src,$shift\t! arithmetic right shift packed2I" %} + ins_encode %{ + bool vector256 = false; + __ vpsrad($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra4I(vecX dst, regF shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (RShiftVI dst shift)); + format %{ "psrad $dst,$shift\t! arithmetic right shift packed4I" %} + ins_encode %{ + __ psrad($dst$$XMMRegister, $shift$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra4I_imm(vecX dst, immI8 shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (RShiftVI dst shift)); + format %{ "psrad $dst,$shift\t! arithmetic right shift packed4I" %} + ins_encode %{ + __ psrad($dst$$XMMRegister, (int)$shift$$constant); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra4I_reg(vecX dst, vecX src, regF shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (RShiftVI src shift)); + format %{ "vpsrad $dst,$src,$shift\t! arithmetic right shift packed4I" %} + ins_encode %{ + bool vector256 = false; + __ vpsrad($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra4I_reg_imm(vecX dst, vecX src, immI8 shift) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (RShiftVI src shift)); + format %{ "vpsrad $dst,$src,$shift\t! arithmetic right shift packed4I" %} + ins_encode %{ + bool vector256 = false; + __ vpsrad($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra8I_reg(vecY dst, vecY src, regF shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 8); + match(Set dst (RShiftVI src shift)); + format %{ "vpsrad $dst,$src,$shift\t! arithmetic right shift packed8I" %} + ins_encode %{ + bool vector256 = true; + __ vpsrad($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra8I_reg_imm(vecY dst, vecY src, immI8 shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 8); + match(Set dst (RShiftVI src shift)); + format %{ "vpsrad $dst,$src,$shift\t! arithmetic right shift packed8I" %} + ins_encode %{ + bool vector256 = true; + __ vpsrad($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// There are no longs vector arithmetic right shift instructions. + + +// --------------------------------- AND -------------------------------------- + +instruct vand4B(vecS dst, vecS src) %{ + predicate(n->as_Vector()->length_in_bytes() == 4); + match(Set dst (AndV dst src)); + format %{ "pand $dst,$src\t! and vectors (4 bytes)" %} + ins_encode %{ + __ pand($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vand4B_reg(vecS dst, vecS src1, vecS src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 4); + match(Set dst (AndV src1 src2)); + format %{ "vpand $dst,$src1,$src2\t! and vectors (4 bytes)" %} + ins_encode %{ + bool vector256 = false; + __ vpand($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vand8B(vecD dst, vecD src) %{ + predicate(n->as_Vector()->length_in_bytes() == 8); + match(Set dst (AndV dst src)); + format %{ "pand $dst,$src\t! and vectors (8 bytes)" %} + ins_encode %{ + __ pand($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vand8B_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 8); + match(Set dst (AndV src1 src2)); + format %{ "vpand $dst,$src1,$src2\t! and vectors (8 bytes)" %} + ins_encode %{ + bool vector256 = false; + __ vpand($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vand16B(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length_in_bytes() == 16); + match(Set dst (AndV dst src)); + format %{ "pand $dst,$src\t! and vectors (16 bytes)" %} + ins_encode %{ + __ pand($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vand16B_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 16); + match(Set dst (AndV src1 src2)); + format %{ "vpand $dst,$src1,$src2\t! and vectors (16 bytes)" %} + ins_encode %{ + bool vector256 = false; + __ vpand($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vand16B_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 16); + match(Set dst (AndV src (LoadVector mem))); + format %{ "vpand $dst,$src,$mem\t! and vectors (16 bytes)" %} + ins_encode %{ + bool vector256 = false; + __ vpand($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vand32B_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 1 && n->as_Vector()->length_in_bytes() == 32); + match(Set dst (AndV src1 src2)); + format %{ "vpand $dst,$src1,$src2\t! and vectors (32 bytes)" %} + ins_encode %{ + bool vector256 = true; + __ vpand($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vand32B_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 1 && n->as_Vector()->length_in_bytes() == 32); + match(Set dst (AndV src (LoadVector mem))); + format %{ "vpand $dst,$src,$mem\t! and vectors (32 bytes)" %} + ins_encode %{ + bool vector256 = true; + __ vpand($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// --------------------------------- OR --------------------------------------- + +instruct vor4B(vecS dst, vecS src) %{ + predicate(n->as_Vector()->length_in_bytes() == 4); + match(Set dst (OrV dst src)); + format %{ "por $dst,$src\t! or vectors (4 bytes)" %} + ins_encode %{ + __ por($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vor4B_reg(vecS dst, vecS src1, vecS src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 4); + match(Set dst (OrV src1 src2)); + format %{ "vpor $dst,$src1,$src2\t! or vectors (4 bytes)" %} + ins_encode %{ + bool vector256 = false; + __ vpor($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vor8B(vecD dst, vecD src) %{ + predicate(n->as_Vector()->length_in_bytes() == 8); + match(Set dst (OrV dst src)); + format %{ "por $dst,$src\t! or vectors (8 bytes)" %} + ins_encode %{ + __ por($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vor8B_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 8); + match(Set dst (OrV src1 src2)); + format %{ "vpor $dst,$src1,$src2\t! or vectors (8 bytes)" %} + ins_encode %{ + bool vector256 = false; + __ vpor($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vor16B(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length_in_bytes() == 16); + match(Set dst (OrV dst src)); + format %{ "por $dst,$src\t! or vectors (16 bytes)" %} + ins_encode %{ + __ por($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vor16B_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 16); + match(Set dst (OrV src1 src2)); + format %{ "vpor $dst,$src1,$src2\t! or vectors (16 bytes)" %} + ins_encode %{ + bool vector256 = false; + __ vpor($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vor16B_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 16); + match(Set dst (OrV src (LoadVector mem))); + format %{ "vpor $dst,$src,$mem\t! or vectors (16 bytes)" %} + ins_encode %{ + bool vector256 = false; + __ vpor($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vor32B_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 1 && n->as_Vector()->length_in_bytes() == 32); + match(Set dst (OrV src1 src2)); + format %{ "vpor $dst,$src1,$src2\t! or vectors (32 bytes)" %} + ins_encode %{ + bool vector256 = true; + __ vpor($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vor32B_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 1 && n->as_Vector()->length_in_bytes() == 32); + match(Set dst (OrV src (LoadVector mem))); + format %{ "vpor $dst,$src,$mem\t! or vectors (32 bytes)" %} + ins_encode %{ + bool vector256 = true; + __ vpor($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +// --------------------------------- XOR -------------------------------------- + +instruct vxor4B(vecS dst, vecS src) %{ + predicate(n->as_Vector()->length_in_bytes() == 4); + match(Set dst (XorV dst src)); + format %{ "pxor $dst,$src\t! xor vectors (4 bytes)" %} + ins_encode %{ + __ pxor($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vxor4B_reg(vecS dst, vecS src1, vecS src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 4); + match(Set dst (XorV src1 src2)); + format %{ "vpxor $dst,$src1,$src2\t! xor vectors (4 bytes)" %} + ins_encode %{ + bool vector256 = false; + __ vpxor($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vxor8B(vecD dst, vecD src) %{ + predicate(n->as_Vector()->length_in_bytes() == 8); + match(Set dst (XorV dst src)); + format %{ "pxor $dst,$src\t! xor vectors (8 bytes)" %} + ins_encode %{ + __ pxor($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vxor8B_reg(vecD dst, vecD src1, vecD src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 8); + match(Set dst (XorV src1 src2)); + format %{ "vpxor $dst,$src1,$src2\t! xor vectors (8 bytes)" %} + ins_encode %{ + bool vector256 = false; + __ vpxor($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vxor16B(vecX dst, vecX src) %{ + predicate(n->as_Vector()->length_in_bytes() == 16); + match(Set dst (XorV dst src)); + format %{ "pxor $dst,$src\t! xor vectors (16 bytes)" %} + ins_encode %{ + __ pxor($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vxor16B_reg(vecX dst, vecX src1, vecX src2) %{ + predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 16); + match(Set dst (XorV src1 src2)); + format %{ "vpxor $dst,$src1,$src2\t! xor vectors (16 bytes)" %} + ins_encode %{ + bool vector256 = false; + __ vpxor($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vxor16B_mem(vecX dst, vecX src, memory mem) %{ + predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 16); + match(Set dst (XorV src (LoadVector mem))); + format %{ "vpxor $dst,$src,$mem\t! xor vectors (16 bytes)" %} + ins_encode %{ + bool vector256 = false; + __ vpxor($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vxor32B_reg(vecY dst, vecY src1, vecY src2) %{ + predicate(UseAVX > 1 && n->as_Vector()->length_in_bytes() == 32); + match(Set dst (XorV src1 src2)); + format %{ "vpxor $dst,$src1,$src2\t! xor vectors (32 bytes)" %} + ins_encode %{ + bool vector256 = true; + __ vpxor($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, vector256); + %} + ins_pipe( pipe_slow ); +%} + +instruct vxor32B_mem(vecY dst, vecY src, memory mem) %{ + predicate(UseAVX > 1 && n->as_Vector()->length_in_bytes() == 32); + match(Set dst (XorV src (LoadVector mem))); + format %{ "vpxor $dst,$src,$mem\t! xor vectors (32 bytes)" %} + ins_encode %{ + bool vector256 = true; + __ vpxor($dst$$XMMRegister, $src$$XMMRegister, $mem$$Address, vector256); + %} + ins_pipe( pipe_slow ); +%} +
--- a/src/cpu/x86/vm/x86_32.ad Fri Nov 09 13:32:53 2012 +0100 +++ b/src/cpu/x86/vm/x86_32.ad Fri Nov 09 13:35:26 2012 +0100 @@ -1367,22 +1367,6 @@ return offset; } - -const bool Matcher::match_rule_supported(int opcode) { - if (!has_match_rule(opcode)) - return false; - - switch (opcode) { - case Op_PopCountI: - case Op_PopCountL: - if (!UsePopCountInstruction) - return false; - break; - } - - return true; // Per default match rules are supported. -} - int Matcher::regnum_to_fpu_offset(int regnum) { return regnum - 32; // The FP registers are in the second chunk }
--- a/src/cpu/x86/vm/x86_64.ad Fri Nov 09 13:32:53 2012 +0100 +++ b/src/cpu/x86/vm/x86_64.ad Fri Nov 09 13:35:26 2012 +0100 @@ -1513,22 +1513,6 @@ return offset; } - -const bool Matcher::match_rule_supported(int opcode) { - if (!has_match_rule(opcode)) - return false; - - switch (opcode) { - case Op_PopCountI: - case Op_PopCountL: - if (!UsePopCountInstruction) - return false; - break; - } - - return true; // Per default match rules are supported. -} - int Matcher::regnum_to_fpu_offset(int regnum) { return regnum - 32; // The FP registers are in the second chunk @@ -6427,6 +6411,31 @@ ins_pipe(ialu_reg_reg); // XXX %} +// Convert oop into int for vectors alignment masking +instruct convP2I(rRegI dst, rRegP src) +%{ + match(Set dst (ConvL2I (CastP2X src))); + + format %{ "movl $dst, $src\t# ptr -> int" %} + ins_encode %{ + __ movl($dst$$Register, $src$$Register); + %} + ins_pipe(ialu_reg_reg); // XXX +%} + +// Convert compressed oop into int for vectors alignment masking +// in case of 32bit oops (heap < 4Gb). +instruct convN2I(rRegI dst, rRegN src) +%{ + predicate(Universe::narrow_oop_shift() == 0); + match(Set dst (ConvL2I (CastP2X (DecodeN src)))); + + format %{ "movl $dst, $src\t# compressed ptr -> int" %} + ins_encode %{ + __ movl($dst$$Register, $src$$Register); + %} + ins_pipe(ialu_reg_reg); // XXX +%} // Convert oop pointer into compressed form instruct encodeHeapOop(rRegN dst, rRegP src, rFlagsReg cr) %{ @@ -10049,11 +10058,10 @@ ins_pipe( pipe_slow ); %} -// The next instructions have long latency and use Int unit. Set high cost. instruct MoveI2F_reg_reg(regF dst, rRegI src) %{ match(Set dst (MoveI2F src)); effect(DEF dst, USE src); - ins_cost(300); + ins_cost(100); format %{ "movd $dst,$src\t# MoveI2F" %} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); @@ -10064,7 +10072,7 @@ instruct MoveL2D_reg_reg(regD dst, rRegL src) %{ match(Set dst (MoveL2D src)); effect(DEF dst, USE src); - ins_cost(300); + ins_cost(100); format %{ "movd $dst,$src\t# MoveL2D" %} ins_encode %{ __ movdq($dst$$XMMRegister, $src$$Register);
--- a/src/cpu/zero/vm/globals_zero.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/cpu/zero/vm/globals_zero.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -60,4 +60,7 @@ // GC Ergo Flags define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread + +#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) + #endif // CPU_ZERO_VM_GLOBALS_ZERO_HPP
--- a/src/os/bsd/vm/os_bsd.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/os/bsd/vm/os_bsd.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -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 @@ -202,7 +202,7 @@ static void fast_thread_clock_init(void); #endif - static bool supports_monotonic_clock() { + static inline bool supports_monotonic_clock() { return _clock_gettime != NULL; }
--- a/src/os/linux/vm/os_linux.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/os/linux/vm/os_linux.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -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 @@ -178,7 +178,7 @@ // fast POSIX clocks support static void fast_thread_clock_init(void); - static bool supports_monotonic_clock() { + static inline bool supports_monotonic_clock() { return _clock_gettime != NULL; }
--- a/src/os/posix/launcher/launcher.script Fri Nov 09 13:32:53 2012 +0100 +++ b/src/os/posix/launcher/launcher.script Fri Nov 09 13:35:26 2012 +0100 @@ -29,7 +29,7 @@ # inside Emacs". # # If the first parameter is "-dbx", HotSpot will be launched inside dbx. -# +# # If the first parameter is "-valgrind", HotSpot will be launched # inside Valgrind (http://valgrind.kde.org) using the Memcheck skin, # and with memory leak detection enabled. This currently (2005jan19) @@ -45,19 +45,19 @@ # This is the name of the gdb binary to use if [ ! "$GDB" ] -then +then GDB=gdb fi # This is the name of the gdb binary to use if [ ! "$DBX" ] -then +then DBX=dbx fi # This is the name of the Valgrind binary to use if [ ! "$VALGRIND" ] -then +then VALGRIND=valgrind fi @@ -98,7 +98,7 @@ JDK= if [ "${ALT_JAVA_HOME}" = "" ]; then . ${MYDIR}/jdkpath.sh -else +else JDK=${ALT_JAVA_HOME%%/jre}; fi @@ -114,22 +114,34 @@ # any. JRE=$JDK/jre JAVA_HOME=$JDK +export JAVA_HOME + ARCH=@@LIBARCH@@ - SBP=${MYDIR}:${JRE}/lib/${ARCH} -# Set up a suitable LD_LIBRARY_PATH -if [ -z "$LD_LIBRARY_PATH" ] +# Set up a suitable LD_LIBRARY_PATH or DYLD_LIBRARY_PATH +OS=`uname -s` +if [ "${OS}" = "Darwin" ] then - LD_LIBRARY_PATH="$SBP" + if [ -z "$DYLD_LIBRARY_PATH" ] + then + DYLD_LIBRARY_PATH="$SBP" + else + DYLD_LIBRARY_PATH="$SBP:$DYLD_LIBRARY_PATH" + fi + export DYLD_LIBRARY_PATH else - LD_LIBRARY_PATH="$SBP:$LD_LIBRARY_PATH" + # not 'Darwin' + if [ -z "$LD_LIBRARY_PATH" ] + then + LD_LIBRARY_PATH="$SBP" + else + LD_LIBRARY_PATH="$SBP:$LD_LIBRARY_PATH" + fi + export LD_LIBRARY_PATH fi -export LD_LIBRARY_PATH -export JAVA_HOME - JPARMS="$@ $JAVA_ARGS"; # Locate the gamma development launcher
--- a/src/os/solaris/vm/dtraceJSDT_solaris.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/os/solaris/vm/dtraceJSDT_solaris.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -626,45 +626,6 @@ } } -/** - * This prints out hex data in a 'windbg' or 'xxd' form, where each line is: - * <hex-address>: 8 * <hex-halfword> <ascii translation> - * example: - * 0000000: 7f44 4f46 0102 0102 0000 0000 0000 0000 .DOF............ - * 0000010: 0000 0000 0000 0040 0000 0020 0000 0005 .......@... .... - * 0000020: 0000 0000 0000 0040 0000 0000 0000 015d .......@.......] - * ... - */ -static void printDOFRawData(void* dof) { - size_t size = ((dof_hdr_t*)dof)->dofh_loadsz; - size_t limit = (size + 16) / 16 * 16; - for (size_t i = 0; i < limit; ++i) { - if (i % 16 == 0) { - tty->print("%07x:", i); - } - if (i % 2 == 0) { - tty->print(" "); - } - if (i < size) { - tty->print("%02x", ((unsigned char*)dof)[i]); - } else { - tty->print(" "); - } - if ((i + 1) % 16 == 0) { - tty->print(" "); - for (size_t j = 0; j < 16; ++j) { - size_t idx = i + j - 15; - char c = ((char*)dof)[idx]; - if (idx < size) { - tty->print("%c", c >= 32 && c <= 126 ? c : '.'); - } - } - tty->print_cr(""); - } - } - tty->print_cr(""); -} - static void printDOFHelper(dof_helper_t* helper) { tty->print_cr("// dof_helper_t {"); tty->print_cr("// dofhp_mod = \"%s\"", helper->dofhp_mod); @@ -672,7 +633,8 @@ tty->print_cr("// dofhp_dof = 0x%016llx", helper->dofhp_dof); printDOF((void*)helper->dofhp_dof); tty->print_cr("// }"); - printDOFRawData((void*)helper->dofhp_dof); + size_t len = ((dof_hdr_t*)helper)->dofh_loadsz; + tty->print_data((void*)helper->dofhp_dof, len, true); } #else // ndef HAVE_DTRACE_H
--- a/src/share/vm/c1/c1_CodeStubs.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/c1/c1_CodeStubs.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -574,71 +574,6 @@ #endif // PRODUCT }; -// This G1 barrier code stub is used in Unsafe.getObject. -// It generates a sequence of guards around the SATB -// barrier code that are used to detect when we have -// the referent field of a Reference object. -// The first check is assumed to have been generated -// in the code generated for Unsafe.getObject(). - -class G1UnsafeGetObjSATBBarrierStub: public CodeStub { - private: - LIR_Opr _val; - LIR_Opr _src; - - LIR_Opr _tmp; - LIR_Opr _thread; - - bool _gen_src_check; - - public: - // A G1 barrier that is guarded by generated guards that determine whether - // val (which is the result of Unsafe.getObject() should be recorded in an - // SATB log buffer. We could be reading the referent field of a Reference object - // using Unsafe.getObject() and we need to record the referent. - // - // * val is the operand returned by the unsafe.getObject routine. - // * src is the base object - // * tmp is a temp used to load the klass of src, and then reference type - // * thread is the thread object. - - G1UnsafeGetObjSATBBarrierStub(LIR_Opr val, LIR_Opr src, - LIR_Opr tmp, LIR_Opr thread, - bool gen_src_check) : - _val(val), _src(src), - _tmp(tmp), _thread(thread), - _gen_src_check(gen_src_check) - { - assert(_val->is_register(), "should have already been loaded"); - assert(_src->is_register(), "should have already been loaded"); - - assert(_tmp->is_register(), "should be a temporary register"); - } - - LIR_Opr val() const { return _val; } - LIR_Opr src() const { return _src; } - - LIR_Opr tmp() const { return _tmp; } - LIR_Opr thread() const { return _thread; } - - bool gen_src_check() const { return _gen_src_check; } - - virtual void emit_code(LIR_Assembler* e); - - virtual void visit(LIR_OpVisitState* visitor) { - visitor->do_slow_case(); - visitor->do_input(_val); - visitor->do_input(_src); - visitor->do_input(_thread); - - visitor->do_temp(_tmp); - } - -#ifndef PRODUCT - virtual void print_name(outputStream* out) const { out->print("G1UnsafeGetObjSATBBarrierStub"); } -#endif // PRODUCT -}; - class G1PostBarrierStub: public CodeStub { private: LIR_Opr _addr;
--- a/src/share/vm/c1/c1_GraphBuilder.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -1646,19 +1646,15 @@ void GraphBuilder::invoke(Bytecodes::Code code) { - const bool has_receiver = - code == Bytecodes::_invokespecial || - code == Bytecodes::_invokevirtual || - code == Bytecodes::_invokeinterface; - const bool is_invokedynamic = (code == Bytecodes::_invokedynamic); - bool will_link; - ciMethod* target = stream()->get_method(will_link); + ciSignature* declared_signature = NULL; + ciMethod* target = stream()->get_method(will_link, &declared_signature); ciKlass* holder = stream()->get_declared_method_holder(); const Bytecodes::Code bc_raw = stream()->cur_bc_raw(); + assert(declared_signature != NULL, "cannot be null"); // FIXME bail out for now - if ((bc_raw == Bytecodes::_invokehandle || is_invokedynamic) && !will_link) { + if (Bytecodes::has_optional_appendix(bc_raw) && !will_link) { BAILOUT("unlinked call site (FIXME needs patching or recompile support)"); } @@ -1690,8 +1686,12 @@ // convert them directly to an invokespecial or invokestatic. if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) { switch (bc_raw) { - case Bytecodes::_invokevirtual: code = Bytecodes::_invokespecial; break; - case Bytecodes::_invokehandle: code = Bytecodes::_invokestatic; break; + case Bytecodes::_invokevirtual: + code = Bytecodes::_invokespecial; + break; + case Bytecodes::_invokehandle: + code = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokespecial; + break; } } @@ -1840,7 +1840,7 @@ bool success = false; if (target->is_method_handle_intrinsic()) { // method handle invokes - success = for_method_handle_inline(target); + success = try_method_handle_inline(target); } else { // static binding => check if callee is ok success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL), code, better_receiver); @@ -1877,12 +1877,14 @@ // inlining not successful => standard invoke bool is_loaded = target->is_loaded(); - ValueType* result_type = as_ValueType(target->return_type()); - - // We require the debug info to be the "state before" because - // invokedynamics may deoptimize. - ValueStack* state_before = is_invokedynamic ? copy_state_before() : copy_state_exhandling(); - + ValueType* result_type = as_ValueType(declared_signature->return_type()); + ValueStack* state_before = copy_state_exhandling(); + + // The bytecode (code) might change in this method so we are checking this very late. + const bool has_receiver = + code == Bytecodes::_invokespecial || + code == Bytecodes::_invokevirtual || + code == Bytecodes::_invokeinterface; Values* args = state()->pop_arguments(target->arg_size_no_receiver()); Value recv = has_receiver ? apop() : NULL; int vtable_index = methodOopDesc::invalid_vtable_index; @@ -3058,7 +3060,7 @@ case vmIntrinsics::_Reference_get: { - if (UseG1GC) { + { // With java.lang.ref.reference.get() we must go through the // intrinsic - when G1 is enabled - even when get() is the root // method of the compile so that, if necessary, the value in @@ -3070,6 +3072,9 @@ // object removed from the list of discovered references during // reference processing. + // Also we need intrinsic to prevent commoning reads from this field + // across safepoint since GC can change its value. + // Set up a stream so that appending instructions works properly. ciBytecodeStream s(scope->method()); s.reset_to_bci(0); @@ -3226,7 +3231,6 @@ bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) { - if (!InlineNatives ) INLINE_BAILOUT("intrinsic method inlining disabled"); if (callee->is_synchronized()) { // We don't currently support any synchronized intrinsics return false; @@ -3234,9 +3238,13 @@ // callee seems like a good candidate // determine id + vmIntrinsics::ID id = callee->intrinsic_id(); + if (!InlineNatives && id != vmIntrinsics::_Reference_get) { + // InlineNatives does not control Reference.get + INLINE_BAILOUT("intrinsic method inlining disabled"); + } bool preserves_state = false; bool cantrap = true; - vmIntrinsics::ID id = callee->intrinsic_id(); switch (id) { case vmIntrinsics::_arraycopy: if (!InlineArrayCopy) return false; @@ -3376,11 +3384,10 @@ return true; case vmIntrinsics::_Reference_get: - // It is only when G1 is enabled that we absolutely - // need to use the intrinsic version of Reference.get() - // so that the value in the referent field, if necessary, - // can be registered by the pre-barrier code. - if (!UseG1GC) return false; + // Use the intrinsic version of Reference.get() so that the value in + // the referent field can be registered by the G1 pre-barrier code. + // Also to prevent commoning reads from this field across safepoint + // since GC can change its value. preserves_state = true; break; @@ -3816,7 +3823,7 @@ } -bool GraphBuilder::for_method_handle_inline(ciMethod* callee) { +bool GraphBuilder::try_method_handle_inline(ciMethod* callee) { ValueStack* state_before = state()->copy_for_parsing(); vmIntrinsics::ID iid = callee->intrinsic_id(); switch (iid) { @@ -3851,7 +3858,7 @@ // If the target is another method handle invoke try recursivly to get // a better target. if (target->is_method_handle_intrinsic()) { - if (for_method_handle_inline(target)) { + if (try_method_handle_inline(target)) { return true; } } else {
--- a/src/share/vm/c1/c1_GraphBuilder.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/c1/c1_GraphBuilder.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -346,7 +346,7 @@ const char* should_not_inline(ciMethod* callee) const; // JSR 292 support - bool for_method_handle_inline(ciMethod* callee); + bool try_method_handle_inline(ciMethod* callee); // helpers void inline_bailout(const char* msg);
--- a/src/share/vm/c1/c1_Instruction.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/c1/c1_Instruction.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -369,9 +369,6 @@ _signature = new BasicTypeList(number_of_arguments() + (has_receiver() ? 1 : 0)); if (has_receiver()) { _signature->append(as_BasicType(receiver()->type())); - } else if (is_invokedynamic()) { - // Add the synthetic MethodHandle argument to the signature. - _signature->append(T_OBJECT); } for (int i = 0; i < number_of_arguments(); i++) { ValueType* t = argument_at(i)->type();
--- a/src/share/vm/c1/c1_LIRAssembler.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/c1/c1_LIRAssembler.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -449,10 +449,10 @@ switch (op->code()) { case lir_static_call: + case lir_dynamic_call: call(op, relocInfo::static_call_type); break; case lir_optvirtual_call: - case lir_dynamic_call: call(op, relocInfo::opt_virtual_call_type); break; case lir_icvirtual_call: @@ -461,7 +461,9 @@ case lir_virtual_call: vtable_call(op); break; - default: ShouldNotReachHere(); + default: + fatal(err_msg_res("unexpected op code: %s", op->name())); + break; } // JSR 292
--- a/src/share/vm/c1/c1_LIRGenerator.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -920,7 +920,8 @@ LIR_Opr LIRGenerator::force_to_spill(LIR_Opr value, BasicType t) { - assert(type2size[t] == type2size[value->type()], "size mismatch"); + assert(type2size[t] == type2size[value->type()], + err_msg_res("size mismatch: t=%s, value->type()=%s", type2name(t), type2name(value->type()))); if (!value->is_register()) { // force into a register LIR_Opr r = new_register(value->type()); @@ -2176,9 +2177,9 @@ off.load_item(); src.load_item(); - LIR_Opr reg = rlock_result(x, x->basic_type()); - - get_Object_unsafe(reg, src.result(), off.result(), type, x->is_volatile()); + LIR_Opr value = rlock_result(x, x->basic_type()); + + get_Object_unsafe(value, src.result(), off.result(), type, x->is_volatile()); #ifndef SERIALGC // We might be reading the value of the referent field of a @@ -2191,19 +2192,16 @@ // if (offset == java_lang_ref_Reference::referent_offset) { // if (src != NULL) { // if (klass(src)->reference_type() != REF_NONE) { - // pre_barrier(..., reg, ...); + // pre_barrier(..., value, ...); // } // } // } - // - // The first non-constant check of either the offset or - // the src operand will be done here; the remainder - // will take place in the generated code stub. if (UseG1GC && type == T_OBJECT) { - bool gen_code_stub = true; // Assume we need to generate the slow code stub. - bool gen_offset_check = true; // Assume the code stub has to generate the offset guard. - bool gen_source_check = true; // Assume the code stub has to check the src object for null. + bool gen_pre_barrier = true; // Assume we need to generate pre_barrier. + bool gen_offset_check = true; // Assume we need to generate the offset guard. + bool gen_source_check = true; // Assume we need to check the src object for null. + bool gen_type_check = true; // Assume we need to check the reference_type. if (off.is_constant()) { jlong off_con = (off.type()->is_int() ? @@ -2215,7 +2213,7 @@ // The constant offset is something other than referent_offset. // We can skip generating/checking the remaining guards and // skip generation of the code stub. - gen_code_stub = false; + gen_pre_barrier = false; } else { // The constant offset is the same as referent_offset - // we do not need to generate a runtime offset check. @@ -2224,11 +2222,11 @@ } // We don't need to generate stub if the source object is an array - if (gen_code_stub && src.type()->is_array()) { - gen_code_stub = false; + if (gen_pre_barrier && src.type()->is_array()) { + gen_pre_barrier = false; } - if (gen_code_stub) { + if (gen_pre_barrier) { // We still need to continue with the checks. if (src.is_constant()) { ciObject* src_con = src.get_jobject_constant(); @@ -2236,7 +2234,7 @@ if (src_con->is_null_object()) { // The constant src object is null - We can skip // generating the code stub. - gen_code_stub = false; + gen_pre_barrier = false; } else { // Non-null constant source object. We still have to generate // the slow stub - but we don't need to generate the runtime @@ -2245,20 +2243,28 @@ } } } - - if (gen_code_stub) { - // Temoraries. - LIR_Opr src_klass = new_register(T_OBJECT); - - // Get the thread pointer for the pre-barrier - LIR_Opr thread = getThreadPointer(); - - CodeStub* stub; + if (gen_pre_barrier && !PatchALot) { + // Can the klass of object be statically determined to be + // a sub-class of Reference? + ciType* type = src.value()->declared_type(); + if ((type != NULL) && type->is_loaded()) { + if (type->is_subtype_of(compilation()->env()->Reference_klass())) { + gen_type_check = false; + } else if (type->is_klass() && + !compilation()->env()->Object_klass()->is_subtype_of(type->as_klass())) { + // Not Reference and not Object klass. + gen_pre_barrier = false; + } + } + } + + if (gen_pre_barrier) { + LabelObj* Lcont = new LabelObj(); // We can have generate one runtime check here. Let's start with // the offset check. if (gen_offset_check) { - // if (offset == referent_offset) -> slow code stub + // if (offset != referent_offset) -> continue // If offset is an int then we can do the comparison with the // referent_offset constant; otherwise we need to move // referent_offset into a temporary register and generate @@ -2273,43 +2279,36 @@ referent_off = new_register(T_LONG); __ move(LIR_OprFact::longConst(java_lang_ref_Reference::referent_offset), referent_off); } - - __ cmp(lir_cond_equal, off.result(), referent_off); - - // Optionally generate "src == null" check. - stub = new G1UnsafeGetObjSATBBarrierStub(reg, src.result(), - src_klass, thread, - gen_source_check); - - __ branch(lir_cond_equal, as_BasicType(off.type()), stub); - } else { - if (gen_source_check) { - // offset is a const and equals referent offset - // if (source != null) -> slow code stub - __ cmp(lir_cond_notEqual, src.result(), LIR_OprFact::oopConst(NULL)); - - // Since we are generating the "if src == null" guard here, - // there is no need to generate the "src == null" check again. - stub = new G1UnsafeGetObjSATBBarrierStub(reg, src.result(), - src_klass, thread, - false); - - __ branch(lir_cond_notEqual, T_OBJECT, stub); - } else { - // We have statically determined that offset == referent_offset - // && src != null so we unconditionally branch to code stub - // to perform the guards and record reg in the SATB log buffer. - - stub = new G1UnsafeGetObjSATBBarrierStub(reg, src.result(), - src_klass, thread, - false); - - __ branch(lir_cond_always, T_ILLEGAL, stub); - } + __ cmp(lir_cond_notEqual, off.result(), referent_off); + __ branch(lir_cond_notEqual, as_BasicType(off.type()), Lcont->label()); + } + if (gen_source_check) { + // offset is a const and equals referent offset + // if (source == null) -> continue + __ cmp(lir_cond_equal, src.result(), LIR_OprFact::oopConst(NULL)); + __ branch(lir_cond_equal, T_OBJECT, Lcont->label()); } - - // Continuation point - __ branch_destination(stub->continuation()); + LIR_Opr src_klass = new_register(T_OBJECT); + if (gen_type_check) { + // We have determined that offset == referent_offset && src != null. + // if (src->_klass->_reference_type == REF_NONE) -> continue + __ move(new LIR_Address(src.result(), oopDesc::klass_offset_in_bytes(), T_OBJECT), src_klass); + LIR_Address* reference_type_addr = new LIR_Address(src_klass, in_bytes(instanceKlass::reference_type_offset()), T_BYTE); + LIR_Opr reference_type = new_register(T_INT); + __ move(reference_type_addr, reference_type); + __ cmp(lir_cond_equal, reference_type, LIR_OprFact::intConst(REF_NONE)); + __ branch(lir_cond_equal, T_INT, Lcont->label()); + } + { + // We have determined that src->_klass->_reference_type != REF_NONE + // so register the value in the referent field with the pre-barrier. + pre_barrier(LIR_OprFact::illegalOpr /* addr_opr */, + value /* pre_val */, + false /* do_load */, + false /* patch */, + NULL /* info */); + } + __ branch_destination(Lcont->label()); } } #endif // SERIALGC @@ -2664,8 +2663,9 @@ void LIRGenerator::invoke_load_arguments(Invoke* x, LIRItemList* args, const LIR_OprList* arg_list) { - int i = (x->has_receiver() || x->is_invokedynamic()) ? 1 : 0; - for (; i < args->length(); i++) { + assert(args->length() == arg_list->length(), + err_msg_res("args=%d, arg_list=%d", args->length(), arg_list->length())); + for (int i = x->has_receiver() ? 1 : 0; i < args->length(); i++) { LIRItem* param = args->at(i); LIR_Opr loc = arg_list->at(i); if (loc->is_register()) { @@ -2705,15 +2705,9 @@ LIRItem* receiver = new LIRItem(x->receiver(), this); argument_items->append(receiver); } - if (x->is_invokedynamic()) { - // Insert a dummy for the synthetic MethodHandle argument. - argument_items->append(NULL); - } - int idx = x->has_receiver() ? 1 : 0; for (int i = 0; i < x->number_of_arguments(); i++) { LIRItem* param = new LIRItem(x->argument_at(i), this); argument_items->append(param); - idx += (param->type()->is_double_word() ? 2 : 1); } return argument_items; } @@ -2758,9 +2752,6 @@ CodeEmitInfo* info = state_for(x, x->state()); - // invokedynamics can deoptimize. - CodeEmitInfo* deopt_info = x->is_invokedynamic() ? state_for(x, x->state_before()) : NULL; - invoke_load_arguments(x, args, arg_list); if (x->has_receiver()) { @@ -2809,41 +2800,8 @@ } break; case Bytecodes::_invokedynamic: { - ciBytecodeStream bcs(x->scope()->method()); - bcs.force_bci(x->state()->bci()); - assert(bcs.cur_bc() == Bytecodes::_invokedynamic, "wrong stream"); - ciCPCache* cpcache = bcs.get_cpcache(); - - // Get CallSite offset from constant pool cache pointer. - int index = bcs.get_method_index(); - size_t call_site_offset = cpcache->get_f1_offset(index); - - // Load CallSite object from constant pool cache. - LIR_Opr call_site = new_register(objectType); - __ oop2reg(cpcache->constant_encoding(), call_site); - __ move_wide(new LIR_Address(call_site, call_site_offset, T_OBJECT), call_site); - - // If this invokedynamic call site hasn't been executed yet in - // the interpreter, the CallSite object in the constant pool - // cache is still null and we need to deoptimize. - if (cpcache->is_f1_null_at(index)) { - // Only deoptimize if the CallSite object is still null; we don't - // recompile methods in C1 after deoptimization so this call site - // might be resolved the next time we execute it after OSR. - DeoptimizeStub* deopt_stub = new DeoptimizeStub(deopt_info); - __ cmp(lir_cond_equal, call_site, LIR_OprFact::oopConst(NULL)); - __ branch(lir_cond_equal, T_OBJECT, deopt_stub); - } - - // Use the receiver register for the synthetic MethodHandle - // argument. - receiver = LIR_Assembler::receiverOpr(); - - // Load target MethodHandle from CallSite object. - __ load(new LIR_Address(call_site, java_lang_invoke_CallSite::target_offset_in_bytes(), T_OBJECT), receiver); - __ call_dynamic(target, receiver, result_register, - SharedRuntime::get_resolve_opt_virtual_call_stub(), + SharedRuntime::get_resolve_static_call_stub(), arg_list, info); break; }
--- a/src/share/vm/c1/c1_Runtime1.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/c1/c1_Runtime1.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -208,6 +208,7 @@ #ifdef GRAAL case graal_verify_oop_id: case graal_unwind_exception_call_id: + case graal_OSR_migration_end_id: case graal_arithmetic_frem_id: case graal_arithmetic_drem_id: case graal_set_deopt_info_id:
--- a/src/share/vm/c1/c1_Runtime1.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/c1/c1_Runtime1.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -71,6 +71,7 @@ stub(fpu2long_stub) \ stub(counter_overflow) \ stub(graal_unwind_exception_call) \ + stub(graal_OSR_migration_end) \ stub(graal_arithmetic_frem) \ stub(graal_arithmetic_drem) \ stub(graal_monitorenter) \
--- a/src/share/vm/c1/c1_ValueMap.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/c1/c1_ValueMap.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -190,7 +190,7 @@ LoadField* lf = value->as_LoadField(); \ bool must_kill = lf != NULL \ && lf->field()->holder() == field->holder() \ - && lf->field()->offset() == field->offset(); + && (all_offsets || lf->field()->offset() == field->offset()); #define MUST_KILL_EXCEPTION(must_kill, entry, value) \ assert(entry->nesting() < nesting(), "must not find bigger nesting than current"); \ @@ -205,7 +205,7 @@ GENERIC_KILL_VALUE(MUST_KILL_ARRAY); } -void ValueMap::kill_field(ciField* field) { +void ValueMap::kill_field(ciField* field, bool all_offsets) { GENERIC_KILL_VALUE(MUST_KILL_FIELD); } @@ -280,9 +280,9 @@ ValueMap* value_map_of(BlockBegin* block) { return _gvn->value_map_of(block); } // implementation for abstract methods of ValueNumberingVisitor - void kill_memory() { _too_complicated_loop = true; } - void kill_field(ciField* field) { current_map()->kill_field(field); }; - void kill_array(ValueType* type) { current_map()->kill_array(type); }; + void kill_memory() { _too_complicated_loop = true; } + void kill_field(ciField* field, bool all_offsets) { current_map()->kill_field(field, all_offsets); }; + void kill_array(ValueType* type) { current_map()->kill_array(type); }; public: ShortLoopOptimizer(GlobalValueNumbering* gvn)
--- a/src/share/vm/c1/c1_ValueMap.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/c1/c1_ValueMap.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -114,7 +114,7 @@ Value find_insert(Value x); void kill_memory(); - void kill_field(ciField* field); + void kill_field(ciField* field, bool all_offsets); void kill_array(ValueType* type); void kill_exception(); void kill_map(ValueMap* map); @@ -136,7 +136,7 @@ protected: // called by visitor functions for instructions that kill values virtual void kill_memory() = 0; - virtual void kill_field(ciField* field) = 0; + virtual void kill_field(ciField* field, bool all_offsets) = 0; virtual void kill_array(ValueType* type) = 0; // visitor functions @@ -148,7 +148,7 @@ x->field()->is_volatile()) { kill_memory(); } else { - kill_field(x->field()); + kill_field(x->field(), x->needs_patching()); } } void do_StoreIndexed (StoreIndexed* x) { kill_array(x->type()); } @@ -214,9 +214,9 @@ public: // implementation for abstract methods of ValueNumberingVisitor - void kill_memory() { _map->kill_memory(); } - void kill_field(ciField* field) { _map->kill_field(field); } - void kill_array(ValueType* type) { _map->kill_array(type); } + void kill_memory() { _map->kill_memory(); } + void kill_field(ciField* field, bool all_offsets) { _map->kill_field(field, all_offsets); } + void kill_array(ValueType* type) { _map->kill_array(type); } ValueNumberingEffects(ValueMap* map): _map(map) {} }; @@ -234,9 +234,9 @@ void set_value_map_of(BlockBegin* block, ValueMap* map) { assert(value_map_of(block) == NULL, ""); _value_maps.at_put(block->linear_scan_number(), map); } // implementation for abstract methods of ValueNumberingVisitor - void kill_memory() { current_map()->kill_memory(); } - void kill_field(ciField* field) { current_map()->kill_field(field); } - void kill_array(ValueType* type) { current_map()->kill_array(type); } + void kill_memory() { current_map()->kill_memory(); } + void kill_field(ciField* field, bool all_offsets) { current_map()->kill_field(field, all_offsets); } + void kill_array(ValueType* type) { current_map()->kill_array(type); } // main entry point that performs global value numbering GlobalValueNumbering(IR* ir);
--- a/src/share/vm/c1/c1_globals.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/c1/c1_globals.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -164,18 +164,12 @@ develop(bool, CanonicalizeNodes, true, \ "Canonicalize graph nodes") \ \ - develop(bool, CanonicalizeExperimental, false, \ - "Canonicalize graph nodes, experimental code") \ - \ develop(bool, PrintCanonicalization, false, \ "Print graph node canonicalization") \ \ develop(bool, UseTableRanges, true, \ "Faster versions of lookup table using ranges") \ \ - develop(bool, UseFastExceptionHandling, true, \ - "Faster handling of exceptions") \ - \ develop_pd(bool, RoundFPResults, \ "Indicates whether rounding is needed for floating point results")\ \ @@ -232,9 +226,6 @@ develop(bool, PinAllInstructions, false, \ "All instructions are pinned") \ \ - develop(bool, ValueStackPinStackAll, true, \ - "Pinning in ValueStack pin everything") \ - \ develop(bool, UseFastNewInstance, true, \ "Use fast inlined instance allocation") \ \
--- a/src/share/vm/ci/bcEscapeAnalyzer.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -236,12 +236,16 @@ ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(holder); ciInstanceKlass* actual_recv = callee_holder; - // some methods are obviously bindable without any type checks so - // convert them directly to an invokespecial. + // Some methods are obviously bindable without any type checks so + // convert them directly to an invokespecial or invokestatic. if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) { switch (code) { - case Bytecodes::_invokevirtual: code = Bytecodes::_invokespecial; break; - case Bytecodes::_invokehandle: code = Bytecodes::_invokestatic; break; + case Bytecodes::_invokevirtual: + code = Bytecodes::_invokespecial; + break; + case Bytecodes::_invokehandle: + code = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokespecial; + break; } } @@ -826,8 +830,8 @@ break; case Bytecodes::_getstatic: case Bytecodes::_getfield: - { bool will_link; - ciField* field = s.get_field(will_link); + { bool ignored_will_link; + ciField* field = s.get_field(ignored_will_link); BasicType field_type = field->type()->basic_type(); if (s.cur_bc() != Bytecodes::_getstatic) { set_method_escape(state.apop()); @@ -865,16 +869,21 @@ case Bytecodes::_invokestatic: case Bytecodes::_invokedynamic: case Bytecodes::_invokeinterface: - { bool will_link; - ciMethod* target = s.get_method(will_link); - ciKlass* holder = s.get_declared_method_holder(); + { bool ignored_will_link; + ciSignature* declared_signature = NULL; + ciMethod* target = s.get_method(ignored_will_link, &declared_signature); + ciKlass* holder = s.get_declared_method_holder(); + assert(declared_signature != NULL, "cannot be null"); // Push appendix argument, if one. if (s.has_appendix()) { state.apush(unknown_obj); } // Pass in raw bytecode because we need to see invokehandle instructions. invoke(state, s.cur_bc_raw(), target, holder); - ciType* return_type = target->return_type(); + // We are using the return type of the declared signature here because + // it might be a more concrete type than the one from the target (for + // e.g. invokedynamic and invokehandle). + ciType* return_type = declared_signature->return_type(); if (!return_type->is_primitive_type()) { state.apush(unknown_obj); } else if (return_type->is_one_word()) {
--- a/src/share/vm/ci/ciEnv.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/ci/ciEnv.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -737,91 +737,81 @@ ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool, int index, Bytecodes::Code bc, ciInstanceKlass* accessor) { - int holder_index = cpool->klass_ref_index_at(index); - bool holder_is_accessible; - ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor); - ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder); - - // Get the method's name and signature. - Symbol* name_sym = cpool->name_ref_at(index); - Symbol* sig_sym = cpool->signature_ref_at(index); - - if (cpool->has_preresolution() - || (holder == ciEnv::MethodHandle_klass() && - MethodHandles::is_signature_polymorphic_name(holder->get_klassOop(), name_sym))) { - // Short-circuit lookups for JSR 292-related call sites. - // That is, do not rely only on name-based lookups, because they may fail - // if the names are not resolvable in the boot class loader (7056328). - switch (bc) { - case Bytecodes::_invokevirtual: - case Bytecodes::_invokeinterface: - case Bytecodes::_invokespecial: - case Bytecodes::_invokestatic: - { - oop appendix_oop = NULL; - methodOop m = constantPoolOopDesc::method_at_if_loaded(cpool, index); - if (m != NULL) { - return get_object(m)->as_method(); - } - } - break; - } - } + if (bc == Bytecodes::_invokedynamic) { + ConstantPoolCacheEntry* secondary_entry = cpool->cache()->secondary_entry_at(index); + const bool is_resolved = !secondary_entry->is_f1_null(); + // FIXME: code generation could allow for null (unlinked) call site + // The call site could be made patchable as follows: + // Load the appendix argument from the constant pool. + // Test the appendix argument and jump to a known deopt routine if it is null. + // Jump through a patchable call site, which is initially a deopt routine. + // Patch the call site to the nmethod entry point of the static compiled lambda form. + // As with other two-component call sites, both values must be independently verified. - if (holder_is_accessible) { // Our declared holder is loaded. - instanceKlass* lookup = declared_holder->get_instanceKlass(); - methodOop m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc); - if (m != NULL && - (bc == Bytecodes::_invokestatic - ? instanceKlass::cast(m->method_holder())->is_not_initialized() - : !instanceKlass::cast(m->method_holder())->is_loaded())) { - m = NULL; + if (is_resolved) { + // Get the invoker methodOop and the extra argument from the constant pool. + methodOop adapter = secondary_entry->f2_as_vfinal_method(); + return get_object(adapter)->as_method(); } - if (m != NULL) { - // We found the method. - return get_object(m)->as_method(); - } - } - - // Either the declared holder was not loaded, or the method could - // not be found. Create a dummy ciMethod to represent the failed - // lookup. - ciSymbol* name = get_symbol(name_sym); - ciSymbol* signature = get_symbol(sig_sym); - return get_unloaded_method(declared_holder, name, signature, accessor); -} - -// ------------------------------------------------------------------ -// ciEnv::get_fake_invokedynamic_method_impl -ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool, - int index, Bytecodes::Code bc, - ciInstanceKlass* accessor) { - // Compare the following logic with InterpreterRuntime::resolve_invokedynamic. - assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic"); - - ConstantPoolCacheEntry* secondary_entry = cpool->cache()->secondary_entry_at(index); - bool is_resolved = !secondary_entry->is_f1_null(); - // FIXME: code generation could allow for null (unlinked) call site - // The call site could be made patchable as follows: - // Load the appendix argument from the constant pool. - // Test the appendix argument and jump to a known deopt routine if it is null. - // Jump through a patchable call site, which is initially a deopt routine. - // Patch the call site to the nmethod entry point of the static compiled lambda form. - // As with other two-component call sites, both values must be independently verified. - - // Call site might not be resolved yet. - // Stop the code path here with an unlinked method. - if (!is_resolved) { + // Fake a method that is equivalent to a declared method. ciInstanceKlass* holder = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass(); ciSymbol* name = ciSymbol::invokeBasic_name(); ciSymbol* signature = get_symbol(cpool->signature_ref_at(index)); return get_unloaded_method(holder, name, signature, accessor); - } + } else { + const int holder_index = cpool->klass_ref_index_at(index); + bool holder_is_accessible; + ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor); + ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder); + + // Get the method's name and signature. + Symbol* name_sym = cpool->name_ref_at(index); + Symbol* sig_sym = cpool->signature_ref_at(index); - // Get the invoker methodOop and the extra argument from the constant pool. - methodOop adapter = secondary_entry->f2_as_vfinal_method(); - return get_object(adapter)->as_method(); + if (cpool->has_preresolution() + || (holder == ciEnv::MethodHandle_klass() && + MethodHandles::is_signature_polymorphic_name(holder->get_klassOop(), name_sym))) { + // Short-circuit lookups for JSR 292-related call sites. + // That is, do not rely only on name-based lookups, because they may fail + // if the names are not resolvable in the boot class loader (7056328). + switch (bc) { + case Bytecodes::_invokevirtual: + case Bytecodes::_invokeinterface: + case Bytecodes::_invokespecial: + case Bytecodes::_invokestatic: + { + methodOop m = constantPoolOopDesc::method_at_if_loaded(cpool, index); + if (m != NULL) { + return get_object(m)->as_method(); + } + } + break; + } + } + + if (holder_is_accessible) { // Our declared holder is loaded. + instanceKlass* lookup = declared_holder->get_instanceKlass(); + methodOop m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc); + if (m != NULL && + (bc == Bytecodes::_invokestatic + ? instanceKlass::cast(m->method_holder())->is_not_initialized() + : !instanceKlass::cast(m->method_holder())->is_loaded())) { + m = NULL; + } + if (m != NULL) { + // We found the method. + return get_object(m)->as_method(); + } + } + + // Either the declared holder was not loaded, or the method could + // not be found. Create a dummy ciMethod to represent the failed + // lookup. + ciSymbol* name = get_symbol(name_sym); + ciSymbol* signature = get_symbol(sig_sym); + return get_unloaded_method(declared_holder, name, signature, accessor); + } } @@ -852,11 +842,7 @@ ciMethod* ciEnv::get_method_by_index(constantPoolHandle cpool, int index, Bytecodes::Code bc, ciInstanceKlass* accessor) { - if (bc == Bytecodes::_invokedynamic) { - GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(cpool, index, bc, accessor);) - } else { - GUARDED_VM_ENTRY(return get_method_by_index_impl( cpool, index, bc, accessor);) - } + GUARDED_VM_ENTRY(return get_method_by_index_impl(cpool, index, bc, accessor);) }
--- a/src/share/vm/ci/ciEnv.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/ci/ciEnv.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -156,9 +156,6 @@ ciMethod* get_method_by_index_impl(constantPoolHandle cpool, int method_index, Bytecodes::Code bc, ciInstanceKlass* loading_klass); - ciMethod* get_fake_invokedynamic_method_impl(constantPoolHandle cpool, - int index, Bytecodes::Code bc, - ciInstanceKlass* accessor); // Helper methods bool check_klass_accessibility(ciKlass* accessing_klass,
--- a/src/share/vm/ci/ciMethod.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/ci/ciMethod.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -1215,9 +1215,10 @@ holder()->print_name_on(st); st->print(" signature="); signature()->as_symbol()->print_symbol_on(st); - st->print(" arg_size=%d", arg_size()); if (is_loaded()) { - st->print(" loaded=true flags="); + st->print(" loaded=true"); + st->print(" arg_size=%d", arg_size()); + st->print(" flags="); flags().print_member_flags(st); } else { st->print(" loaded=false");
--- a/src/share/vm/ci/ciStreams.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/ci/ciStreams.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -355,11 +355,23 @@ // ciBytecodeStream::get_method // // If this is a method invocation bytecode, get the invoked method. -ciMethod* ciBytecodeStream::get_method(bool& will_link) { +// Additionally return the declared signature to get more concrete +// type information if required (Cf. invokedynamic and invokehandle). +ciMethod* ciBytecodeStream::get_method(bool& will_link, ciSignature* *declared_signature_result) { VM_ENTRY_MARK; + ciEnv* env = CURRENT_ENV; constantPoolHandle cpool(_method->get_methodOop()->constants()); - ciMethod* m = CURRENT_ENV->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder); + ciMethod* m = env->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder); will_link = m->is_loaded(); + // Get declared method signature and return it. + if (has_optional_appendix()) { + const int sig_index = get_method_signature_index(); + Symbol* sig_sym = cpool->symbol_at(sig_index); + ciKlass* pool_holder = env->get_object(cpool->pool_holder())->as_klass(); + (*declared_signature_result) = new (env->arena()) ciSignature(pool_holder, cpool, env->get_symbol(sig_sym)); + } else { + (*declared_signature_result) = m->signature(); + } return m; } @@ -419,35 +431,18 @@ } // ------------------------------------------------------------------ -// ciBytecodeStream::get_declared_method_signature -// -// Get the declared signature of the currently referenced method. -// -// This is always the same as the signature of the resolved method -// itself, except for _invokehandle and _invokedynamic calls. -// -ciSignature* ciBytecodeStream::get_declared_method_signature() { - int sig_index = get_method_signature_index(); - VM_ENTRY_MARK; - ciEnv* env = CURRENT_ENV; - constantPoolHandle cpool(_method->get_methodOop()->constants()); - Symbol* sig_sym = cpool->symbol_at(sig_index); - ciKlass* pool_holder = env->get_object(cpool->pool_holder())->as_klass(); - return new (env->arena()) ciSignature(pool_holder, cpool, env->get_symbol(sig_sym)); -} - -// ------------------------------------------------------------------ // ciBytecodeStream::get_method_signature_index // // Get the constant pool index of the signature of the method // referenced by the current bytecode. Used for generating // deoptimization information. int ciBytecodeStream::get_method_signature_index() { - VM_ENTRY_MARK; - constantPoolOop cpool = _holder->get_instanceKlass()->constants(); - int method_index = get_method_index(); - int name_and_type_index = cpool->name_and_type_ref_index_at(method_index); - return cpool->signature_ref_index_at(name_and_type_index); + GUARDED_VM_ENTRY( + constantPoolOop cpool = _holder->get_instanceKlass()->constants(); + const int method_index = get_method_index(); + const int name_and_type_index = cpool->name_and_type_ref_index_at(method_index); + return cpool->signature_ref_index_at(name_and_type_index); + ) } // ------------------------------------------------------------------
--- a/src/share/vm/ci/ciStreams.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/ci/ciStreams.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -151,6 +151,8 @@ // Does this instruction contain an index which refes into the CP cache? bool has_cache_index() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); } + bool has_optional_appendix() { return Bytecodes::has_optional_appendix(cur_bc_raw()); } + int get_index_u1() const { return bytecode().get_index_u1(cur_bc_raw()); } @@ -257,13 +259,11 @@ int get_field_holder_index(); int get_field_signature_index(); - // If this is a method invocation bytecode, get the invoked method. - ciMethod* get_method(bool& will_link); + ciMethod* get_method(bool& will_link, ciSignature* *declared_signature_result); bool has_appendix(); ciObject* get_appendix(); ciKlass* get_declared_method_holder(); int get_method_holder_index(); - ciSignature* get_declared_method_signature(); int get_method_signature_index(); ciCPCache* get_cpcache() const;
--- a/src/share/vm/ci/ciTypeFlow.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/ci/ciTypeFlow.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -643,9 +643,11 @@ // ------------------------------------------------------------------ // ciTypeFlow::StateVector::do_invoke void ciTypeFlow::StateVector::do_invoke(ciBytecodeStream* str, - bool has_receiver_foo) { + bool has_receiver) { bool will_link; - ciMethod* callee = str->get_method(will_link); + ciSignature* declared_signature = NULL; + ciMethod* callee = str->get_method(will_link, &declared_signature); + assert(declared_signature != NULL, "cannot be null"); if (!will_link) { // We weren't able to find the method. if (str->cur_bc() == Bytecodes::_invokedynamic) { @@ -658,22 +660,12 @@ trap(str, unloaded_holder, str->get_method_holder_index()); } } else { - // TODO Use Bytecode_invoke after metadata changes. - //Bytecode_invoke inv(str->method(), str->cur_bci()); - //const bool has_receiver = callee->is_loaded() ? !callee->is_static() : inv.has_receiver(); - Bytecode inv(str); - Bytecodes::Code code = inv.invoke_code(); - const bool has_receiver = callee->is_loaded() ? !callee->is_static() : code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic; - - ciSignature* signature = callee->signature(); - ciSignatureStream sigstr(signature); - // Push appendix argument, if one. - if (str->has_appendix()) { - ciObject* appendix = str->get_appendix(); - push_object(appendix->klass()); - } - int arg_size = signature->size(); - int stack_base = stack_size() - arg_size; + // We are using the declared signature here because it might be + // different from the callee signature (Cf. invokedynamic and + // invokehandle). + ciSignatureStream sigstr(declared_signature); + const int arg_size = declared_signature->size(); + const int stack_base = stack_size() - arg_size; int i = 0; for( ; !sigstr.at_return_type(); sigstr.next()) { ciType* type = sigstr.type(); @@ -689,7 +681,6 @@ for (int j = 0; j < arg_size; j++) { pop(); } - assert(!callee->is_loaded() || has_receiver == !callee->is_static(), "mismatch"); if (has_receiver) { // Check this? pop_object();
--- a/src/share/vm/classfile/stackMapFrame.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/classfile/stackMapFrame.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,9 +32,9 @@ #include "utilities/globalDefinitions.hpp" StackMapFrame::StackMapFrame(u2 max_locals, u2 max_stack, ClassVerifier* v) : - _offset(0), _locals_size(0), _stack_size(0), _flags(0), - _max_locals(max_locals), _max_stack(max_stack), - _verifier(v) { + _offset(0), _locals_size(0), _stack_size(0), + _stack_mark(0), _flags(0), _max_locals(max_locals), + _max_stack(max_stack), _verifier(v) { Thread* thr = v->thread(); _locals = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_locals); _stack = NEW_RESOURCE_ARRAY_IN_THREAD(thr, VerificationType, max_stack); @@ -157,17 +157,17 @@ } } - -bool StackMapFrame::is_assignable_to( +// Returns the location of the first mismatch, or 'len' if there are no +// mismatches +int StackMapFrame::is_assignable_to( VerificationType* from, VerificationType* to, int32_t len, TRAPS) const { - for (int32_t i = 0; i < len; i++) { - bool subtype = to[i].is_assignable_from( - from[i], verifier(), THREAD); - if (!subtype) { - return false; + int32_t i = 0; + for (i = 0; i < len; i++) { + if (!to[i].is_assignable_from(from[i], verifier(), THREAD)) { + break; } } - return true; + return i; } bool StackMapFrame::has_flag_match_exception( @@ -209,50 +209,84 @@ } bool StackMapFrame::is_assignable_to( - const StackMapFrame* target, bool is_exception_handler, TRAPS) const { - if (_max_locals != target->max_locals() || - _stack_size != target->stack_size()) { + const StackMapFrame* target, bool is_exception_handler, + ErrorContext* ctx, TRAPS) const { + if (_max_locals != target->max_locals()) { + *ctx = ErrorContext::locals_size_mismatch( + _offset, (StackMapFrame*)this, (StackMapFrame*)target); + return false; + } + if (_stack_size != target->stack_size()) { + *ctx = ErrorContext::stack_size_mismatch( + _offset, (StackMapFrame*)this, (StackMapFrame*)target); return false; } // Only need to compare type elements up to target->locals() or target->stack(). // The remaining type elements in this state can be ignored because they are // assignable to bogus type. - bool match_locals = is_assignable_to( - _locals, target->locals(), target->locals_size(), CHECK_false); - bool match_stack = is_assignable_to( - _stack, target->stack(), _stack_size, CHECK_false); + int mismatch_loc; + mismatch_loc = is_assignable_to( + _locals, target->locals(), target->locals_size(), THREAD); + if (mismatch_loc != target->locals_size()) { + *ctx = ErrorContext::bad_type(target->offset(), + TypeOrigin::local(mismatch_loc, (StackMapFrame*)this), + TypeOrigin::sm_local(mismatch_loc, (StackMapFrame*)target)); + return false; + } + mismatch_loc = is_assignable_to(_stack, target->stack(), _stack_size, THREAD); + if (mismatch_loc != _stack_size) { + *ctx = ErrorContext::bad_type(target->offset(), + TypeOrigin::stack(mismatch_loc, (StackMapFrame*)this), + TypeOrigin::sm_stack(mismatch_loc, (StackMapFrame*)target)); + return false; + } + bool match_flags = (_flags | target->flags()) == target->flags(); - - return match_locals && match_stack && - (match_flags || (is_exception_handler && has_flag_match_exception(target))); + if (match_flags || is_exception_handler && has_flag_match_exception(target)) { + return true; + } else { + *ctx = ErrorContext::bad_flags(target->offset(), + (StackMapFrame*)this, (StackMapFrame*)target); + return false; + } } VerificationType StackMapFrame::pop_stack_ex(VerificationType type, TRAPS) { if (_stack_size <= 0) { - verifier()->verify_error(_offset, "Operand stack underflow"); + verifier()->verify_error( + ErrorContext::stack_underflow(_offset, this), + "Operand stack underflow"); return VerificationType::bogus_type(); } VerificationType top = _stack[--_stack_size]; bool subtype = type.is_assignable_from( top, verifier(), CHECK_(VerificationType::bogus_type())); if (!subtype) { - verifier()->verify_error(_offset, "Bad type on operand stack"); + verifier()->verify_error( + ErrorContext::bad_type(_offset, stack_top_ctx(), + TypeOrigin::implicit(type)), + "Bad type on operand stack"); return VerificationType::bogus_type(); } - NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); ) return top; } VerificationType StackMapFrame::get_local( int32_t index, VerificationType type, TRAPS) { if (index >= _max_locals) { - verifier()->verify_error(_offset, "Local variable table overflow"); + verifier()->verify_error( + ErrorContext::bad_local_index(_offset, index), + "Local variable table overflow"); return VerificationType::bogus_type(); } bool subtype = type.is_assignable_from(_locals[index], verifier(), CHECK_(VerificationType::bogus_type())); if (!subtype) { - verifier()->verify_error(_offset, "Bad local variable type"); + verifier()->verify_error( + ErrorContext::bad_type(_offset, + TypeOrigin::local(index, this), + TypeOrigin::implicit(type)), + "Bad local variable type"); return VerificationType::bogus_type(); } if(index >= _locals_size) { _locals_size = index + 1; } @@ -264,23 +298,37 @@ assert(type1.is_long() || type1.is_double(), "must be long/double"); assert(type2.is_long2() || type2.is_double2(), "must be long/double_2"); if (index >= _locals_size - 1) { - verifier()->verify_error(_offset, "get long/double overflows locals"); + verifier()->verify_error( + ErrorContext::bad_local_index(_offset, index), + "get long/double overflows locals"); return; } - bool subtype1 = type1.is_assignable_from( - _locals[index], verifier(), CHECK); - bool subtype2 = type2.is_assignable_from( - _locals[index+1], verifier(), CHECK); - if (!subtype1 || !subtype2) { - verifier()->verify_error(_offset, "Bad local variable type"); - return; + bool subtype = type1.is_assignable_from(_locals[index], verifier(), CHECK); + if (!subtype) { + verifier()->verify_error( + ErrorContext::bad_type(_offset, + TypeOrigin::local(index, this), TypeOrigin::implicit(type1)), + "Bad local variable type"); + } else { + subtype = type2.is_assignable_from(_locals[index + 1], verifier(), CHECK); + if (!subtype) { + /* Unreachable? All local store routines convert a split long or double + * into a TOP during the store. So we should never end up seeing an + * orphaned half. */ + verifier()->verify_error( + ErrorContext::bad_type(_offset, + TypeOrigin::local(index + 1, this), TypeOrigin::implicit(type2)), + "Bad local variable type"); + } } } void StackMapFrame::set_local(int32_t index, VerificationType type, TRAPS) { assert(!type.is_check(), "Must be a real type"); if (index >= _max_locals) { - verifier()->verify_error("Local variable table overflow", _offset); + verifier()->verify_error( + ErrorContext::bad_local_index(_offset, index), + "Local variable table overflow"); return; } // If type at index is double or long, set the next location to be unusable @@ -310,7 +358,9 @@ assert(type1.is_long() || type1.is_double(), "must be long/double"); assert(type2.is_long2() || type2.is_double2(), "must be long/double_2"); if (index >= _max_locals - 1) { - verifier()->verify_error("Local variable table overflow", _offset); + verifier()->verify_error( + ErrorContext::bad_local_index(_offset, index), + "Local variable table overflow"); return; } // If type at index+1 is double or long, set the next location to be unusable @@ -336,21 +386,30 @@ } } -#ifndef PRODUCT - -void StackMapFrame::print() const { - tty->print_cr("stackmap_frame[%d]:", _offset); - tty->print_cr("flags = 0x%x", _flags); - tty->print("locals[%d] = { ", _locals_size); - for (int32_t i = 0; i < _locals_size; i++) { - _locals[i].print_on(tty); - } - tty->print_cr(" }"); - tty->print("stack[%d] = { ", _stack_size); - for (int32_t j = 0; j < _stack_size; j++) { - _stack[j].print_on(tty); - } - tty->print_cr(" }"); +TypeOrigin StackMapFrame::stack_top_ctx() { + return TypeOrigin::stack(_stack_size, this); } -#endif +void StackMapFrame::print_on(outputStream* str) const { + str->indent().print_cr("bci: @%d", _offset); + str->indent().print_cr("flags: {%s }", + flag_this_uninit() ? " flagThisUninit" : ""); + str->indent().print("locals: {"); + for (int32_t i = 0; i < _locals_size; ++i) { + str->print(" "); + _locals[i].print_on(str); + if (i != _locals_size - 1) { + str->print(","); + } + } + str->print_cr(" }"); + str->indent().print("stack: {"); + for (int32_t j = 0; j < _stack_size; ++j) { + str->print(" "); + _stack[j].print_on(str); + if (j != _stack_size - 1) { + str->print(","); + } + } + str->print_cr(" }"); +}
--- a/src/share/vm/classfile/stackMapFrame.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/classfile/stackMapFrame.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,8 @@ // A StackMapFrame represents one frame in the stack map attribute. +class TypeContext; + enum { FLAG_THIS_UNINIT = 0x01 }; @@ -47,6 +49,10 @@ int32_t _locals_size; // number of valid type elements in _locals int32_t _stack_size; // number of valid type elements in _stack + int32_t _stack_mark; // Records the size of the stack prior to an + // instruction modification, to allow rewinding + // when/if an error occurs. + int32_t _max_locals; int32_t _max_stack; @@ -56,6 +62,31 @@ ClassVerifier* _verifier; // the verifier verifying this method + StackMapFrame(const StackMapFrame& cp) : + _offset(cp._offset), _locals_size(cp._locals_size), + _stack_size(cp._stack_size), _stack_mark(cp._stack_mark), + _max_locals(cp._max_locals), _max_stack(cp._max_stack), + _flags(cp._flags) { + _locals = NEW_RESOURCE_ARRAY(VerificationType, _max_locals); + for (int i = 0; i < _max_locals; ++i) { + if (i < _locals_size) { + _locals[i] = cp._locals[i]; + } else { + _locals[i] = VerificationType::bogus_type(); + } + } + int ss = MAX2(_stack_size, _stack_mark); + _stack = NEW_RESOURCE_ARRAY(VerificationType, _max_stack); + for (int i = 0; i < _max_stack; ++i) { + if (i < ss) { + _stack[i] = cp._stack[i]; + } else { + _stack[i] = VerificationType::bogus_type(); + } + } + _verifier = NULL; + } + public: // constructors @@ -77,16 +108,21 @@ ClassVerifier* v) : _offset(offset), _flags(flags), _locals_size(locals_size), _stack_size(stack_size), + _stack_mark(-1), _max_locals(max_locals), _max_stack(max_stack), _locals(locals), _stack(stack), _verifier(v) { } + static StackMapFrame* copy(StackMapFrame* smf) { + return new StackMapFrame(*smf); + } + inline void set_offset(int32_t offset) { _offset = offset; } inline void set_verifier(ClassVerifier* v) { _verifier = v; } inline void set_flags(u1 flags) { _flags = flags; } inline void set_locals_size(u2 locals_size) { _locals_size = locals_size; } - inline void set_stack_size(u2 stack_size) { _stack_size = stack_size; } + inline void set_stack_size(u2 stack_size) { _stack_size = _stack_mark = stack_size; } inline void clear_stack() { _stack_size = 0; } inline int32_t offset() const { return _offset; } inline ClassVerifier* verifier() const { return _verifier; } @@ -134,14 +170,37 @@ void copy_stack(const StackMapFrame* src); // Return true if this stack map frame is assignable to target. - bool is_assignable_to(const StackMapFrame* target, - bool is_exception_handler, TRAPS) const; + bool is_assignable_to( + const StackMapFrame* target, bool is_exception_handler, + ErrorContext* ctx, TRAPS) const; + + inline void set_mark() { +#ifdef DEBUG + // Put bogus type to indicate it's no longer valid. + if (_stack_mark != -1) { + for (int i = _stack_mark; i >= _stack_size; --i) { + _stack[i] = VerificationType::bogus_type(); + } + } +#endif // def DEBUG + _stack_mark = _stack_size; + } + + // Used when an error occurs and we want to reset the stack to the state + // it was before operands were popped off. + void restore() { + if (_stack_mark != -1) { + _stack_size = _stack_mark; + } + } // Push type into stack type array. inline void push_stack(VerificationType type, TRAPS) { assert(!type.is_check(), "Must be a real type"); if (_stack_size >= _max_stack) { - verifier()->verify_error(_offset, "Operand stack overflow"); + verifier()->verify_error( + ErrorContext::stack_overflow(_offset, this), + "Operand stack overflow"); return; } _stack[_stack_size++] = type; @@ -152,7 +211,9 @@ assert(type1.is_long() || type1.is_double(), "must be long/double"); assert(type2.is_long2() || type2.is_double2(), "must be long/double_2"); if (_stack_size >= _max_stack - 1) { - verifier()->verify_error(_offset, "Operand stack overflow"); + verifier()->verify_error( + ErrorContext::stack_overflow(_offset, this), + "Operand stack overflow"); return; } _stack[_stack_size++] = type1; @@ -162,13 +223,12 @@ // Pop and return the top type on stack without verifying. inline VerificationType pop_stack(TRAPS) { if (_stack_size <= 0) { - verifier()->verify_error(_offset, "Operand stack underflow"); + verifier()->verify_error( + ErrorContext::stack_underflow(_offset, this), + "Operand stack underflow"); return VerificationType::bogus_type(); } - // Put bogus type to indicate it's no longer valid. - // Added to make it consistent with the other pop_stack method. VerificationType top = _stack[--_stack_size]; - NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); ) return top; } @@ -180,8 +240,7 @@ bool subtype = type.is_assignable_from( top, verifier(), CHECK_(VerificationType::bogus_type())); if (subtype) { - _stack_size --; - NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); ) + --_stack_size; return top; } } @@ -199,8 +258,6 @@ bool subtype2 = type2.is_assignable_from(top2, verifier(), CHECK); if (subtype1 && subtype2) { _stack_size -= 2; - NOT_PRODUCT( _stack[_stack_size] = VerificationType::bogus_type(); ) - NOT_PRODUCT( _stack[_stack_size+1] = VerificationType::bogus_type(); ) return; } } @@ -208,6 +265,14 @@ pop_stack_ex(type2, THREAD); } + VerificationType local_at(int index) { + return _locals[index]; + } + + VerificationType stack_at(int index) { + return _stack[index]; + } + // Uncommon case that throws exceptions. VerificationType pop_stack_ex(VerificationType type, TRAPS); @@ -226,13 +291,14 @@ // Private auxiliary method used only in is_assignable_to(StackMapFrame). // Returns true if src is assignable to target. - bool is_assignable_to( + int is_assignable_to( VerificationType* src, VerificationType* target, int32_t len, TRAPS) const; bool has_flag_match_exception(const StackMapFrame* target) const; - // Debugging - void print() const PRODUCT_RETURN; + TypeOrigin stack_top_ctx(); + + void print_on(outputStream* str) const; }; #endif // SHARE_VM_CLASSFILE_STACKMAPFRAME_HPP
--- a/src/share/vm/classfile/stackMapTable.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/classfile/stackMapTable.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,9 @@ _frame_array[i] = frame; int offset = frame->offset(); if (offset >= code_len || code_data[offset] == 0) { - frame->verifier()->verify_error("StackMapTable error: bad offset"); + frame->verifier()->verify_error( + ErrorContext::bad_stackmap(i, frame), + "StackMapTable error: bad offset"); return; } pre_frame = frame; @@ -68,12 +70,9 @@ bool StackMapTable::match_stackmap( StackMapFrame* frame, int32_t target, - bool match, bool update, TRAPS) const { + bool match, bool update, ErrorContext* ctx, TRAPS) const { int index = get_index_from_offset(target); - - return match_stackmap( - frame, target, index, match, - update, CHECK_VERIFY_(frame->verifier(), false)); + return match_stackmap(frame, target, index, match, update, ctx, THREAD); } // Match and/or update current_frame to the frame in stackmap table with @@ -88,23 +87,23 @@ // unconditional branch: true true bool StackMapTable::match_stackmap( StackMapFrame* frame, int32_t target, int32_t frame_index, - bool match, bool update, TRAPS) const { + bool match, bool update, ErrorContext* ctx, TRAPS) const { if (frame_index < 0 || frame_index >= _frame_count) { - frame->verifier()->verify_error(frame->offset(), - "Expecting a stackmap frame at branch target %d", target); + *ctx = ErrorContext::missing_stackmap(frame->offset()); + frame->verifier()->verify_error( + *ctx, "Expecting a stackmap frame at branch target %d", target); return false; } + StackMapFrame *stackmap_frame = _frame_array[frame_index]; bool result = true; - StackMapFrame *stackmap_frame = _frame_array[frame_index]; if (match) { // when checking handler target, match == true && update == false bool is_exception_handler = !update; // Has direct control flow from last instruction, need to match the two // frames. - result = frame->is_assignable_to( - stackmap_frame, is_exception_handler, - CHECK_VERIFY_(frame->verifier(), false)); + result = frame->is_assignable_to(stackmap_frame, is_exception_handler, + ctx, CHECK_VERIFY_(frame->verifier(), result)); } if (update) { // Use the frame in stackmap table as current frame @@ -125,11 +124,12 @@ void StackMapTable::check_jump_target( StackMapFrame* frame, int32_t target, TRAPS) const { + ErrorContext ctx; bool match = match_stackmap( - frame, target, true, false, CHECK_VERIFY(frame->verifier())); + frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier())); if (!match || (target < 0 || target >= _code_length)) { - frame->verifier()->verify_error(frame->offset(), - "Inconsistent stackmap frames at branch target %d", target); + frame->verifier()->verify_error(ctx, + "Inconsistent stackmap frames at branch target %d", target); return; } // check if uninitialized objects exist on backward branches @@ -139,25 +139,25 @@ void StackMapTable::check_new_object( const StackMapFrame* frame, int32_t target, TRAPS) const { if (frame->offset() > target && frame->has_new_object()) { - frame->verifier()->verify_error(frame->offset(), - "Uninitialized object exists on backward branch %d", target); + frame->verifier()->verify_error( + ErrorContext::bad_code(frame->offset()), + "Uninitialized object exists on backward branch %d", target); return; } } -#ifndef PRODUCT - -void StackMapTable::print() const { - tty->print_cr("StackMapTable: frame_count = %d", _frame_count); - tty->print_cr("table = { "); - for (int32_t i = 0; i < _frame_count; i++) { - _frame_array[i]->print(); +void StackMapTable::print_on(outputStream* str) const { + str->indent().print_cr("StackMapTable: frame_count = %d", _frame_count); + str->indent().print_cr("table = { "); + { + streamIndentor si(str); + for (int32_t i = 0; i < _frame_count; ++i) { + _frame_array[i]->print_on(str); + } } - tty->print_cr(" }"); + str->print_cr(" }"); } -#endif - int32_t StackMapReader::chop( VerificationType* locals, int32_t length, int32_t chops) { if (locals == NULL) return -1;
--- a/src/share/vm/classfile/stackMapTable.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/classfile/stackMapTable.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ #define SHARE_VM_CLASSFILE_STACKMAPTABLE_HPP #include "classfile/stackMapFrame.hpp" +#include "classfile/verifier.hpp" #include "memory/allocation.hpp" #include "oops/constantPoolOop.hpp" #include "oops/methodOop.hpp" @@ -73,12 +74,12 @@ // specified offset. Return true if the two frames match. bool match_stackmap( StackMapFrame* current_frame, int32_t offset, - bool match, bool update, TRAPS) const; + bool match, bool update, ErrorContext* ctx, TRAPS) const; // Match and/or update current_frame to the frame in stackmap table with // specified offset and frame index. Return true if the two frames match. bool match_stackmap( StackMapFrame* current_frame, int32_t offset, int32_t frame_index, - bool match, bool update, TRAPS) const; + bool match, bool update, ErrorContext* ctx, TRAPS) const; // Check jump instructions. Make sure there are no uninitialized // instances on backward branch. @@ -93,8 +94,7 @@ void check_new_object( const StackMapFrame* frame, int32_t target, TRAPS) const; - // Debugging - void print() const PRODUCT_RETURN; + void print_on(outputStream* str) const; }; class StackMapStream : StackObj {
--- a/src/share/vm/classfile/stackMapTableFormat.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/classfile/stackMapTableFormat.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -135,7 +135,6 @@ !is_object() && !is_uninitialized())); } -#ifdef ASSERT void print_on(outputStream* st) { switch (tag()) { case ITEM_Top: st->print("Top"); break; @@ -154,14 +153,13 @@ assert(false, "Bad verification_type_info"); } } -#endif }; #define FOR_EACH_STACKMAP_FRAME_TYPE(macro, arg1, arg2) \ macro(same_frame, arg1, arg2) \ macro(same_frame_extended, arg1, arg2) \ - macro(same_frame_1_stack_item_frame, arg1, arg2) \ - macro(same_frame_1_stack_item_extended, arg1, arg2) \ + macro(same_locals_1_stack_item_frame, arg1, arg2) \ + macro(same_locals_1_stack_item_extended, arg1, arg2) \ macro(chop_frame, arg1, arg2) \ macro(append_frame, arg1, arg2) \ macro(full_frame, arg1, arg2) @@ -203,9 +201,8 @@ // that we don't read past a particular memory limit. It returns false // if any part of the data structure is outside the specified memory bounds. inline bool verify(address start, address end) const; -#ifdef ASSERT - inline void print_on(outputStream* st) const; -#endif + + inline void print_on(outputStream* st, int current_offset) const; // Create as_xxx and is_xxx methods for the subtypes #define FRAME_TYPE_DECL(stackmap_frame_type, arg1, arg2) \ @@ -263,11 +260,9 @@ return true; } -#ifdef ASSERT - void print_on(outputStream* st) const { - st->print("same_frame(%d)", offset_delta()); + void print_on(outputStream* st, int current_offset = -1) const { + st->print("same_frame(@%d)", offset_delta() + current_offset); } -#endif }; class same_frame_extended : public stack_map_frame { @@ -311,14 +306,12 @@ return frame_type_addr() + size() <= end; } -#ifdef ASSERT - void print_on(outputStream* st) const { - st->print("same_frame_extended(%d)", offset_delta()); + void print_on(outputStream* st, int current_offset = -1) const { + st->print("same_frame_extended(@%d)", offset_delta() + current_offset); } -#endif }; -class same_frame_1_stack_item_frame : public stack_map_frame { +class same_locals_1_stack_item_frame : public stack_map_frame { private: address type_addr() const { return frame_type_addr() + sizeof(u1); } @@ -332,14 +325,14 @@ return tag >= 64 && tag < 128; } - static same_frame_1_stack_item_frame* at(address addr) { + static same_locals_1_stack_item_frame* at(address addr) { assert(is_frame_type(*addr), "Wrong frame id"); - return (same_frame_1_stack_item_frame*)addr; + return (same_locals_1_stack_item_frame*)addr; } - static same_frame_1_stack_item_frame* create_at( + static same_locals_1_stack_item_frame* create_at( address addr, int offset_delta, verification_type_info* vti) { - same_frame_1_stack_item_frame* sm = (same_frame_1_stack_item_frame*)addr; + same_locals_1_stack_item_frame* sm = (same_locals_1_stack_item_frame*)addr; sm->set_offset_delta(offset_delta); if (vti != NULL) { sm->set_type(vti); @@ -382,16 +375,15 @@ return types()->verify(start, end); } -#ifdef ASSERT - void print_on(outputStream* st) const { - st->print("same_frame_1_stack_item_frame(%d,", offset_delta()); + void print_on(outputStream* st, int current_offset = -1) const { + st->print("same_locals_1_stack_item_frame(@%d,", + offset_delta() + current_offset); types()->print_on(st); st->print(")"); } -#endif }; -class same_frame_1_stack_item_extended : public stack_map_frame { +class same_locals_1_stack_item_extended : public stack_map_frame { private: address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); } address type_addr() const { return offset_delta_addr() + sizeof(u2); } @@ -403,15 +395,15 @@ return tag == _frame_id; } - static same_frame_1_stack_item_extended* at(address addr) { + static same_locals_1_stack_item_extended* at(address addr) { assert(is_frame_type(*addr), "Wrong frame id"); - return (same_frame_1_stack_item_extended*)addr; + return (same_locals_1_stack_item_extended*)addr; } - static same_frame_1_stack_item_extended* create_at( + static same_locals_1_stack_item_extended* create_at( address addr, int offset_delta, verification_type_info* vti) { - same_frame_1_stack_item_extended* sm = - (same_frame_1_stack_item_extended*)addr; + same_locals_1_stack_item_extended* sm = + (same_locals_1_stack_item_extended*)addr; sm->set_frame_type(_frame_id); sm->set_offset_delta(offset_delta); if (vti != NULL) { @@ -448,13 +440,12 @@ return type_addr() < end && types()->verify(start, end); } -#ifdef ASSERT - void print_on(outputStream* st) const { - st->print("same_frame_1_stack_item_extended(%d,", offset_delta()); + void print_on(outputStream* st, int current_offset = -1) const { + st->print("same_locals_1_stack_item_extended(@%d,", + offset_delta() + current_offset); types()->print_on(st); st->print(")"); } -#endif }; class chop_frame : public stack_map_frame { @@ -517,11 +508,9 @@ return frame_type_addr() + size() <= end; } -#ifdef ASSERT - void print_on(outputStream* st) const { - st->print("chop_frame(%d,%d)", offset_delta(), chops()); + void print_on(outputStream* st, int current_offset = -1) const { + st->print("chop_frame(@%d,%d)", offset_delta() + current_offset, chops()); } -#endif }; class append_frame : public stack_map_frame { @@ -618,9 +607,8 @@ return false; } -#ifdef ASSERT - void print_on(outputStream* st) const { - st->print("append_frame(%d,", offset_delta()); + void print_on(outputStream* st, int current_offset = -1) const { + st->print("append_frame(@%d,", offset_delta() + current_offset); verification_type_info* vti = types(); for (int i = 0; i < number_of_types(); ++i) { vti->print_on(st); @@ -631,7 +619,6 @@ } st->print(")"); } -#endif }; class full_frame : public stack_map_frame { @@ -774,9 +761,8 @@ return true; } -#ifdef ASSERT - void print_on(outputStream* st) const { - st->print("full_frame(%d,{", offset_delta()); + void print_on(outputStream* st, int current_offset = -1) const { + st->print("full_frame(@%d,{", offset_delta() + current_offset); verification_type_info* vti = locals(); for (int i = 0; i < num_locals(); ++i) { vti->print_on(st); @@ -798,7 +784,6 @@ } st->print("})"); } -#endif }; #define VIRTUAL_DISPATCH(stack_frame_type, func_name, args) \ @@ -852,11 +837,9 @@ return false; } -#ifdef ASSERT -void stack_map_frame::print_on(outputStream* st) const { - FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_on, (st)); +void stack_map_frame::print_on(outputStream* st, int offs = -1) const { + FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_on, (st, offs)); } -#endif #undef VIRTUAL_DISPATCH #undef VOID_VIRTUAL_DISPATCH @@ -873,16 +856,46 @@ FOR_EACH_STACKMAP_FRAME_TYPE(AS_SUBTYPE_DEF, x, x) #undef AS_SUBTYPE_DEF +class stack_map_table { + private: + address number_of_entries_addr() const { + return (address)this; + } + address entries_addr() const { + return number_of_entries_addr() + sizeof(u2); + } + + protected: + // No constructors - should be 'private', but GCC issues a warning if it is + stack_map_table() {} + stack_map_table(const stack_map_table&) {} + + public: + + static stack_map_table* at(address addr) { + return (stack_map_table*)addr; + } + + u2 number_of_entries() const { + return Bytes::get_Java_u2(number_of_entries_addr()); + } + stack_map_frame* entries() const { + return stack_map_frame::at(entries_addr()); + } + + void set_number_of_entries(u2 num) { + Bytes::put_Java_u2(number_of_entries_addr(), num); + } +}; + class stack_map_table_attribute { private: address name_index_addr() const { return (address)this; } address attribute_length_addr() const { return name_index_addr() + sizeof(u2); } - address number_of_entries_addr() const { + address stack_map_table_addr() const { return attribute_length_addr() + sizeof(u4); } - address entries_addr() const { - return number_of_entries_addr() + sizeof(u2); } protected: // No constructors - should be 'private', but GCC issues a warning if it is @@ -896,17 +909,11 @@ } u2 name_index() const { - return Bytes::get_Java_u2(name_index_addr()); } + return Bytes::get_Java_u2(name_index_addr()); } u4 attribute_length() const { - return Bytes::get_Java_u4(attribute_length_addr()); } - u2 number_of_entries() const { - return Bytes::get_Java_u2(number_of_entries_addr()); } - stack_map_frame* entries() const { - return stack_map_frame::at(entries_addr()); - } - - static size_t header_size() { - return sizeof(u2) + sizeof(u4); + return Bytes::get_Java_u4(attribute_length_addr()); } + stack_map_table* table() const { + return stack_map_table::at(stack_map_table_addr()); } void set_name_index(u2 idx) { @@ -915,9 +922,8 @@ void set_attribute_length(u4 len) { Bytes::put_Java_u4(attribute_length_addr(), len); } - void set_number_of_entries(u2 num) { - Bytes::put_Java_u2(number_of_entries_addr(), num); - } }; +#undef FOR_EACH_STACKMAP_FRAME_TYPE + #endif // SHARE_VM_CLASSFILE_STACKMAPTABLEFORMAT_HPP
--- a/src/share/vm/classfile/systemDictionary.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/classfile/systemDictionary.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -200,13 +200,13 @@ template(BytecodePosition_klass, com_oracle_graal_api_code_BytecodePosition, Opt) \ template(DebugInfo_klass, com_oracle_graal_api_code_DebugInfo, Opt) \ template(BytecodeFrame_klass, com_oracle_graal_api_code_BytecodeFrame, Opt) \ - template(InstalledCode_klass, com_oracle_graal_api_code_InstalledCode, Opt) \ - template(InstalledCode_Call_klass, com_oracle_graal_api_code_InstalledCode_Call, Opt) \ - template(InstalledCode_DataPatch_klass, com_oracle_graal_api_code_InstalledCode_DataPatch, Opt) \ - template(InstalledCode_ExceptionHandler_klass, com_oracle_graal_api_code_InstalledCode_ExceptionHandler, Opt) \ - template(InstalledCode_Mark_klass, com_oracle_graal_api_code_InstalledCode_Mark, Opt) \ - template(InstalledCode_Safepoint_klass, com_oracle_graal_api_code_InstalledCode_Safepoint, Opt) \ - template(InstalledCode_Site_klass, com_oracle_graal_api_code_InstalledCode_Site, Opt) \ + template(CompilationResult_klass, com_oracle_graal_api_code_CompilationResult, Opt) \ + template(CompilationResult_Call_klass, com_oracle_graal_api_code_CompilationResult_Call, Opt) \ + template(CompilationResult_DataPatch_klass, com_oracle_graal_api_code_CompilationResult_DataPatch, Opt) \ + template(CompilationResult_ExceptionHandler_klass, com_oracle_graal_api_code_CompilationResult_ExceptionHandler, Opt) \ + template(CompilationResult_Mark_klass, com_oracle_graal_api_code_CompilationResult_Mark, Opt) \ + template(CompilationResult_Safepoint_klass, com_oracle_graal_api_code_CompilationResult_Safepoint, Opt) \ + template(CompilationResult_Site_klass, com_oracle_graal_api_code_CompilationResult_Site, Opt) \ template(code_MonitorValue_klass, com_oracle_graal_api_code_MonitorValue, Opt) \ template(code_Register_klass, com_oracle_graal_api_code_Register, Opt) \ template(RegisterValue_klass, com_oracle_graal_api_code_RegisterValue, Opt) \
--- a/src/share/vm/classfile/verificationType.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/classfile/verificationType.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -110,34 +110,34 @@ } } -#ifndef PRODUCT - void VerificationType::print_on(outputStream* st) const { switch (_u._data) { - case Bogus: st->print(" bogus "); break; - case Category1: st->print(" category1 "); break; - case Category2: st->print(" category2 "); break; - case Category2_2nd: st->print(" category2_2nd "); break; - case Boolean: st->print(" boolean "); break; - case Byte: st->print(" byte "); break; - case Short: st->print(" short "); break; - case Char: st->print(" char "); break; - case Integer: st->print(" integer "); break; - case Float: st->print(" float "); break; - case Long: st->print(" long "); break; - case Double: st->print(" double "); break; - case Long_2nd: st->print(" long_2nd "); break; - case Double_2nd: st->print(" double_2nd "); break; - case Null: st->print(" null "); break; + case Bogus: st->print("top"); break; + case Category1: st->print("category1"); break; + case Category2: st->print("category2"); break; + case Category2_2nd: st->print("category2_2nd"); break; + case Boolean: st->print("boolean"); break; + case Byte: st->print("byte"); break; + case Short: st->print("short"); break; + case Char: st->print("char"); break; + case Integer: st->print("integer"); break; + case Float: st->print("float"); break; + case Long: st->print("long"); break; + case Double: st->print("double"); break; + case Long_2nd: st->print("long_2nd"); break; + case Double_2nd: st->print("double_2nd"); break; + case Null: st->print("null"); break; + case ReferenceQuery: st->print("reference type"); break; + case Category1Query: st->print("category1 type"); break; + case Category2Query: st->print("category2 type"); break; + case Category2_2ndQuery: st->print("category2_2nd type"); break; default: if (is_uninitialized_this()) { - st->print(" uninitializedThis "); + st->print("uninitializedThis"); } else if (is_uninitialized()) { - st->print(" uninitialized %d ", bci()); + st->print("uninitialized %d", bci()); } else { - st->print(" class %s ", name()->as_klass_external_name()); + name()->print_value_on(st); } } } - -#endif
--- a/src/share/vm/classfile/verificationType.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/classfile/verificationType.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -157,7 +157,7 @@ // For reference types, store the actual Symbol static VerificationType reference_type(Symbol* sh) { - assert(((uintptr_t)sh & 0x3) == 0, "Oops must be aligned"); + assert(((uintptr_t)sh & 0x3) == 0, "Symbols must be aligned"); // If the above assert fails in the future because oop* isn't aligned, // then this type encoding system will have to change to have a tag value // to descriminate between oops and primitives. @@ -303,7 +303,7 @@ return index; } - void print_on(outputStream* st) const PRODUCT_RETURN; + void print_on(outputStream* st) const; private:
--- a/src/share/vm/classfile/verifier.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/classfile/verifier.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -26,9 +26,12 @@ #include "classfile/classFileStream.hpp" #include "classfile/javaClasses.hpp" #include "classfile/stackMapTable.hpp" +#include "classfile/stackMapFrame.hpp" +#include "classfile/stackMapTableFormat.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/verifier.hpp" #include "classfile/vmSymbols.hpp" +#include "interpreter/bytecodes.hpp" #include "interpreter/bytecodeStream.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" @@ -110,8 +113,11 @@ Symbol* exception_name = NULL; const size_t message_buffer_len = klass->name()->utf8_length() + 1024; char* message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len); + char* exception_message = message_buffer; const char* klassName = klass->external_name(); + bool can_failover = FailOverToOldVerifier && + klass->major_version() < NOFAILOVER_MAJOR_VERSION; // If the class should be verified, first see if we can use the split // verifier. If not, or if verification fails and FailOverToOldVerifier @@ -122,27 +128,28 @@ } if (UseSplitVerifier && klass->major_version() >= STACKMAP_ATTRIBUTE_MAJOR_VERSION) { - ClassVerifier split_verifier( - klass, message_buffer, message_buffer_len, THREAD); - split_verifier.verify_class(THREAD); - exception_name = split_verifier.result(); - if (klass->major_version() < NOFAILOVER_MAJOR_VERSION && - FailOverToOldVerifier && !HAS_PENDING_EXCEPTION && + ClassVerifier split_verifier(klass, THREAD); + split_verifier.verify_class(THREAD); + exception_name = split_verifier.result(); + if (can_failover && !HAS_PENDING_EXCEPTION && (exception_name == vmSymbols::java_lang_VerifyError() || exception_name == vmSymbols::java_lang_ClassFormatError())) { - if (TraceClassInitialization) { + if (TraceClassInitialization || VerboseVerification) { tty->print_cr( "Fail over class verification to old verifier for: %s", klassName); } exception_name = inference_verify( klass, message_buffer, message_buffer_len, THREAD); } + if (exception_name != NULL) { + exception_message = split_verifier.exception_message(); + } } else { exception_name = inference_verify( klass, message_buffer, message_buffer_len, THREAD); } - if (TraceClassInitialization) { + if (TraceClassInitialization || VerboseVerification) { if (HAS_PENDING_EXCEPTION) { tty->print("Verification for %s has", klassName); tty->print_cr(" exception pending %s ", @@ -173,7 +180,7 @@ kls = kls->super(); } message_buffer[message_buffer_len - 1] = '\0'; // just to be sure - THROW_MSG_(exception_name, message_buffer, false); + THROW_MSG_(exception_name, exception_message, false); } } @@ -221,7 +228,7 @@ } ResourceMark rm(THREAD); - if (ClassVerifier::_verify_verbose) { + if (VerboseVerification) { tty->print_cr("Verifying class %s with old format", klass->external_name()); } @@ -265,14 +272,252 @@ } } +TypeOrigin TypeOrigin::null() { + return TypeOrigin(); +} +TypeOrigin TypeOrigin::local(u2 index, StackMapFrame* frame) { + assert(frame != NULL, "Must have a frame"); + return TypeOrigin(CF_LOCALS, index, StackMapFrame::copy(frame), + frame->local_at(index)); +} +TypeOrigin TypeOrigin::stack(u2 index, StackMapFrame* frame) { + assert(frame != NULL, "Must have a frame"); + return TypeOrigin(CF_STACK, index, StackMapFrame::copy(frame), + frame->stack_at(index)); +} +TypeOrigin TypeOrigin::sm_local(u2 index, StackMapFrame* frame) { + assert(frame != NULL, "Must have a frame"); + return TypeOrigin(SM_LOCALS, index, StackMapFrame::copy(frame), + frame->local_at(index)); +} +TypeOrigin TypeOrigin::sm_stack(u2 index, StackMapFrame* frame) { + assert(frame != NULL, "Must have a frame"); + return TypeOrigin(SM_STACK, index, StackMapFrame::copy(frame), + frame->stack_at(index)); +} +TypeOrigin TypeOrigin::bad_index(u2 index) { + return TypeOrigin(BAD_INDEX, index, NULL, VerificationType::bogus_type()); +} +TypeOrigin TypeOrigin::cp(u2 index, VerificationType vt) { + return TypeOrigin(CONST_POOL, index, NULL, vt); +} +TypeOrigin TypeOrigin::signature(VerificationType vt) { + return TypeOrigin(SIG, 0, NULL, vt); +} +TypeOrigin TypeOrigin::implicit(VerificationType t) { + return TypeOrigin(IMPLICIT, 0, NULL, t); +} +TypeOrigin TypeOrigin::frame(StackMapFrame* frame) { + return TypeOrigin(FRAME_ONLY, 0, StackMapFrame::copy(frame), + VerificationType::bogus_type()); +} + +void TypeOrigin::reset_frame() { + if (_frame != NULL) { + _frame->restore(); + } +} + +void TypeOrigin::details(outputStream* ss) const { + _type.print_on(ss); + switch (_origin) { + case CF_LOCALS: + ss->print(" (current frame, locals[%d])", _index); + break; + case CF_STACK: + ss->print(" (current frame, stack[%d])", _index); + break; + case SM_LOCALS: + ss->print(" (stack map, locals[%d])", _index); + break; + case SM_STACK: + ss->print(" (stack map, stack[%d])", _index); + break; + case CONST_POOL: + ss->print(" (constant pool %d)", _index); + break; + case SIG: + ss->print(" (from method signature)"); + break; + case IMPLICIT: + case FRAME_ONLY: + case NONE: + default: + ; + } +} + +#ifdef ASSERT +void TypeOrigin::print_on(outputStream* str) const { + str->print("{%d,%d,%p:", _origin, _index, _frame); + if (_frame != NULL) { + _frame->print_on(str); + } else { + str->print("null"); + } + str->print(","); + _type.print_on(str); + str->print("}"); +} +#endif + +void ErrorContext::details(outputStream* ss, methodOop method) const { + if (is_valid()) { + ss->print_cr(""); + ss->print_cr("Exception Details:"); + location_details(ss, method); + reason_details(ss); + frame_details(ss); + bytecode_details(ss, method); + handler_details(ss, method); + stackmap_details(ss, method); + } +} + +void ErrorContext::reason_details(outputStream* ss) const { + streamIndentor si(ss); + ss->indent().print_cr("Reason:"); + streamIndentor si2(ss); + ss->indent().print(""); + switch (_fault) { + case INVALID_BYTECODE: + ss->print("Error exists in the bytecode"); + break; + case WRONG_TYPE: + if (_expected.is_valid()) { + ss->print("Type "); + _type.details(ss); + ss->print(" is not assignable to "); + _expected.details(ss); + } else { + ss->print("Invalid type: "); + _type.details(ss); + } + break; + case FLAGS_MISMATCH: + if (_expected.is_valid()) { + ss->print("Current frame's flags are not assignable " + "to stack map frame's."); + } else { + ss->print("Current frame's flags are invalid in this context."); + } + break; + case BAD_CP_INDEX: + ss->print("Constant pool index %d is invalid", _type.index()); + break; + case BAD_LOCAL_INDEX: + ss->print("Local index %d is invalid", _type.index()); + break; + case LOCALS_SIZE_MISMATCH: + ss->print("Current frame's local size doesn't match stackmap."); + break; + case STACK_SIZE_MISMATCH: + ss->print("Current frame's stack size doesn't match stackmap."); + break; + case STACK_OVERFLOW: + ss->print("Exceeded max stack size."); + break; + case STACK_UNDERFLOW: + ss->print("Attempt to pop empty stack."); + break; + case MISSING_STACKMAP: + ss->print("Expected stackmap frame at this location."); + break; + case BAD_STACKMAP: + ss->print("Invalid stackmap specification."); + break; + case UNKNOWN: + default: + ShouldNotReachHere(); + ss->print_cr("Unknown"); + } + ss->print_cr(""); +} + +void ErrorContext::location_details(outputStream* ss, methodOop method) const { + if (_bci != -1 && method != NULL) { + streamIndentor si(ss); + const char* bytecode_name = "<invalid>"; + if (method->validate_bci_from_bcx(_bci) != -1) { + Bytecodes::Code code = Bytecodes::code_or_bp_at(method->bcp_from(_bci)); + if (Bytecodes::is_defined(code)) { + bytecode_name = Bytecodes::name(code); + } else { + bytecode_name = "<illegal>"; + } + } + instanceKlass* ik = instanceKlass::cast(method->method_holder()); + ss->indent().print_cr("Location:"); + streamIndentor si2(ss); + ss->indent().print_cr("%s.%s%s @%d: %s", + ik->name()->as_C_string(), method->name()->as_C_string(), + method->signature()->as_C_string(), _bci, bytecode_name); + } +} + +void ErrorContext::frame_details(outputStream* ss) const { + streamIndentor si(ss); + if (_type.is_valid() && _type.frame() != NULL) { + ss->indent().print_cr("Current Frame:"); + streamIndentor si2(ss); + _type.frame()->print_on(ss); + } + if (_expected.is_valid() && _expected.frame() != NULL) { + ss->indent().print_cr("Stackmap Frame:"); + streamIndentor si2(ss); + _expected.frame()->print_on(ss); + } +} + +void ErrorContext::bytecode_details(outputStream* ss, methodOop method) const { + if (method != NULL) { + streamIndentor si(ss); + ss->indent().print_cr("Bytecode:"); + streamIndentor si2(ss); + ss->print_data(method->code_base(), method->code_size(), false); + } +} + +void ErrorContext::handler_details(outputStream* ss, methodOop method) const { + if (method != NULL) { + streamIndentor si(ss); + ExceptionTable table(method); + if (table.length() > 0) { + ss->indent().print_cr("Exception Handler Table:"); + streamIndentor si2(ss); + for (int i = 0; i < table.length(); ++i) { + ss->indent().print_cr("bci [%d, %d] => handler: %d", table.start_pc(i), + table.end_pc(i), table.handler_pc(i)); + } + } + } +} + +void ErrorContext::stackmap_details(outputStream* ss, methodOop method) const { + if (method != NULL && method->has_stackmap_table()) { + streamIndentor si(ss); + ss->indent().print_cr("Stackmap Table:"); + typeArrayOop data = method->stackmap_data(); + stack_map_table* sm_table = + stack_map_table::at((address)data->byte_at_addr(0)); + stack_map_frame* sm_frame = sm_table->entries(); + streamIndentor si2(ss); + int current_offset = -1; + for (u2 i = 0; i < sm_table->number_of_entries(); ++i) { + ss->indent(); + sm_frame->print_on(ss, current_offset); + ss->print_cr(""); + current_offset += sm_frame->offset_delta(); + sm_frame = sm_frame->next(); + } + } +} + // Methods in ClassVerifier -bool ClassVerifier::_verify_verbose = false; - ClassVerifier::ClassVerifier( - instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS) - : _thread(THREAD), _exception_type(NULL), _message(msg), - _message_buffer_len(msg_len), _klass(klass) { + instanceKlassHandle klass, TRAPS) + : _thread(THREAD), _exception_type(NULL), _message(NULL), _klass(klass) { _this_type = VerificationType::reference_type(klass->name()); // Create list to hold symbols in reference area. _symbols = new GrowableArray<Symbol*>(100, 0, NULL); @@ -290,8 +535,14 @@ return VerificationType::reference_type(vmSymbols::java_lang_Object()); } +TypeOrigin ClassVerifier::ref_ctx(const char* sig, TRAPS) { + VerificationType vt = VerificationType::reference_type( + create_temporary_symbol(sig, (int)strlen(sig), THREAD)); + return TypeOrigin::implicit(vt); +} + void ClassVerifier::verify_class(TRAPS) { - if (_verify_verbose) { + if (VerboseVerification) { tty->print_cr("Verifying class %s with new format", _klass->external_name()); } @@ -312,7 +563,7 @@ verify_method(methodHandle(THREAD, m), CHECK_VERIFY(this)); } - if (_verify_verbose || TraceClassInitialization) { + if (VerboseVerification || TraceClassInitialization) { if (was_recursively_verified()) tty->print_cr("Recursive verification detected for: %s", _klass->external_name()); @@ -321,7 +572,7 @@ void ClassVerifier::verify_method(methodHandle m, TRAPS) { _method = m; // initialize _method - if (_verify_verbose) { + if (VerboseVerification) { tty->print_cr("Verifying method %s", m->name_and_sig_as_C_string()); } @@ -368,8 +619,8 @@ StackMapTable stackmap_table(&reader, ¤t_frame, max_locals, max_stack, code_data, code_length, CHECK_VERIFY(this)); - if (_verify_verbose) { - stackmap_table.print(); + if (VerboseVerification) { + stackmap_table.print_on(tty); } RawBytecodeStream bcs(m); @@ -388,6 +639,7 @@ // Set current frame's offset to bci current_frame.set_offset(bci); + current_frame.set_mark(); // Make sure every offset in stackmap table point to the beginning to // an instruction. Match current_frame to stackmap_table entry with @@ -396,6 +648,7 @@ stackmap_index, bci, ¤t_frame, &stackmap_table, no_control_flow, CHECK_VERIFY(this)); + bool this_uninit = false; // Set to true when invokespecial <init> initialized 'this' // Merge with the next instruction @@ -406,8 +659,8 @@ VerificationType atype; #ifndef PRODUCT - if (_verify_verbose) { - current_frame.print(); + if (VerboseVerification) { + current_frame.print_on(tty); tty->print_cr("offset = %d, opcode = %s", bci, Bytecodes::name(opcode)); } #endif @@ -420,7 +673,10 @@ opcode != Bytecodes::_lstore && opcode != Bytecodes::_fload && opcode != Bytecodes::_dload && opcode != Bytecodes::_fstore && opcode != Bytecodes::_dstore) { - verify_error(bci, "Bad wide instruction"); + /* Unreachable? RawBytecodeStream's raw_next() returns 'illegal' + * if we encounter a wide instruction that modifies an invalid + * opcode (not one of the ones listed above) */ + verify_error(ErrorContext::bad_code(bci), "Bad wide instruction"); return; } } @@ -532,7 +788,9 @@ atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_int_array()) { - verify_error(bci, bad_type_msg, "iaload"); + verify_error(ErrorContext::bad_type(bci, + current_frame.stack_top_ctx(), ref_ctx("[I", THREAD)), + bad_type_msg, "iaload"); return; } current_frame.push_stack( @@ -544,7 +802,9 @@ atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_bool_array() && !atype.is_byte_array()) { - verify_error(bci, bad_type_msg, "baload"); + verify_error( + ErrorContext::bad_type(bci, current_frame.stack_top_ctx()), + bad_type_msg, "baload"); return; } current_frame.push_stack( @@ -556,7 +816,9 @@ atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_char_array()) { - verify_error(bci, bad_type_msg, "caload"); + verify_error(ErrorContext::bad_type(bci, + current_frame.stack_top_ctx(), ref_ctx("[C", THREAD)), + bad_type_msg, "caload"); return; } current_frame.push_stack( @@ -568,7 +830,9 @@ atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_short_array()) { - verify_error(bci, bad_type_msg, "saload"); + verify_error(ErrorContext::bad_type(bci, + current_frame.stack_top_ctx(), ref_ctx("[S", THREAD)), + bad_type_msg, "saload"); return; } current_frame.push_stack( @@ -580,7 +844,9 @@ atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_long_array()) { - verify_error(bci, bad_type_msg, "laload"); + verify_error(ErrorContext::bad_type(bci, + current_frame.stack_top_ctx(), ref_ctx("[J", THREAD)), + bad_type_msg, "laload"); return; } current_frame.push_stack_2( @@ -593,7 +859,9 @@ atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_float_array()) { - verify_error(bci, bad_type_msg, "faload"); + verify_error(ErrorContext::bad_type(bci, + current_frame.stack_top_ctx(), ref_ctx("[F", THREAD)), + bad_type_msg, "faload"); return; } current_frame.push_stack( @@ -605,7 +873,9 @@ atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_double_array()) { - verify_error(bci, bad_type_msg, "daload"); + verify_error(ErrorContext::bad_type(bci, + current_frame.stack_top_ctx(), ref_ctx("[D", THREAD)), + bad_type_msg, "daload"); return; } current_frame.push_stack_2( @@ -618,7 +888,10 @@ atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_reference_array()) { - verify_error(bci, bad_type_msg, "aaload"); + verify_error(ErrorContext::bad_type(bci, + current_frame.stack_top_ctx(), + TypeOrigin::implicit(VerificationType::reference_check())), + bad_type_msg, "aaload"); return; } if (atype.is_null()) { @@ -689,7 +962,9 @@ atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_int_array()) { - verify_error(bci, bad_type_msg, "iastore"); + verify_error(ErrorContext::bad_type(bci, + current_frame.stack_top_ctx(), ref_ctx("[I", THREAD)), + bad_type_msg, "iastore"); return; } no_control_flow = false; break; @@ -701,7 +976,9 @@ atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_bool_array() && !atype.is_byte_array()) { - verify_error(bci, bad_type_msg, "bastore"); + verify_error( + ErrorContext::bad_type(bci, current_frame.stack_top_ctx()), + bad_type_msg, "bastore"); return; } no_control_flow = false; break; @@ -713,7 +990,9 @@ atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_char_array()) { - verify_error(bci, bad_type_msg, "castore"); + verify_error(ErrorContext::bad_type(bci, + current_frame.stack_top_ctx(), ref_ctx("[C", THREAD)), + bad_type_msg, "castore"); return; } no_control_flow = false; break; @@ -725,7 +1004,9 @@ atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_short_array()) { - verify_error(bci, bad_type_msg, "sastore"); + verify_error(ErrorContext::bad_type(bci, + current_frame.stack_top_ctx(), ref_ctx("[S", THREAD)), + bad_type_msg, "sastore"); return; } no_control_flow = false; break; @@ -738,7 +1019,9 @@ atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_long_array()) { - verify_error(bci, bad_type_msg, "lastore"); + verify_error(ErrorContext::bad_type(bci, + current_frame.stack_top_ctx(), ref_ctx("[J", THREAD)), + bad_type_msg, "lastore"); return; } no_control_flow = false; break; @@ -750,7 +1033,9 @@ atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_float_array()) { - verify_error(bci, bad_type_msg, "fastore"); + verify_error(ErrorContext::bad_type(bci, + current_frame.stack_top_ctx(), ref_ctx("[F", THREAD)), + bad_type_msg, "fastore"); return; } no_control_flow = false; break; @@ -763,7 +1048,9 @@ atype = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_double_array()) { - verify_error(bci, bad_type_msg, "dastore"); + verify_error(ErrorContext::bad_type(bci, + current_frame.stack_top_ctx(), ref_ctx("[D", THREAD)), + bad_type_msg, "dastore"); return; } no_control_flow = false; break; @@ -775,7 +1062,10 @@ VerificationType::reference_check(), CHECK_VERIFY(this)); // more type-checking is done at runtime if (!atype.is_reference_array()) { - verify_error(bci, bad_type_msg, "aastore"); + verify_error(ErrorContext::bad_type(bci, + current_frame.stack_top_ctx(), + TypeOrigin::implicit(VerificationType::reference_check())), + bad_type_msg, "aastore"); return; } // 4938384: relaxed constraint in JVMS 3nd edition. @@ -793,7 +1083,11 @@ current_frame.pop_stack( VerificationType::category2_check(), CHECK_VERIFY(this)); } else { - verify_error(bci, bad_type_msg, "pop2"); + /* Unreachable? Would need a category2_1st on TOS + * which does not appear possible. */ + verify_error( + ErrorContext::bad_type(bci, current_frame.stack_top_ctx()), + bad_type_msg, "pop2"); return; } no_control_flow = false; break; @@ -825,7 +1119,10 @@ type3 = current_frame.pop_stack( VerificationType::category2_check(), CHECK_VERIFY(this)); } else { - verify_error(bci, bad_type_msg, "dup_x2"); + /* Unreachable? Would need a category2_1st at stack depth 2 with + * a category1 on TOS which does not appear possible. */ + verify_error(ErrorContext::bad_type( + bci, current_frame.stack_top_ctx()), bad_type_msg, "dup_x2"); return; } current_frame.push_stack(type, CHECK_VERIFY(this)); @@ -843,7 +1140,11 @@ type2 = current_frame.pop_stack( VerificationType::category2_check(), CHECK_VERIFY(this)); } else { - verify_error(bci, bad_type_msg, "dup2"); + /* Unreachable? Would need a category2_1st on TOS which does not + * appear possible. */ + verify_error( + ErrorContext::bad_type(bci, current_frame.stack_top_ctx()), + bad_type_msg, "dup2"); return; } current_frame.push_stack(type2, CHECK_VERIFY(this)); @@ -858,11 +1159,15 @@ if (type.is_category1()) { type2 = current_frame.pop_stack( VerificationType::category1_check(), CHECK_VERIFY(this)); - } else if(type.is_category2_2nd()) { - type2 = current_frame.pop_stack - (VerificationType::category2_check(), CHECK_VERIFY(this)); + } else if (type.is_category2_2nd()) { + type2 = current_frame.pop_stack( + VerificationType::category2_check(), CHECK_VERIFY(this)); } else { - verify_error(bci, bad_type_msg, "dup2_x1"); + /* Unreachable? Would need a category2_1st on TOS which does + * not appear possible. */ + verify_error( + ErrorContext::bad_type(bci, current_frame.stack_top_ctx()), + bad_type_msg, "dup2_x1"); return; } type3 = current_frame.pop_stack( @@ -885,7 +1190,11 @@ type2 = current_frame.pop_stack( VerificationType::category2_check(), CHECK_VERIFY(this)); } else { - verify_error(bci, bad_type_msg, "dup2_x2"); + /* Unreachable? Would need a category2_1st on TOS which does + * not appear possible. */ + verify_error( + ErrorContext::bad_type(bci, current_frame.stack_top_ctx()), + bad_type_msg, "dup2_x2"); return; } type3 = current_frame.pop_stack(CHECK_VERIFY(this)); @@ -896,7 +1205,12 @@ type4 = current_frame.pop_stack( VerificationType::category2_check(), CHECK_VERIFY(this)); } else { - verify_error(bci, bad_type_msg, "dup2_x2"); + /* Unreachable? Would need a category2_1st on TOS after popping + * a long/double or two category 1's, which does not + * appear possible. */ + verify_error( + ErrorContext::bad_type(bci, current_frame.stack_top_ctx()), + bad_type_msg, "dup2_x2"); return; } current_frame.push_stack(type2, CHECK_VERIFY(this)); @@ -1176,43 +1490,50 @@ case Bytecodes::_ireturn : type = current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); - verify_return_value(return_type, type, bci, CHECK_VERIFY(this)); + verify_return_value(return_type, type, bci, + ¤t_frame, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_lreturn : type2 = current_frame.pop_stack( VerificationType::long2_type(), CHECK_VERIFY(this)); type = current_frame.pop_stack( VerificationType::long_type(), CHECK_VERIFY(this)); - verify_return_value(return_type, type, bci, CHECK_VERIFY(this)); + verify_return_value(return_type, type, bci, + ¤t_frame, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_freturn : type = current_frame.pop_stack( VerificationType::float_type(), CHECK_VERIFY(this)); - verify_return_value(return_type, type, bci, CHECK_VERIFY(this)); + verify_return_value(return_type, type, bci, + ¤t_frame, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_dreturn : type2 = current_frame.pop_stack( VerificationType::double2_type(), CHECK_VERIFY(this)); type = current_frame.pop_stack( VerificationType::double_type(), CHECK_VERIFY(this)); - verify_return_value(return_type, type, bci, CHECK_VERIFY(this)); + verify_return_value(return_type, type, bci, + ¤t_frame, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_areturn : type = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); - verify_return_value(return_type, type, bci, CHECK_VERIFY(this)); + verify_return_value(return_type, type, bci, + ¤t_frame, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_return : if (return_type != VerificationType::bogus_type()) { - verify_error(bci, "Method expects no return value"); + verify_error(ErrorContext::bad_code(bci), + "Method expects a return value"); return; } // Make sure "this" has been initialized if current method is an // <init> if (_method->name() == vmSymbols::object_initializer_name() && current_frame.flag_this_uninit()) { - verify_error(bci, - "Constructor must call super() or this() before return"); + verify_error(ErrorContext::bad_code(bci), + "Constructor must call super() or this() " + "before return"); return; } no_control_flow = true; break; @@ -1239,11 +1560,13 @@ case Bytecodes::_new : { index = bcs.get_index_u2(); - verify_cp_class_type(index, cp, CHECK_VERIFY(this)); + verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); VerificationType new_class_type = cp_index_to_type(index, cp, CHECK_VERIFY(this)); if (!new_class_type.is_object()) { - verify_error(bci, "Illegal new instruction"); + verify_error(ErrorContext::bad_type(bci, + TypeOrigin::cp(index, new_class_type)), + "Illegal new instruction"); return; } type = VerificationType::uninitialized_type(bci); @@ -1258,13 +1581,15 @@ no_control_flow = false; break; case Bytecodes::_anewarray : verify_anewarray( - bcs.get_index_u2(), cp, ¤t_frame, CHECK_VERIFY(this)); + bci, bcs.get_index_u2(), cp, ¤t_frame, CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_arraylength : type = current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); if (!(type.is_null() || type.is_array())) { - verify_error(bci, bad_type_msg, "arraylength"); + verify_error(ErrorContext::bad_type( + bci, current_frame.stack_top_ctx()), + bad_type_msg, "arraylength"); } current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); @@ -1272,7 +1597,7 @@ case Bytecodes::_checkcast : { index = bcs.get_index_u2(); - verify_cp_class_type(index, cp, CHECK_VERIFY(this)); + verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); current_frame.pop_stack(object_type(), CHECK_VERIFY(this)); VerificationType klass_type = cp_index_to_type( index, cp, CHECK_VERIFY(this)); @@ -1281,7 +1606,7 @@ } case Bytecodes::_instanceof : { index = bcs.get_index_u2(); - verify_cp_class_type(index, cp, CHECK_VERIFY(this)); + verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); current_frame.pop_stack(object_type(), CHECK_VERIFY(this)); current_frame.push_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); @@ -1296,17 +1621,18 @@ { index = bcs.get_index_u2(); u2 dim = *(bcs.bcp()+3); - verify_cp_class_type(index, cp, CHECK_VERIFY(this)); + verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); VerificationType new_array_type = cp_index_to_type(index, cp, CHECK_VERIFY(this)); if (!new_array_type.is_array()) { - verify_error(bci, - "Illegal constant pool index in multianewarray instruction"); + verify_error(ErrorContext::bad_type(bci, + TypeOrigin::cp(index, new_array_type)), + "Illegal constant pool index in multianewarray instruction"); return; } if (dim < 1 || new_array_type.dimensions() < dim) { - verify_error(bci, - "Illegal dimension in multianewarray instruction"); + verify_error(ErrorContext::bad_code(bci), + "Illegal dimension in multianewarray instruction: %d", dim); return; } for (int i = 0; i < dim; i++) { @@ -1324,7 +1650,8 @@ default: // We only need to check the valid bytecodes in class file. // And jsr and ret are not in the new class file format in JDK1.5. - verify_error(bci, "Bad instruction"); + verify_error(ErrorContext::bad_code(bci), + "Bad instruction: %02x", opcode); no_control_flow = false; return; } // end switch @@ -1340,7 +1667,8 @@ // Make sure that control flow does not fall through end of the method if (!no_control_flow) { - verify_error(code_length, "Control flow falls through code end"); + verify_error(ErrorContext::bad_code(code_length), + "Control flow falls through code end"); return; } } @@ -1359,7 +1687,7 @@ code_data[bci] = BYTECODE_OFFSET; } } else { - verify_error(bcs.bci(), "Bad instruction"); + verify_error(ErrorContext::bad_code(bcs.bci()), "Bad instruction"); return NULL; } } @@ -1402,9 +1730,11 @@ catch_type, this, CHECK_VERIFY(this)); if (!is_subclass) { // 4286534: should throw VerifyError according to recent spec change - verify_error( - "Catch type is not a subclass of Throwable in handler %d", - handler_pc); + verify_error(ErrorContext::bad_type(handler_pc, + TypeOrigin::cp(catch_type_index, catch_type), + TypeOrigin::implicit(throwable)), + "Catch type is not a subclass " + "of Throwable in exception handler %d", handler_pc); return; } } @@ -1444,19 +1774,21 @@ if (stackmap_index < stackmap_table->get_frame_count()) { u2 this_offset = stackmap_table->get_offset(stackmap_index); if (no_control_flow && this_offset > bci) { - verify_error(bci, "Expecting a stack map frame"); + verify_error(ErrorContext::missing_stackmap(bci), + "Expecting a stack map frame"); return 0; } if (this_offset == bci) { + ErrorContext ctx; // See if current stack map can be assigned to the frame in table. // current_frame is the stackmap frame got from the last instruction. // If matched, current_frame will be updated by this method. - bool match = stackmap_table->match_stackmap( + bool matches = stackmap_table->match_stackmap( current_frame, this_offset, stackmap_index, - !no_control_flow, true, CHECK_VERIFY_(this, 0)); - if (!match) { + !no_control_flow, true, &ctx, CHECK_VERIFY_(this, 0)); + if (!matches) { // report type error - verify_error(bci, "Instruction type does not match stack map"); + verify_error(ctx, "Instruction type does not match stack map"); return 0; } stackmap_index++; @@ -1466,7 +1798,7 @@ return 0; } } else if (no_control_flow) { - verify_error(bci, "Expecting a stack map frame"); + verify_error(ErrorContext::bad_code(bci), "Expecting a stack map frame"); return 0; } return stackmap_index; @@ -1498,29 +1830,31 @@ VerificationType::reference_type(vmSymbols::java_lang_Throwable()); new_frame->push_stack(throwable, CHECK_VERIFY(this)); } - bool match = stackmap_table->match_stackmap( - new_frame, handler_pc, true, false, CHECK_VERIFY(this)); - if (!match) { - verify_error(bci, - "Stack map does not match the one at exception handler %d", - handler_pc); + ErrorContext ctx; + bool matches = stackmap_table->match_stackmap( + new_frame, handler_pc, true, false, &ctx, CHECK_VERIFY(this)); + if (!matches) { + verify_error(ctx, "Stack map does not match the one at " + "exception handler %d", handler_pc); return; } } } } -void ClassVerifier::verify_cp_index(constantPoolHandle cp, int index, TRAPS) { +void ClassVerifier::verify_cp_index( + u2 bci, constantPoolHandle cp, int index, TRAPS) { int nconstants = cp->length(); if ((index <= 0) || (index >= nconstants)) { - verify_error("Illegal constant pool index %d in class %s", - index, instanceKlass::cast(cp->pool_holder())->external_name()); + verify_error(ErrorContext::bad_cp_index(bci, index), + "Illegal constant pool index %d in class %s", + index, instanceKlass::cast(cp->pool_holder())->external_name()); return; } } void ClassVerifier::verify_cp_type( - int index, constantPoolHandle cp, unsigned int types, TRAPS) { + u2 bci, int index, constantPoolHandle cp, unsigned int types, TRAPS) { // In some situations, bytecode rewriting may occur while we're verifying. // In this case, a constant pool cache exists and some indices refer to that @@ -1528,10 +1862,10 @@ // We must check was_recursively_verified() before we get here. guarantee(cp->cache() == NULL, "not rewritten yet"); - verify_cp_index(cp, index, CHECK_VERIFY(this)); + verify_cp_index(bci, cp, index, CHECK_VERIFY(this)); unsigned int tag = cp->tag_at(index).value(); if ((types & (1 << tag)) == 0) { - verify_error( + verify_error(ErrorContext::bad_cp_index(bci, index), "Illegal type at constant pool entry %d in class %s", index, instanceKlass::cast(cp->pool_holder())->external_name()); return; @@ -1539,51 +1873,46 @@ } void ClassVerifier::verify_cp_class_type( - int index, constantPoolHandle cp, TRAPS) { - verify_cp_index(cp, index, CHECK_VERIFY(this)); + u2 bci, int index, constantPoolHandle cp, TRAPS) { + verify_cp_index(bci, cp, index, CHECK_VERIFY(this)); constantTag tag = cp->tag_at(index); if (!tag.is_klass() && !tag.is_unresolved_klass()) { - verify_error("Illegal type at constant pool entry %d in class %s", - index, instanceKlass::cast(cp->pool_holder())->external_name()); + verify_error(ErrorContext::bad_cp_index(bci, index), + "Illegal type at constant pool entry %d in class %s", + index, instanceKlass::cast(cp->pool_holder())->external_name()); return; } } -void ClassVerifier::format_error_message( - const char* fmt, int offset, va_list va) { - ResourceMark rm(_thread); - stringStream message(_message, _message_buffer_len); - message.vprint(fmt, va); - if (!_method.is_null()) { - message.print(" in method %s", _method->name_and_sig_as_C_string()); - } - if (offset != -1) { - message.print(" at offset %d", offset); - } -} +void ClassVerifier::verify_error(ErrorContext ctx, const char* msg, ...) { + stringStream ss; -void ClassVerifier::verify_error(u2 offset, const char* fmt, ...) { + ctx.reset_frames(); _exception_type = vmSymbols::java_lang_VerifyError(); + _error_context = ctx; va_list va; - va_start(va, fmt); - format_error_message(fmt, offset, va); + va_start(va, msg); + ss.vprint(msg, va); va_end(va); -} - -void ClassVerifier::verify_error(const char* fmt, ...) { - _exception_type = vmSymbols::java_lang_VerifyError(); - va_list va; - va_start(va, fmt); - format_error_message(fmt, -1, va); - va_end(va); + _message = ss.as_string(); +#ifdef ASSERT + ResourceMark rm; + const char* exception_name = _exception_type->as_C_string(); + Exceptions::debug_check_abort(exception_name, NULL); +#endif // ndef ASSERT } void ClassVerifier::class_format_error(const char* msg, ...) { + stringStream ss; _exception_type = vmSymbols::java_lang_ClassFormatError(); va_list va; va_start(va, msg); - format_error_message(msg, -1, va); + ss.vprint(msg, va); va_end(va); + if (!_method.is_null()) { + ss.print(" in method %s", _method->name_and_sig_as_C_string()); + } + _message = ss.as_string(); } klassOop ClassVerifier::load_class(Symbol* name, TRAPS) { @@ -1619,7 +1948,7 @@ } } else { klassOop member_klass = target_instance->find_field(field_name, field_sig, &fd); - if(member_klass != NULL && fd.is_protected()) { + if (member_klass != NULL && fd.is_protected()) { if (!this_class->is_same_class_package(member_klass)) { return true; } @@ -1629,9 +1958,9 @@ } void ClassVerifier::verify_ldc( - int opcode, u2 index, StackMapFrame *current_frame, - constantPoolHandle cp, u2 bci, TRAPS) { - verify_cp_index(cp, index, CHECK_VERIFY(this)); + int opcode, u2 index, StackMapFrame* current_frame, + constantPoolHandle cp, u2 bci, TRAPS) { + verify_cp_index(bci, cp, index, CHECK_VERIFY(this)); constantTag tag = cp->tag_at(index); unsigned int types; if (opcode == Bytecodes::_ldc || opcode == Bytecodes::_ldc_w) { @@ -1641,12 +1970,12 @@ | (1 << JVM_CONSTANT_MethodHandle) | (1 << JVM_CONSTANT_MethodType); // Note: The class file parser already verified the legality of // MethodHandle and MethodType constants. - verify_cp_type(index, cp, types, CHECK_VERIFY(this)); + verify_cp_type(bci, index, cp, types, CHECK_VERIFY(this)); } } else { assert(opcode == Bytecodes::_ldc2_w, "must be ldc2_w"); types = (1 << JVM_CONSTANT_Double) | (1 << JVM_CONSTANT_Long); - verify_cp_type(index, cp, types, CHECK_VERIFY(this)); + verify_cp_type(bci, index, cp, types, CHECK_VERIFY(this)); } if (tag.is_string() && cp->is_pseudo_string_at(index)) { current_frame->push_stack(object_type(), CHECK_VERIFY(this)); @@ -1681,7 +2010,9 @@ VerificationType::reference_type( vmSymbols::java_lang_invoke_MethodType()), CHECK_VERIFY(this)); } else { - verify_error(bci, "Invalid index in ldc"); + /* Unreachable? verify_cp_type has already validated the cp type. */ + verify_error( + ErrorContext::bad_cp_index(bci, index), "Invalid index in ldc"); return; } } @@ -1697,7 +2028,8 @@ u2 padding_offset = 1; while ((bcp + padding_offset) < aligned_bcp) { if(*(bcp + padding_offset) != 0) { - verify_error(bci, "Nonzero padding byte in lookswitch or tableswitch"); + verify_error(ErrorContext::bad_code(bci), + "Nonzero padding byte in lookswitch or tableswitch"); return; } padding_offset++; @@ -1710,20 +2042,21 @@ jint low = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize); jint high = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize); if (low > high) { - verify_error(bci, - "low must be less than or equal to high in tableswitch"); + verify_error(ErrorContext::bad_code(bci), + "low must be less than or equal to high in tableswitch"); return; } keys = high - low + 1; if (keys < 0) { - verify_error(bci, "too many keys in tableswitch"); + verify_error(ErrorContext::bad_code(bci), "too many keys in tableswitch"); return; } delta = 1; } else { keys = (int)Bytes::get_Java_u4(aligned_bcp + jintSize); if (keys < 0) { - verify_error(bci, "number of keys in lookupswitch less than 0"); + verify_error(ErrorContext::bad_code(bci), + "number of keys in lookupswitch less than 0"); return; } delta = 2; @@ -1732,7 +2065,8 @@ jint this_key = Bytes::get_Java_u4(aligned_bcp + (2+2*i)*jintSize); jint next_key = Bytes::get_Java_u4(aligned_bcp + (2+2*i+2)*jintSize); if (this_key >= next_key) { - verify_error(bci, "Bad lookupswitch instruction"); + verify_error(ErrorContext::bad_code(bci), + "Bad lookupswitch instruction"); return; } } @@ -1767,7 +2101,8 @@ constantPoolHandle cp, TRAPS) { u2 index = bcs->get_index_u2(); - verify_cp_type(index, cp, 1 << JVM_CONSTANT_Fieldref, CHECK_VERIFY(this)); + verify_cp_type(bcs->bci(), index, cp, + 1 << JVM_CONSTANT_Fieldref, CHECK_VERIFY(this)); // Get field name and signature Symbol* field_name = cp->name_ref_at(index); @@ -1784,9 +2119,11 @@ VerificationType ref_class_type = cp_ref_index_to_type( index, cp, CHECK_VERIFY(this)); if (!ref_class_type.is_object()) { - verify_error( - "Expecting reference to class in class %s at constant pool index %d", - _klass->external_name(), index); + /* Unreachable? Class file parser verifies Fieldref contents */ + verify_error(ErrorContext::bad_type(bcs->bci(), + TypeOrigin::cp(index, ref_class_type)), + "Expecting reference to class in class %s at constant pool index %d", + _klass->external_name(), index); return; } VerificationType target_class_type = ref_class_type; @@ -1844,7 +2181,10 @@ is_assignable = target_class_type.is_assignable_from( stack_object_type, this, CHECK_VERIFY(this)); if (!is_assignable) { - verify_error(bci, "Bad type on operand stack in putfield"); + verify_error(ErrorContext::bad_type(bci, + current_frame->stack_top_ctx(), + TypeOrigin::cp(index, target_class_type)), + "Bad type on operand stack in putfield"); return; } } @@ -1868,7 +2208,10 @@ is_assignable = current_type().is_assignable_from( stack_object_type, this, CHECK_VERIFY(this)); if (!is_assignable) { - verify_error(bci, "Bad access to protected data in getfield"); + verify_error(ErrorContext::bad_type(bci, + current_frame->stack_top_ctx(), + TypeOrigin::implicit(current_type())), + "Bad access to protected data in getfield"); return; } } @@ -1879,7 +2222,7 @@ } void ClassVerifier::verify_invoke_init( - RawBytecodeStream* bcs, VerificationType ref_class_type, + RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type, StackMapFrame* current_frame, u4 code_length, bool *this_uninit, constantPoolHandle cp, TRAPS) { u2 bci = bcs->bci(); @@ -1890,7 +2233,10 @@ klassOop superk = current_class()->super(); if (ref_class_type.name() != current_class()->name() && ref_class_type.name() != superk->klass_part()->name()) { - verify_error(bci, "Bad <init> method call"); + verify_error(ErrorContext::bad_type(bci, + TypeOrigin::implicit(ref_class_type), + TypeOrigin::implicit(current_type())), + "Bad <init> method call"); return; } current_frame->initialize_object(type, current_type()); @@ -1899,17 +2245,23 @@ u2 new_offset = type.bci(); address new_bcp = bcs->bcp() - bci + new_offset; if (new_offset > (code_length - 3) || (*new_bcp) != Bytecodes::_new) { - verify_error(new_offset, "Expecting new instruction"); + /* Unreachable? Stack map parsing ensures valid type and new + * instructions have a valid BCI. */ + verify_error(ErrorContext::bad_code(new_offset), + "Expecting new instruction"); return; } u2 new_class_index = Bytes::get_Java_u2(new_bcp + 1); - verify_cp_class_type(new_class_index, cp, CHECK_VERIFY(this)); + verify_cp_class_type(bci, new_class_index, cp, CHECK_VERIFY(this)); // The method must be an <init> method of the indicated class VerificationType new_class_type = cp_index_to_type( new_class_index, cp, CHECK_VERIFY(this)); if (!new_class_type.equals(ref_class_type)) { - verify_error(bci, "Call to wrong <init> method"); + verify_error(ErrorContext::bad_type(bci, + TypeOrigin::cp(new_class_index, new_class_type), + TypeOrigin::cp(ref_class_index, ref_class_type)), + "Call to wrong <init> method"); return; } // According to the VM spec, if the referent class is a superclass of the @@ -1928,14 +2280,18 @@ bool assignable = current_type().is_assignable_from( objectref_type, this, CHECK_VERIFY(this)); if (!assignable) { - verify_error(bci, "Bad access to protected <init> method"); + verify_error(ErrorContext::bad_type(bci, + TypeOrigin::cp(new_class_index, objectref_type), + TypeOrigin::implicit(current_type())), + "Bad access to protected <init> method"); return; } } } current_frame->initialize_object(type, new_class_type); } else { - verify_error(bci, "Bad operand type when invoking <init>"); + verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx()), + "Bad operand type when invoking <init>"); return; } } @@ -1952,7 +2308,7 @@ : opcode == Bytecodes::_invokedynamic ? 1 << JVM_CONSTANT_InvokeDynamic : 1 << JVM_CONSTANT_Methodref); - verify_cp_type(index, cp, types, CHECK_VERIFY(this)); + verify_cp_type(bcs->bci(), index, cp, types, CHECK_VERIFY(this)); // Get method name and signature Symbol* method_name = cp->name_ref_at(index); @@ -2029,11 +2385,13 @@ // the difference between the size of the operand stack before and after the instruction // executes. if (*(bcp+3) != (nargs+1)) { - verify_error(bci, "Inconsistent args count operand in invokeinterface"); + verify_error(ErrorContext::bad_code(bci), + "Inconsistent args count operand in invokeinterface"); return; } if (*(bcp+4) != 0) { - verify_error(bci, "Fourth operand byte of invokeinterface must be zero"); + verify_error(ErrorContext::bad_code(bci), + "Fourth operand byte of invokeinterface must be zero"); return; } } @@ -2041,7 +2399,8 @@ if (opcode == Bytecodes::_invokedynamic) { address bcp = bcs->bcp(); if (*(bcp+3) != 0 || *(bcp+4) != 0) { - verify_error(bci, "Third and fourth operand bytes of invokedynamic must be zero"); + verify_error(ErrorContext::bad_code(bci), + "Third and fourth operand bytes of invokedynamic must be zero"); return; } } @@ -2050,7 +2409,8 @@ // Make sure <init> can only be invoked by invokespecial if (opcode != Bytecodes::_invokespecial || method_name != vmSymbols::object_initializer_name()) { - verify_error(bci, "Illegal call to internal method"); + verify_error(ErrorContext::bad_code(bci), + "Illegal call to internal method"); return; } } else if (opcode == Bytecodes::_invokespecial @@ -2060,7 +2420,8 @@ bool subtype = ref_class_type.is_assignable_from( current_type(), this, CHECK_VERIFY(this)); if (!subtype) { - verify_error(bci, "Bad invokespecial instruction: " + verify_error(ErrorContext::bad_code(bci), + "Bad invokespecial instruction: " "current class isn't assignable to reference class."); return; } @@ -2073,7 +2434,7 @@ if (opcode != Bytecodes::_invokestatic && opcode != Bytecodes::_invokedynamic) { if (method_name == vmSymbols::object_initializer_name()) { // <init> method - verify_invoke_init(bcs, ref_class_type, current_frame, + verify_invoke_init(bcs, index, ref_class_type, current_frame, code_length, this_uninit, cp, CHECK_VERIFY(this)); } else { // other methods // Ensures that target class is assignable to method class. @@ -2103,8 +2464,10 @@ // Special case: arrays pretend to implement public Object // clone(). } else { - verify_error(bci, - "Bad access to protected data in invokevirtual"); + verify_error(ErrorContext::bad_type(bci, + current_frame->stack_top_ctx(), + TypeOrigin::implicit(current_type())), + "Bad access to protected data in invokevirtual"); return; } } @@ -2121,7 +2484,10 @@ if (sig_stream.type() != T_VOID) { if (method_name == vmSymbols::object_initializer_name()) { // <init> method must have a void return type - verify_error(bci, "Return type must be void in <init> method"); + /* Unreachable? Class file parser verifies that methods with '<' have + * void return */ + verify_error(ErrorContext::bad_code(bci), + "Return type must be void in <init> method"); return; } VerificationType return_type[2]; @@ -2139,7 +2505,7 @@ NULL, NULL, NULL, NULL, "[Z", "[C", "[F", "[D", "[B", "[S", "[I", "[J", }; if (index < T_BOOLEAN || index > T_LONG) { - verify_error(bci, "Illegal newarray instruction"); + verify_error(ErrorContext::bad_code(bci), "Illegal newarray instruction"); return VerificationType::bogus_type(); } @@ -2150,8 +2516,9 @@ } void ClassVerifier::verify_anewarray( - u2 index, constantPoolHandle cp, StackMapFrame* current_frame, TRAPS) { - verify_cp_class_type(index, cp, CHECK_VERIFY(this)); + u2 bci, u2 index, constantPoolHandle cp, + StackMapFrame* current_frame, TRAPS) { + verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this)); current_frame->pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); @@ -2264,14 +2631,19 @@ } void ClassVerifier::verify_return_value( - VerificationType return_type, VerificationType type, u2 bci, TRAPS) { + VerificationType return_type, VerificationType type, u2 bci, + StackMapFrame* current_frame, TRAPS) { if (return_type == VerificationType::bogus_type()) { - verify_error(bci, "Method expects a return value"); + verify_error(ErrorContext::bad_type(bci, + current_frame->stack_top_ctx(), TypeOrigin::signature(return_type)), + "Method expects a return value"); return; } bool match = return_type.is_assignable_from(type, this, CHECK_VERIFY(this)); if (!match) { - verify_error(bci, "Bad return type"); + verify_error(ErrorContext::bad_type(bci, + current_frame->stack_top_ctx(), TypeOrigin::signature(return_type)), + "Bad return type"); return; } }
--- a/src/share/vm/classfile/verifier.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/classfile/verifier.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,18 +88,178 @@ #define CHECK_VERIFY_(verifier, result) \ CHECK_(result)); if ((verifier)->has_error()) return (result); (0 +class TypeOrigin VALUE_OBJ_CLASS_SPEC { + private: + typedef enum { + CF_LOCALS, // Comes from the current frame locals + CF_STACK, // Comes from the current frame expression stack + SM_LOCALS, // Comes from stackmap locals + SM_STACK, // Comes from stackmap expression stack + CONST_POOL, // Comes from the constant pool + SIG, // Comes from method signature + IMPLICIT, // Comes implicitly from code or context + BAD_INDEX, // No type, but the index is bad + FRAME_ONLY, // No type, context just contains the frame + NONE + } Origin; + + Origin _origin; + u2 _index; // local, stack, or constant pool index + StackMapFrame* _frame; // source frame if CF or SM + VerificationType _type; // The actual type + + TypeOrigin( + Origin origin, u2 index, StackMapFrame* frame, VerificationType type) + : _origin(origin), _index(index), _frame(frame), _type(type) {} + + public: + TypeOrigin() : _origin(NONE), _index(0), _frame(NULL) {} + + static TypeOrigin null(); + static TypeOrigin local(u2 index, StackMapFrame* frame); + static TypeOrigin stack(u2 index, StackMapFrame* frame); + static TypeOrigin sm_local(u2 index, StackMapFrame* frame); + static TypeOrigin sm_stack(u2 index, StackMapFrame* frame); + static TypeOrigin cp(u2 index, VerificationType vt); + static TypeOrigin signature(VerificationType vt); + static TypeOrigin bad_index(u2 index); + static TypeOrigin implicit(VerificationType t); + static TypeOrigin frame(StackMapFrame* frame); + + void reset_frame(); + void details(outputStream* ss) const; + void print_frame(outputStream* ss) const; + const StackMapFrame* frame() const { return _frame; } + bool is_valid() const { return _origin != NONE; } + u2 index() const { return _index; } + +#ifdef ASSERT + void print_on(outputStream* str) const; +#endif +}; + +class ErrorContext VALUE_OBJ_CLASS_SPEC { + private: + typedef enum { + INVALID_BYTECODE, // There was a problem with the bytecode + WRONG_TYPE, // Type value was not as expected + FLAGS_MISMATCH, // Frame flags are not assignable + BAD_CP_INDEX, // Invalid constant pool index + BAD_LOCAL_INDEX, // Invalid local index + LOCALS_SIZE_MISMATCH, // Frames have differing local counts + STACK_SIZE_MISMATCH, // Frames have different stack sizes + STACK_OVERFLOW, // Attempt to push onto a full expression stack + STACK_UNDERFLOW, // Attempt to pop and empty expression stack + MISSING_STACKMAP, // No stackmap for this location and there should be + BAD_STACKMAP, // Format error in stackmap + NO_FAULT, // No error + UNKNOWN + } FaultType; + + int _bci; + FaultType _fault; + TypeOrigin _type; + TypeOrigin _expected; + + ErrorContext(int bci, FaultType fault) : + _bci(bci), _fault(fault) {} + ErrorContext(int bci, FaultType fault, TypeOrigin type) : + _bci(bci), _fault(fault), _type(type) {} + ErrorContext(int bci, FaultType fault, TypeOrigin type, TypeOrigin exp) : + _bci(bci), _fault(fault), _type(type), _expected(exp) {} + + public: + ErrorContext() : _bci(-1), _fault(NO_FAULT) {} + + static ErrorContext bad_code(u2 bci) { + return ErrorContext(bci, INVALID_BYTECODE); + } + static ErrorContext bad_type(u2 bci, TypeOrigin type) { + return ErrorContext(bci, WRONG_TYPE, type); + } + static ErrorContext bad_type(u2 bci, TypeOrigin type, TypeOrigin exp) { + return ErrorContext(bci, WRONG_TYPE, type, exp); + } + static ErrorContext bad_flags(u2 bci, StackMapFrame* frame) { + return ErrorContext(bci, FLAGS_MISMATCH, TypeOrigin::frame(frame)); + } + static ErrorContext bad_flags(u2 bci, StackMapFrame* cur, StackMapFrame* sm) { + return ErrorContext(bci, FLAGS_MISMATCH, + TypeOrigin::frame(cur), TypeOrigin::frame(sm)); + } + static ErrorContext bad_cp_index(u2 bci, u2 index) { + return ErrorContext(bci, BAD_CP_INDEX, TypeOrigin::bad_index(index)); + } + static ErrorContext bad_local_index(u2 bci, u2 index) { + return ErrorContext(bci, BAD_LOCAL_INDEX, TypeOrigin::bad_index(index)); + } + static ErrorContext locals_size_mismatch( + u2 bci, StackMapFrame* frame0, StackMapFrame* frame1) { + return ErrorContext(bci, LOCALS_SIZE_MISMATCH, + TypeOrigin::frame(frame0), TypeOrigin::frame(frame1)); + } + static ErrorContext stack_size_mismatch( + u2 bci, StackMapFrame* frame0, StackMapFrame* frame1) { + return ErrorContext(bci, STACK_SIZE_MISMATCH, + TypeOrigin::frame(frame0), TypeOrigin::frame(frame1)); + } + static ErrorContext stack_overflow(u2 bci, StackMapFrame* frame) { + return ErrorContext(bci, STACK_OVERFLOW, TypeOrigin::frame(frame)); + } + static ErrorContext stack_underflow(u2 bci, StackMapFrame* frame) { + return ErrorContext(bci, STACK_UNDERFLOW, TypeOrigin::frame(frame)); + } + static ErrorContext missing_stackmap(u2 bci) { + return ErrorContext(bci, MISSING_STACKMAP); + } + static ErrorContext bad_stackmap(int index, StackMapFrame* frame) { + return ErrorContext(0, BAD_STACKMAP, TypeOrigin::frame(frame)); + } + + bool is_valid() const { return _fault != NO_FAULT; } + int bci() const { return _bci; } + + void reset_frames() { + _type.reset_frame(); + _expected.reset_frame(); + } + + void details(outputStream* ss, methodOop method) const; + +#ifdef ASSERT + void print_on(outputStream* str) const { + str->print("error_context(%d, %d,", _bci, _fault); + _type.print_on(str); + str->print(","); + _expected.print_on(str); + str->print(")"); + } +#endif + + private: + void location_details(outputStream* ss, methodOop method) const; + void reason_details(outputStream* ss) const; + void frame_details(outputStream* ss) const; + void bytecode_details(outputStream* ss, methodOop method) const; + void handler_details(outputStream* ss, methodOop method) const; + void stackmap_details(outputStream* ss, methodOop method) const; +}; + // A new instance of this class is created for each class being verified class ClassVerifier : public StackObj { private: Thread* _thread; + GrowableArray<Symbol*>* _symbols; // keep a list of symbols created + Symbol* _exception_type; char* _message; - size_t _message_buffer_len; - GrowableArray<Symbol*>* _symbols; // keep a list of symbols created + + ErrorContext _error_context; // contains information about an error void verify_method(methodHandle method, TRAPS); char* generate_code_data(methodHandle m, u4 code_length, TRAPS); - void verify_exception_handler_table(u4 code_length, char* code_data, int& min, int& max, TRAPS); + void verify_exception_handler_table(u4 code_length, char* code_data, + int& min, int& max, TRAPS); void verify_local_variable_table(u4 code_length, char* code_data, TRAPS); VerificationType cp_ref_index_to_type( @@ -111,10 +271,10 @@ instanceKlassHandle this_class, klassOop target_class, Symbol* field_name, Symbol* field_sig, bool is_method); - void verify_cp_index(constantPoolHandle cp, int index, TRAPS); - void verify_cp_type( - int index, constantPoolHandle cp, unsigned int types, TRAPS); - void verify_cp_class_type(int index, constantPoolHandle cp, TRAPS); + void verify_cp_index(u2 bci, constantPoolHandle cp, int index, TRAPS); + void verify_cp_type(u2 bci, int index, constantPoolHandle cp, + unsigned int types, TRAPS); + void verify_cp_class_type(u2 bci, int index, constantPoolHandle cp, TRAPS); u2 verify_stackmap_table( u2 stackmap_index, u2 bci, StackMapFrame* current_frame, @@ -137,7 +297,7 @@ constantPoolHandle cp, TRAPS); void verify_invoke_init( - RawBytecodeStream* bcs, VerificationType ref_class_type, + RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type, StackMapFrame* current_frame, u4 code_length, bool* this_uninit, constantPoolHandle cp, TRAPS); @@ -147,10 +307,11 @@ constantPoolHandle cp, TRAPS); VerificationType get_newarray_type(u2 index, u2 bci, TRAPS); - void verify_anewarray( - u2 index, constantPoolHandle cp, StackMapFrame* current_frame, TRAPS); + void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp, + StackMapFrame* current_frame, TRAPS); void verify_return_value( - VerificationType return_type, VerificationType type, u2 offset, TRAPS); + VerificationType return_type, VerificationType type, u2 offset, + StackMapFrame* current_frame, TRAPS); void verify_iload (u2 index, StackMapFrame* current_frame, TRAPS); void verify_lload (u2 index, StackMapFrame* current_frame, TRAPS); @@ -189,7 +350,7 @@ }; // constructor - ClassVerifier(instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS); + ClassVerifier(instanceKlassHandle klass, TRAPS); // destructor ~ClassVerifier(); @@ -207,13 +368,17 @@ // Return status modes Symbol* result() const { return _exception_type; } bool has_error() const { return result() != NULL; } + char* exception_message() { + stringStream ss; + ss.print(_message); + _error_context.details(&ss, _method()); + return ss.as_string(); + } // Called when verify or class format errors are encountered. // May throw an exception based upon the mode. - void verify_error(u2 offset, const char* fmt, ...); - void verify_error(const char* fmt, ...); + void verify_error(ErrorContext ctx, const char* fmt, ...); void class_format_error(const char* fmt, ...); - void format_error_message(const char* fmt, int offset, va_list args); klassOop load_class(Symbol* name, TRAPS); @@ -228,10 +393,11 @@ // their reference counts need to be decrememented when the verifier object // goes out of scope. Since these symbols escape the scope in which they're // created, we can't use a TempNewSymbol. - Symbol* create_temporary_symbol(const Symbol* s, int begin, int end, TRAPS); + Symbol* create_temporary_symbol( + const Symbol* s, int begin, int end, TRAPS); Symbol* create_temporary_symbol(const char *s, int length, TRAPS); - static bool _verify_verbose; // for debugging + TypeOrigin ref_ctx(const char* str, TRAPS); }; inline int ClassVerifier::change_sig_to_verificationType(
--- a/src/share/vm/classfile/vmSymbols.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/classfile/vmSymbols.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -303,13 +303,13 @@ template(com_oracle_graal_api_code_Assumptions_MethodContents, "com/oracle/graal/api/code/Assumptions$MethodContents") \ template(com_oracle_graal_api_code_Assumptions_ConcreteSubtype, "com/oracle/graal/api/code/Assumptions$ConcreteSubtype") \ template(com_oracle_graal_api_code_Assumptions_ConcreteMethod, "com/oracle/graal/api/code/Assumptions$ConcreteMethod") \ - template(com_oracle_graal_api_code_InstalledCode, "com/oracle/graal/api/code/CompilationResult") \ - template(com_oracle_graal_api_code_InstalledCode_Call, "com/oracle/graal/api/code/CompilationResult$Call") \ - template(com_oracle_graal_api_code_InstalledCode_DataPatch, "com/oracle/graal/api/code/CompilationResult$DataPatch") \ - template(com_oracle_graal_api_code_InstalledCode_ExceptionHandler, "com/oracle/graal/api/code/CompilationResult$ExceptionHandler") \ - template(com_oracle_graal_api_code_InstalledCode_Mark, "com/oracle/graal/api/code/CompilationResult$Mark") \ - template(com_oracle_graal_api_code_InstalledCode_Safepoint, "com/oracle/graal/api/code/CompilationResult$Safepoint") \ - template(com_oracle_graal_api_code_InstalledCode_Site, "com/oracle/graal/api/code/CompilationResult$Site") \ + template(com_oracle_graal_api_code_CompilationResult, "com/oracle/graal/api/code/CompilationResult") \ + template(com_oracle_graal_api_code_CompilationResult_Call, "com/oracle/graal/api/code/CompilationResult$Call") \ + template(com_oracle_graal_api_code_CompilationResult_DataPatch, "com/oracle/graal/api/code/CompilationResult$DataPatch") \ + template(com_oracle_graal_api_code_CompilationResult_ExceptionHandler, "com/oracle/graal/api/code/CompilationResult$ExceptionHandler") \ + template(com_oracle_graal_api_code_CompilationResult_Mark, "com/oracle/graal/api/code/CompilationResult$Mark") \ + template(com_oracle_graal_api_code_CompilationResult_Safepoint, "com/oracle/graal/api/code/CompilationResult$Safepoint") \ + template(com_oracle_graal_api_code_CompilationResult_Site, "com/oracle/graal/api/code/CompilationResult$Site") \ template(com_oracle_graal_api_code_BytecodeFrame, "com/oracle/graal/api/code/BytecodeFrame") \ template(com_oracle_graal_api_code_BytecodePosition, "com/oracle/graal/api/code/BytecodePosition") \ template(com_oracle_graal_api_code_DebugInfo, "com/oracle/graal/api/code/DebugInfo") \
--- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -159,14 +159,30 @@ "right address out of range"); assert(left < right, "Heap addresses out of order"); size_t num_cards = pointer_delta(right, left) >> LogN_words; - memset(&_offset_array[index_for(left)], offset, num_cards); + if (UseMemSetInBOT) { + memset(&_offset_array[index_for(left)], offset, num_cards); + } else { + size_t i = index_for(left); + const size_t end = i + num_cards; + for (; i < end; i++) { + _offset_array[i] = offset; + } + } } void set_offset_array(size_t left, size_t right, u_char offset) { assert(right < _vs.committed_size(), "right address out of range"); - assert(left <= right, "indexes out of order"); + assert(left <= right, "indexes out of order"); size_t num_cards = right - left + 1; - memset(&_offset_array[left], offset, num_cards); + if (UseMemSetInBOT) { + memset(&_offset_array[left], offset, num_cards); + } else { + size_t i = left; + const size_t end = i + num_cards; + for (; i < end; i++) { + _offset_array[i] = offset; + } + } } void check_offset_array(size_t index, HeapWord* high, HeapWord* low) const {
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -1246,6 +1246,31 @@ heap_region_iterate(&cl); } +double G1CollectedHeap::verify(bool guard, const char* msg) { + double verify_time_ms = 0.0; + + if (guard && total_collections() >= VerifyGCStartAt) { + double verify_start = os::elapsedTime(); + HandleMark hm; // Discard invalid handles created during verification + gclog_or_tty->print(msg); + prepare_for_verify(); + Universe::verify(false /* silent */, VerifyOption_G1UsePrevMarking); + verify_time_ms = (os::elapsedTime() - verify_start) * 1000; + } + + return verify_time_ms; +} + +void G1CollectedHeap::verify_before_gc() { + double verify_time_ms = verify(VerifyBeforeGC, " VerifyBeforeGC:"); + g1_policy()->phase_times()->record_verify_before_time_ms(verify_time_ms); +} + +void G1CollectedHeap::verify_after_gc() { + double verify_time_ms = verify(VerifyAfterGC, " VerifyAfterGC:"); + g1_policy()->phase_times()->record_verify_after_time_ms(verify_time_ms); +} + bool G1CollectedHeap::do_collection(bool explicit_gc, bool clear_all_soft_refs, size_t word_size) { @@ -1304,14 +1329,8 @@ size_t g1h_prev_used = used(); assert(used() == recalculate_used(), "Should be equal"); - if (VerifyBeforeGC && total_collections() >= VerifyGCStartAt) { - HandleMark hm; // Discard invalid handles created during verification - gclog_or_tty->print(" VerifyBeforeGC:"); - prepare_for_verify(); - Universe::verify(/* silent */ false, - /* option */ VerifyOption_G1UsePrevMarking); - - } + verify_before_gc(); + pre_full_gc_dump(); COMPILER2_PRESENT(DerivedPointerTable::clear()); @@ -1378,14 +1397,7 @@ MemoryService::track_memory_usage(); - if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { - HandleMark hm; // Discard invalid handles created during verification - gclog_or_tty->print(" VerifyAfterGC:"); - prepare_for_verify(); - Universe::verify(/* silent */ false, - /* option */ VerifyOption_G1UsePrevMarking); - - } + verify_after_gc(); assert(!ref_processor_stw()->discovery_enabled(), "Postcondition"); ref_processor_stw()->verify_no_references_recorded(); @@ -1891,6 +1903,8 @@ _young_list(new YoungList(this)), _gc_time_stamp(0), _retained_old_gc_alloc_region(NULL), + _survivor_plab_stats(YoungPLABSize, PLABWeight), + _old_plab_stats(OldPLABSize, PLABWeight), _expand_heap_after_alloc_failure(true), _surviving_young_words(NULL), _old_marking_cycles_started(0), @@ -1931,7 +1945,18 @@ clear_cset_start_regions(); + // Initialize the G1EvacuationFailureALot counters and flags. + NOT_PRODUCT(reset_evacuation_should_fail();) + guarantee(_task_queues != NULL, "task_queues allocation failure."); +#ifdef SPARC + // Issue a stern warning, but allow use for experimentation and debugging. + if (VM_Version::is_sun4v() && UseMemSetInBOT) { + assert(!FLAG_IS_DEFAULT(UseMemSetInBOT), "Error"); + warning("Experimental flag -XX:+UseMemSetInBOT is known to cause instability" + " on sun4v; please understand that you are using at your own risk!"); + } +#endif } jint G1CollectedHeap::initialize() { @@ -2317,8 +2342,7 @@ while (dcqs.apply_closure_to_completed_buffer(cl, worker_i, 0, true)) { n_completed_buffers++; } - g1_policy()->phase_times()->record_update_rs_processed_buffers(worker_i, - (double) n_completed_buffers); + g1_policy()->phase_times()->record_update_rs_processed_buffers(worker_i, n_completed_buffers); dcqs.clear_n_completed_buffers(); assert(!dcqs.completed_buffers_exist_dirty(), "Completed buffers exist!"); } @@ -3580,15 +3604,11 @@ DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); size_t buffer_size = dcqs.buffer_size(); size_t buffer_num = dcqs.completed_buffers_num(); - return buffer_size * buffer_num + extra_cards; -} - -size_t G1CollectedHeap::max_pending_card_num() { - DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); - size_t buffer_size = dcqs.buffer_size(); - size_t buffer_num = dcqs.completed_buffers_num(); - int thread_num = Threads::number_of_threads(); - return (buffer_num + thread_num) * buffer_size; + + // PtrQueueSet::buffer_size() and PtrQueue:size() return sizes + // in bytes - not the number of 'entries'. We need to convert + // into a number of cards. + return (buffer_size * buffer_num + extra_cards) / oopSize; } size_t G1CollectedHeap::cards_scanned() { @@ -3729,8 +3749,9 @@ int active_workers = (G1CollectedHeap::use_parallel_gc_threads() ? workers()->active_workers() : 1); - g1_policy()->phase_times()->note_gc_start(os::elapsedTime(), active_workers, - g1_policy()->gcs_are_young(), g1_policy()->during_initial_mark_pause(), gc_cause()); + double pause_start_sec = os::elapsedTime(); + g1_policy()->phase_times()->note_gc_start(active_workers); + bool initial_mark_gc = g1_policy()->during_initial_mark_pause(); TraceCollectorStats tcs(g1mm()->incremental_collection_counters()); TraceMemoryManagerStats tms(false /* fullGC */, gc_cause()); @@ -3759,13 +3780,7 @@ increment_total_collections(false /* full gc */); increment_gc_time_stamp(); - if (VerifyBeforeGC && total_collections() >= VerifyGCStartAt) { - HandleMark hm; // Discard invalid handles created during verification - gclog_or_tty->print(" VerifyBeforeGC:"); - prepare_for_verify(); - Universe::verify(/* silent */ false, - /* option */ VerifyOption_G1UsePrevMarking); - } + verify_before_gc(); COMPILER2_PRESENT(DerivedPointerTable::clear()); @@ -3978,10 +3993,6 @@ true /* verify_fingers */); _cm->note_end_of_gc(); - // Collect thread local data to allow the ergonomics to use - // the collected information - g1_policy()->phase_times()->collapse_par_times(); - // This timing is only used by the ergonomics to handle our pause target. // It is unclear why this should not include the full pause. We will // investigate this in CR 7178365. @@ -4014,13 +4025,7 @@ // scanning cards (see CR 7039627). increment_gc_time_stamp(); - if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) { - HandleMark hm; // Discard invalid handles created during verification - gclog_or_tty->print(" VerifyAfterGC:"); - prepare_for_verify(); - Universe::verify(/* silent */ false, - /* option */ VerifyOption_G1UsePrevMarking); - } + verify_after_gc(); assert(!ref_processor_stw()->discovery_enabled(), "Postcondition"); ref_processor_stw()->verify_no_references_recorded(); @@ -4044,10 +4049,35 @@ gc_epilogue(false); - g1_policy()->phase_times()->note_gc_end(os::elapsedTime()); - - // We have to do this after we decide whether to expand the heap or not. + if (G1Log::fine()) { + if (PrintGCTimeStamps) { + gclog_or_tty->stamp(); + gclog_or_tty->print(": "); + } + + GCCauseString gc_cause_str = GCCauseString("GC pause", gc_cause()) + .append(g1_policy()->gcs_are_young() ? " (young)" : " (mixed)") + .append(initial_mark_gc ? " (initial-mark)" : ""); + + double pause_time_sec = os::elapsedTime() - pause_start_sec; + + if (G1Log::finer()) { + if (evacuation_failed()) { + gc_cause_str.append(" (to-space exhausted)"); + } + gclog_or_tty->print_cr("[%s, %3.7f secs]", (const char*)gc_cause_str, pause_time_sec); + g1_policy()->phase_times()->note_gc_end(); + g1_policy()->phase_times()->print(pause_time_sec); + g1_policy()->print_detailed_heap_transition(); + } else { + if (evacuation_failed()) { + gc_cause_str.append("--"); + } + gclog_or_tty->print("[%s", (const char*)gc_cause_str); g1_policy()->print_heap_transition(); + gclog_or_tty->print_cr(", %3.7f secs]", pause_time_sec); + } + } } // It is not yet to safe to tell the concurrent mark to @@ -4099,17 +4129,22 @@ size_t gclab_word_size; switch (purpose) { case GCAllocForSurvived: - gclab_word_size = YoungPLABSize; + gclab_word_size = _survivor_plab_stats.desired_plab_sz(); break; case GCAllocForTenured: - gclab_word_size = OldPLABSize; + gclab_word_size = _old_plab_stats.desired_plab_sz(); break; default: assert(false, "unknown GCAllocPurpose"); - gclab_word_size = OldPLABSize; + gclab_word_size = _old_plab_stats.desired_plab_sz(); break; } - return gclab_word_size; + + // Prevent humongous PLAB sizes for two reasons: + // * PLABs are allocated using a similar paths as oops, but should + // never be in a humongous region + // * Allowing humongous PLABs needlessly churns the region free lists + return MIN2(_humongous_object_threshold_in_words, gclab_word_size); } void G1CollectedHeap::init_mutator_alloc_region() { @@ -4165,6 +4200,11 @@ // want either way so no reason to check explicitly for either // condition. _retained_old_gc_alloc_region = _old_gc_alloc_region.release(); + + if (ResizePLAB) { + _survivor_plab_stats.adjust_desired_plab_sz(); + _old_plab_stats.adjust_desired_plab_sz(); + } } void G1CollectedHeap::abandon_gc_alloc_regions() { @@ -4527,7 +4567,15 @@ GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age, word_sz); HeapWord* obj_ptr = _par_scan_state->allocate(alloc_purpose, word_sz); - oop obj = oop(obj_ptr); +#ifndef PRODUCT + // Should this evacuation fail? + if (_g1->evacuation_should_fail()) { + if (obj_ptr != NULL) { + _par_scan_state->undo_allocation(alloc_purpose, obj_ptr, word_sz); + obj_ptr = NULL; + } + } +#endif // !PRODUCT if (obj_ptr == NULL) { // This will either forward-to-self, or detect that someone else has @@ -4536,6 +4584,8 @@ return _g1->handle_evacuation_failure_par(cl, old); } + oop obj = oop(obj_ptr); + // We're going to allocate linearly, so might as well prefetch ahead. Prefetch::write(obj_ptr, PrefetchCopyIntervalInBytes); @@ -4847,7 +4897,7 @@ evac.do_void(); double elapsed_ms = (os::elapsedTime()-start)*1000.0; double term_ms = pss.term_time()*1000.0; - _g1h->g1_policy()->phase_times()->record_obj_copy_time(worker_id, elapsed_ms-term_ms); + _g1h->g1_policy()->phase_times()->add_obj_copy_time(worker_id, elapsed_ms-term_ms); _g1h->g1_policy()->phase_times()->record_termination(worker_id, term_ms, pss.term_attempts()); } _g1h->g1_policy()->record_thread_age_table(pss.age_table()); @@ -4975,27 +5025,28 @@ buf_scan_non_heap_roots.done(); buf_scan_perm.done(); - double ext_roots_end = os::elapsedTime(); - - g1_policy()->phase_times()->reset_obj_copy_time(worker_i); double obj_copy_time_sec = buf_scan_perm.closure_app_seconds() + buf_scan_non_heap_roots.closure_app_seconds(); g1_policy()->phase_times()->record_obj_copy_time(worker_i, obj_copy_time_sec * 1000.0); double ext_root_time_ms = - ((ext_roots_end - ext_roots_start) - obj_copy_time_sec) * 1000.0; + ((os::elapsedTime() - ext_roots_start) - obj_copy_time_sec) * 1000.0; g1_policy()->phase_times()->record_ext_root_scan_time(worker_i, ext_root_time_ms); // During conc marking we have to filter the per-thread SATB buffers // to make sure we remove any oops into the CSet (which will show up // as implicitly live). + double satb_filtering_ms = 0.0; if (!_process_strong_tasks->is_task_claimed(G1H_PS_filter_satb_buffers)) { if (mark_in_progress()) { + double satb_filter_start = os::elapsedTime(); + JavaThread::satb_mark_queue_set().filter_thread_buffers(); + + satb_filtering_ms = (os::elapsedTime() - satb_filter_start) * 1000.0; } } - double satb_filtering_ms = (os::elapsedTime() - ext_roots_end) * 1000.0; g1_policy()->phase_times()->record_satb_filtering_time(worker_i, satb_filtering_ms); // Now scan the complement of the collection set. @@ -5540,6 +5591,9 @@ _expand_heap_after_alloc_failure = true; set_evacuation_failed(false); + // Should G1EvacuationFailureALot be in effect for this GC? + NOT_PRODUCT(set_evacuation_failure_alot_for_current_gc();) + g1_rem_set()->prepare_for_oops_into_collection_set_do(); concurrent_g1_refine()->set_use_cache(false); concurrent_g1_refine()->clear_hot_cache_claimed_index(); @@ -5631,11 +5685,11 @@ if (evacuation_failed()) { remove_self_forwarding_pointers(); - if (G1Log::finer()) { - gclog_or_tty->print(" (to-space exhausted)"); - } else if (G1Log::fine()) { - gclog_or_tty->print("--"); - } + + // Reset the G1EvacuationFailureALot counters and flags + // Note: the values are reset only when an actual + // evacuation failure occurs. + NOT_PRODUCT(reset_evacuation_should_fail();) } // Enqueue any remaining references remaining on the STW
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -33,7 +33,7 @@ #include "gc_implementation/g1/heapRegionSeq.hpp" #include "gc_implementation/g1/heapRegionSets.hpp" #include "gc_implementation/shared/hSpaceCounters.hpp" -#include "gc_implementation/parNew/parGCAllocBuffer.hpp" +#include "gc_implementation/shared/parGCAllocBuffer.hpp" #include "memory/barrierSet.hpp" #include "memory/memRegion.hpp" #include "memory/sharedHeap.hpp" @@ -278,10 +278,33 @@ // survivor objects. SurvivorGCAllocRegion _survivor_gc_alloc_region; + // PLAB sizing policy for survivors. + PLABStats _survivor_plab_stats; + // Alloc region used to satisfy allocation requests by the GC for // old objects. OldGCAllocRegion _old_gc_alloc_region; + // PLAB sizing policy for tenured objects. + PLABStats _old_plab_stats; + + PLABStats* stats_for_purpose(GCAllocPurpose purpose) { + PLABStats* stats = NULL; + + switch (purpose) { + case GCAllocForSurvived: + stats = &_survivor_plab_stats; + break; + case GCAllocForTenured: + stats = &_old_plab_stats; + break; + default: + assert(false, "unrecognized GCAllocPurpose"); + } + + return stats; + } + // The last old region we allocated to during the last GC. // Typically, it is not full so we should re-use it during the next GC. HeapRegion* _retained_old_gc_alloc_region; @@ -314,7 +337,7 @@ G1MonitoringSupport* _g1mm; // Determines PLAB size for a particular allocation purpose. - static size_t desired_plab_sz(GCAllocPurpose purpose); + size_t desired_plab_sz(GCAllocPurpose purpose); // Outside of GC pauses, the number of bytes used in all regions other // than the current allocation region. @@ -382,6 +405,10 @@ // heap after a compaction. void print_hrs_post_compaction(); + double verify(bool guard, const char* msg); + void verify_before_gc(); + void verify_after_gc(); + // These are macros so that, if the assert fires, we get the correct // line number, file, etc. @@ -888,6 +915,39 @@ oop handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop obj); void handle_evacuation_failure_common(oop obj, markOop m); +#ifndef PRODUCT + // Support for forcing evacuation failures. Analogous to + // PromotionFailureALot for the other collectors. + + // Records whether G1EvacuationFailureALot should be in effect + // for the current GC + bool _evacuation_failure_alot_for_current_gc; + + // Used to record the GC number for interval checking when + // determining whether G1EvaucationFailureALot is in effect + // for the current GC. + size_t _evacuation_failure_alot_gc_number; + + // Count of the number of evacuations between failures. + volatile size_t _evacuation_failure_alot_count; + + // Set whether G1EvacuationFailureALot should be in effect + // for the current GC (based upon the type of GC and which + // command line flags are set); + inline bool evacuation_failure_alot_for_gc_type(bool gcs_are_young, + bool during_initial_mark, + bool during_marking); + + inline void set_evacuation_failure_alot_for_current_gc(); + + // Return true if it's time to cause an evacuation failure. + inline bool evacuation_should_fail(); + + // Reset the G1EvacuationFailureALot counters. Should be called at + // the end of an evacuation pause in which an evacuation failure ocurred. + inline void reset_evacuation_should_fail(); +#endif // !PRODUCT + // ("Weak") Reference processing support. // // G1 has 2 instances of the referece processor class. One @@ -1683,7 +1743,6 @@ void stop_conc_gc_threads(); size_t pending_card_num(); - size_t max_pending_card_num(); size_t cards_scanned(); protected: @@ -1811,19 +1870,19 @@ } HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz) { - HeapWord* obj = NULL; size_t gclab_word_size = _g1h->desired_plab_sz(purpose); if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) { G1ParGCAllocBuffer* alloc_buf = alloc_buffer(purpose); - assert(gclab_word_size == alloc_buf->word_sz(), - "dynamic resizing is not supported"); add_to_alloc_buffer_waste(alloc_buf->words_remaining()); - alloc_buf->retire(false, false); + alloc_buf->flush_stats_and_retire(_g1h->stats_for_purpose(purpose), + false /* end_of_gc */, + false /* retain */); HeapWord* buf = _g1h->par_allocate_during_gc(purpose, gclab_word_size); if (buf == NULL) return NULL; // Let caller handle allocation failure. // Otherwise. + alloc_buf->set_word_size(gclab_word_size); alloc_buf->set_buf(buf); obj = alloc_buf->allocate(word_sz); @@ -1908,7 +1967,9 @@ for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { size_t waste = _alloc_buffers[ap]->words_remaining(); add_to_alloc_buffer_waste(waste); - _alloc_buffers[ap]->retire(true, false); + _alloc_buffers[ap]->flush_stats_and_retire(_g1h->stats_for_purpose((GCAllocPurpose)ap), + true /* end_of_gc */, + false /* retain */); } }
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -138,7 +138,7 @@ return _task_queues->queue(i); } -inline bool G1CollectedHeap::isMarkedPrev(oop obj) const { +inline bool G1CollectedHeap::isMarkedPrev(oop obj) const { return _cm->prevMarkBitMap()->isMarked((HeapWord *)obj); } @@ -146,4 +146,77 @@ return _cm->nextMarkBitMap()->isMarked((HeapWord *)obj); } +#ifndef PRODUCT +// Support for G1EvacuationFailureALot + +inline bool +G1CollectedHeap::evacuation_failure_alot_for_gc_type(bool gcs_are_young, + bool during_initial_mark, + bool during_marking) { + bool res = false; + if (during_marking) { + res |= G1EvacuationFailureALotDuringConcMark; + } + if (during_initial_mark) { + res |= G1EvacuationFailureALotDuringInitialMark; + } + if (gcs_are_young) { + res |= G1EvacuationFailureALotDuringYoungGC; + } else { + // GCs are mixed + res |= G1EvacuationFailureALotDuringMixedGC; + } + return res; +} + +inline void +G1CollectedHeap::set_evacuation_failure_alot_for_current_gc() { + if (G1EvacuationFailureALot) { + // Note we can't assert that _evacuation_failure_alot_for_current_gc + // is clear here. It may have been set during a previous GC but that GC + // did not copy enough objects (i.e. G1EvacuationFailureALotCount) to + // trigger an evacuation failure and clear the flags and and counts. + + // Check if we have gone over the interval. + const size_t gc_num = total_collections(); + const size_t elapsed_gcs = gc_num - _evacuation_failure_alot_gc_number; + + _evacuation_failure_alot_for_current_gc = (elapsed_gcs >= G1EvacuationFailureALotInterval); + + // Now check if G1EvacuationFailureALot is enabled for the current GC type. + const bool gcs_are_young = g1_policy()->gcs_are_young(); + const bool during_im = g1_policy()->during_initial_mark_pause(); + const bool during_marking = mark_in_progress(); + + _evacuation_failure_alot_for_current_gc &= + evacuation_failure_alot_for_gc_type(gcs_are_young, + during_im, + during_marking); + } +} + +inline bool +G1CollectedHeap::evacuation_should_fail() { + if (!G1EvacuationFailureALot || !_evacuation_failure_alot_for_current_gc) { + return false; + } + // G1EvacuationFailureALot is in effect for current GC + // Access to _evacuation_failure_alot_count is not atomic; + // the value does not have to be exact. + if (++_evacuation_failure_alot_count < G1EvacuationFailureALotCount) { + return false; + } + _evacuation_failure_alot_count = 0; + return true; +} + +inline void G1CollectedHeap::reset_evacuation_should_fail() { + if (G1EvacuationFailureALot) { + _evacuation_failure_alot_gc_number = total_collections(); + _evacuation_failure_alot_count = 0; + _evacuation_failure_alot_for_current_gc = false; + } +} +#endif // #ifndef PRODUCT + #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_INLINE_HPP
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -90,7 +90,6 @@ _alloc_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)), _prev_collection_pause_end_ms(0.0), - _pending_card_diff_seq(new TruncatedSeq(TruncatedSeqLength)), _rs_length_diff_seq(new TruncatedSeq(TruncatedSeqLength)), _cost_per_card_ms_seq(new TruncatedSeq(TruncatedSeqLength)), _young_cards_per_entry_ratio_seq(new TruncatedSeq(TruncatedSeqLength)), @@ -197,7 +196,6 @@ int index = MIN2(_parallel_gc_threads - 1, 7); - _pending_card_diff_seq->add(0.0); _rs_length_diff_seq->add(rs_length_diff_defaults[index]); _cost_per_card_ms_seq->add(cost_per_card_ms_defaults[index]); _young_cards_per_entry_ratio_seq->add( @@ -657,7 +655,7 @@ for (HeapRegion * r = _recorded_survivor_head; r != NULL && r != _recorded_survivor_tail->get_next_young_region(); r = r->get_next_young_region()) { - survivor_regions_evac_time += predict_region_elapsed_time_ms(r, true); + survivor_regions_evac_time += predict_region_elapsed_time_ms(r, gcs_are_young()); } return survivor_regions_evac_time; } @@ -797,13 +795,12 @@ _trace_gen0_time_data.record_start_collection(s_w_t_ms); _stop_world_start = 0.0; - phase_times()->_cur_collection_start_sec = start_time_sec; + phase_times()->record_cur_collection_start_sec(start_time_sec); _cur_collection_pause_used_at_start_bytes = start_used; _cur_collection_pause_used_regions_at_start = _g1->used_regions(); _pending_cards = _g1->pending_card_num(); - _max_pending_cards = _g1->max_pending_card_num(); - _bytes_in_collection_set_before_gc = 0; + _collection_set_bytes_used_before = 0; _bytes_copied_during_gc = 0; YoungList* young_list = _g1->young_list(); @@ -950,7 +947,7 @@ _trace_gen0_time_data.record_end_collection(pause_time_ms, phase_times()); // this is where we update the allocation rate of the application double app_time_ms = - (phase_times()->_cur_collection_start_sec * 1000.0 - _prev_collection_pause_end_ms); + (phase_times()->cur_collection_start_sec() * 1000.0 - _prev_collection_pause_end_ms); if (app_time_ms < MIN_TIMER_GRANULARITY) { // This usually happens due to the timer not having the required // granularity. Some Linuxes are the usual culprits. @@ -1036,15 +1033,9 @@ // do that for any other surv rate groupsx if (update_stats) { - size_t diff = 0; - if (_max_pending_cards >= _pending_cards) { - diff = _max_pending_cards - _pending_cards; - } - _pending_card_diff_seq->add((double) diff); - double cost_per_card_ms = 0.0; if (_pending_cards > 0) { - cost_per_card_ms = phase_times()->_update_rs_time / (double) _pending_cards; + cost_per_card_ms = phase_times()->average_last_update_rs_time() / (double) _pending_cards; _cost_per_card_ms_seq->add(cost_per_card_ms); } @@ -1052,7 +1043,7 @@ double cost_per_entry_ms = 0.0; if (cards_scanned > 10) { - cost_per_entry_ms = phase_times()->_scan_rs_time / (double) cards_scanned; + cost_per_entry_ms = phase_times()->average_last_scan_rs_time() / (double) cards_scanned; if (_last_gc_was_young) { _cost_per_entry_ms_seq->add(cost_per_entry_ms); } else { @@ -1092,7 +1083,7 @@ size_t copied_bytes = surviving_bytes; double cost_per_byte_ms = 0.0; if (copied_bytes > 0) { - cost_per_byte_ms = phase_times()->_obj_copy_time / (double) copied_bytes; + cost_per_byte_ms = phase_times()->average_last_obj_copy_time() / (double) copied_bytes; if (_in_marking_window) { _cost_per_byte_ms_during_cm_seq->add(cost_per_byte_ms); } else { @@ -1101,21 +1092,22 @@ } double all_other_time_ms = pause_time_ms - - (phase_times()->_update_rs_time + phase_times()->_scan_rs_time + phase_times()->_obj_copy_time + phase_times()->_termination_time); + (phase_times()->average_last_update_rs_time() + phase_times()->average_last_scan_rs_time() + + phase_times()->average_last_obj_copy_time() + phase_times()->average_last_termination_time()); double young_other_time_ms = 0.0; if (young_cset_region_length() > 0) { young_other_time_ms = - phase_times()->_recorded_young_cset_choice_time_ms + - phase_times()->_recorded_young_free_cset_time_ms; + phase_times()->young_cset_choice_time_ms() + + phase_times()->young_free_cset_time_ms(); _young_other_cost_per_region_ms_seq->add(young_other_time_ms / (double) young_cset_region_length()); } double non_young_other_time_ms = 0.0; if (old_cset_region_length() > 0) { non_young_other_time_ms = - phase_times()->_recorded_non_young_cset_choice_time_ms + - phase_times()->_recorded_non_young_free_cset_time_ms; + phase_times()->non_young_cset_choice_time_ms() + + phase_times()->non_young_free_cset_time_ms(); _non_young_other_cost_per_region_ms_seq->add(non_young_other_time_ms / (double) old_cset_region_length()); @@ -1126,9 +1118,9 @@ _constant_other_time_ms_seq->add(constant_other_time_ms); double survival_ratio = 0.0; - if (_bytes_in_collection_set_before_gc > 0) { + if (_collection_set_bytes_used_before > 0) { survival_ratio = (double) _bytes_copied_during_gc / - (double) _bytes_in_collection_set_before_gc; + (double) _collection_set_bytes_used_before; } _pending_cards_seq->add((double) _pending_cards); @@ -1142,7 +1134,8 @@ // Note that _mmu_tracker->max_gc_time() returns the time in seconds. double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0; - adjust_concurrent_refinement(phase_times()->_update_rs_time, phase_times()->_update_rs_processed_buffers, update_rs_time_goal_ms); + adjust_concurrent_refinement(phase_times()->average_last_update_rs_time(), + phase_times()->sum_last_update_rs_processed_buffers(), update_rs_time_goal_ms); _collectionSetChooser->verify(); } @@ -1153,7 +1146,11 @@ proper_unit_for_byte_size((bytes)) void G1CollectorPolicy::print_heap_transition() { - if (G1Log::finer()) { + _g1->print_size_transition(gclog_or_tty, + _cur_collection_pause_used_at_start_bytes, _g1->used(), _g1->capacity()); +} + +void G1CollectorPolicy::print_detailed_heap_transition() { YoungList* young_list = _g1->young_list(); size_t eden_bytes = young_list->eden_used_bytes(); size_t survivor_bytes = young_list->survivor_used_bytes(); @@ -1180,11 +1177,6 @@ EXT_SIZE_PARAMS(capacity)); _prev_eden_capacity = eden_capacity; - } else if (G1Log::fine()) { - _g1->print_size_transition(gclog_or_tty, - _cur_collection_pause_used_at_start_bytes, - _g1->used(), _g1->capacity()); - } } void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time, @@ -1229,18 +1221,6 @@ } double -G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards) { - size_t rs_length = predict_rs_length_diff(); - size_t card_num; - if (gcs_are_young()) { - card_num = predict_young_card_num(rs_length); - } else { - card_num = predict_non_young_card_num(rs_length); - } - return predict_base_elapsed_time_ms(pending_cards, card_num); -} - -double G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards, size_t scanned_cards) { return @@ -1250,27 +1230,15 @@ } double -G1CollectorPolicy::predict_region_elapsed_time_ms(HeapRegion* hr, - bool young) { - size_t rs_length = hr->rem_set()->occupied(); +G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards) { + size_t rs_length = predict_rs_length_diff(); size_t card_num; if (gcs_are_young()) { card_num = predict_young_card_num(rs_length); } else { card_num = predict_non_young_card_num(rs_length); } - size_t bytes_to_copy = predict_bytes_to_copy(hr); - - double region_elapsed_time_ms = - predict_rs_scan_time_ms(card_num) + - predict_object_copy_time_ms(bytes_to_copy); - - if (young) - region_elapsed_time_ms += predict_young_other_time_ms(1); - else - region_elapsed_time_ms += predict_non_young_other_time_ms(1); - - return region_elapsed_time_ms; + return predict_base_elapsed_time_ms(pending_cards, card_num); } size_t G1CollectorPolicy::predict_bytes_to_copy(HeapRegion* hr) { @@ -1286,6 +1254,35 @@ return bytes_to_copy; } +double +G1CollectorPolicy::predict_region_elapsed_time_ms(HeapRegion* hr, + bool for_young_gc) { + size_t rs_length = hr->rem_set()->occupied(); + size_t card_num; + + // Predicting the number of cards is based on which type of GC + // we're predicting for. + if (for_young_gc) { + card_num = predict_young_card_num(rs_length); + } else { + card_num = predict_non_young_card_num(rs_length); + } + size_t bytes_to_copy = predict_bytes_to_copy(hr); + + double region_elapsed_time_ms = + predict_rs_scan_time_ms(card_num) + + predict_object_copy_time_ms(bytes_to_copy); + + // The prediction of the "other" time for this region is based + // upon the region type and NOT the GC type. + if (hr->is_young()) { + region_elapsed_time_ms += predict_young_other_time_ms(1); + } else { + region_elapsed_time_ms += predict_non_young_other_time_ms(1); + } + return region_elapsed_time_ms; +} + void G1CollectorPolicy::init_cset_region_lengths(uint eden_cset_region_length, uint survivor_cset_region_length) { @@ -1342,22 +1339,6 @@ } } -class CountCSClosure: public HeapRegionClosure { - G1CollectorPolicy* _g1_policy; -public: - CountCSClosure(G1CollectorPolicy* g1_policy) : - _g1_policy(g1_policy) {} - bool doHeapRegion(HeapRegion* r) { - _g1_policy->_bytes_in_collection_set_before_gc += r->used(); - return false; - } -}; - -void G1CollectorPolicy::count_CS_bytes_used() { - CountCSClosure cs_closure(this); - _g1->collection_set_iterate(&cs_closure); -} - void G1CollectorPolicy::print_tracing_info() const { _trace_gen0_time_data.print(); _trace_gen1_time_data.print(); @@ -1696,7 +1677,7 @@ // retiring the current allocation region) or a concurrent // refine thread (RSet sampling). - double region_elapsed_time_ms = predict_region_elapsed_time_ms(hr, true); + double region_elapsed_time_ms = predict_region_elapsed_time_ms(hr, gcs_are_young()); size_t used_bytes = hr->used(); _inc_cset_recorded_rs_lengths += rs_length; _inc_cset_predicted_elapsed_time_ms += region_elapsed_time_ms; @@ -1731,7 +1712,7 @@ _inc_cset_recorded_rs_lengths_diffs += rs_lengths_diff; double old_elapsed_time_ms = hr->predicted_elapsed_time_ms(); - double new_region_elapsed_time_ms = predict_region_elapsed_time_ms(hr, true); + double new_region_elapsed_time_ms = predict_region_elapsed_time_ms(hr, gcs_are_young()); double elapsed_ms_diff = new_region_elapsed_time_ms - old_elapsed_time_ms; _inc_cset_predicted_elapsed_time_ms_diffs += elapsed_ms_diff; @@ -1854,8 +1835,7 @@ } void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { - // Set this here - in case we're not doing young collections. - double non_young_start_time_sec = os::elapsedTime(); + double young_start_time_sec = os::elapsedTime(); YoungList* young_list = _g1->young_list(); finalize_incremental_cset_building(); @@ -1869,17 +1849,14 @@ double predicted_pause_time_ms = base_time_ms; double time_remaining_ms = target_pause_time_ms - base_time_ms; - ergo_verbose3(ErgoCSetConstruction | ErgoHigh, + ergo_verbose4(ErgoCSetConstruction | ErgoHigh, "start choosing CSet", + ergo_format_size("_pending_cards") ergo_format_ms("predicted base time") ergo_format_ms("remaining time") ergo_format_ms("target pause time"), - base_time_ms, time_remaining_ms, target_pause_time_ms); + _pending_cards, base_time_ms, time_remaining_ms, target_pause_time_ms); - HeapRegion* hr; - double young_start_time_sec = os::elapsedTime(); - - _collection_set_bytes_used_before = 0; _last_gc_was_young = gcs_are_young() ? true : false; if (_last_gc_was_young) { @@ -1895,7 +1872,8 @@ uint survivor_region_length = young_list->survivor_length(); uint eden_region_length = young_list->length() - survivor_region_length; init_cset_region_lengths(eden_region_length, survivor_region_length); - hr = young_list->first_survivor_region(); + + HeapRegion* hr = young_list->first_survivor_region(); while (hr != NULL) { assert(hr->is_survivor(), "badly formed young list"); hr->set_young(); @@ -1923,11 +1901,10 @@ set_recorded_rs_lengths(_inc_cset_recorded_rs_lengths); double young_end_time_sec = os::elapsedTime(); - phase_times()->_recorded_young_cset_choice_time_ms = - (young_end_time_sec - young_start_time_sec) * 1000.0; + phase_times()->record_young_cset_choice_time_ms((young_end_time_sec - young_start_time_sec) * 1000.0); - // We are doing young collections so reset this. - non_young_start_time_sec = young_end_time_sec; + // Set the start of the non-young choice time. + double non_young_start_time_sec = young_end_time_sec; if (!gcs_are_young()) { CollectionSetChooser* cset_chooser = _collectionSetChooser; @@ -1937,6 +1914,7 @@ uint expensive_region_num = 0; bool check_time_remaining = adaptive_young_list_length(); + HeapRegion* hr = cset_chooser->peek(); while (hr != NULL) { if (old_cset_region_length() >= max_old_cset_length) { @@ -1950,7 +1928,7 @@ break; } - double predicted_time_ms = predict_region_elapsed_time_ms(hr, false); + double predicted_time_ms = predict_region_elapsed_time_ms(hr, gcs_are_young()); if (check_time_remaining) { if (predicted_time_ms > time_remaining_ms) { // Too expensive for the current CSet. @@ -2025,8 +2003,6 @@ stop_incremental_cset_building(); - count_CS_bytes_used(); - ergo_verbose5(ErgoCSetConstruction, "finish choosing CSet", ergo_format_region("eden") @@ -2039,8 +2015,7 @@ predicted_pause_time_ms, target_pause_time_ms); double non_young_end_time_sec = os::elapsedTime(); - phase_times()->_recorded_non_young_cset_choice_time_ms = - (non_young_end_time_sec - non_young_start_time_sec) * 1000.0; + phase_times()->record_non_young_cset_choice_time_ms((non_young_end_time_sec - non_young_start_time_sec) * 1000.0); } void TraceGen0TimeData::record_start_collection(double time_to_stop_the_world_ms) { @@ -2059,25 +2034,25 @@ if(TraceGen0Time) { _total.add(pause_time_ms); _other.add(pause_time_ms - phase_times->accounted_time_ms()); - _root_region_scan_wait.add(phase_times->_root_region_scan_wait_time_ms); - _parallel.add(phase_times->_cur_collection_par_time_ms); - _ext_root_scan.add(phase_times->_ext_root_scan_time); - _satb_filtering.add(phase_times->_satb_filtering_time); - _update_rs.add(phase_times->_update_rs_time); - _scan_rs.add(phase_times->_scan_rs_time); - _obj_copy.add(phase_times->_obj_copy_time); - _termination.add(phase_times->_termination_time); + _root_region_scan_wait.add(phase_times->root_region_scan_wait_time_ms()); + _parallel.add(phase_times->cur_collection_par_time_ms()); + _ext_root_scan.add(phase_times->average_last_ext_root_scan_time()); + _satb_filtering.add(phase_times->average_last_satb_filtering_times_ms()); + _update_rs.add(phase_times->average_last_update_rs_time()); + _scan_rs.add(phase_times->average_last_scan_rs_time()); + _obj_copy.add(phase_times->average_last_obj_copy_time()); + _termination.add(phase_times->average_last_termination_time()); - double parallel_known_time = phase_times->_ext_root_scan_time + - phase_times->_satb_filtering_time + - phase_times->_update_rs_time + - phase_times->_scan_rs_time + - phase_times->_obj_copy_time + - + phase_times->_termination_time; + double parallel_known_time = phase_times->average_last_ext_root_scan_time() + + phase_times->average_last_satb_filtering_times_ms() + + phase_times->average_last_update_rs_time() + + phase_times->average_last_scan_rs_time() + + phase_times->average_last_obj_copy_time() + + + phase_times->average_last_termination_time(); - double parallel_other_time = phase_times->_cur_collection_par_time_ms - parallel_known_time; + double parallel_other_time = phase_times->cur_collection_par_time_ms() - parallel_known_time; _parallel_other.add(parallel_other_time); - _clear_ct.add(phase_times->_cur_clear_ct_time_ms); + _clear_ct.add(phase_times->cur_clear_ct_time_ms()); } }
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -228,7 +228,6 @@ TruncatedSeq* _alloc_rate_ms_seq; double _prev_collection_pause_end_ms; - TruncatedSeq* _pending_card_diff_seq; TruncatedSeq* _rs_length_diff_seq; TruncatedSeq* _cost_per_card_ms_seq; TruncatedSeq* _young_cards_per_entry_ratio_seq; @@ -295,7 +294,6 @@ double _pause_time_target_ms; size_t _pending_cards; - size_t _max_pending_cards; public: // Accessors @@ -325,28 +323,6 @@ _max_rs_lengths = rs_lengths; } - size_t predict_pending_card_diff() { - double prediction = get_new_neg_prediction(_pending_card_diff_seq); - if (prediction < 0.00001) { - return 0; - } else { - return (size_t) prediction; - } - } - - size_t predict_pending_cards() { - size_t max_pending_card_num = _g1->max_pending_card_num(); - size_t diff = predict_pending_card_diff(); - size_t prediction; - if (diff > max_pending_card_num) { - prediction = max_pending_card_num; - } else { - prediction = max_pending_card_num - diff; - } - - return prediction; - } - size_t predict_rs_length_diff() { return (size_t) get_new_prediction(_rs_length_diff_seq); } @@ -439,7 +415,7 @@ double predict_base_elapsed_time_ms(size_t pending_cards, size_t scanned_cards); size_t predict_bytes_to_copy(HeapRegion* hr); - double predict_region_elapsed_time_ms(HeapRegion* hr, bool young); + double predict_region_elapsed_time_ms(HeapRegion* hr, bool for_young_gc); void set_recorded_rs_lengths(size_t rs_lengths); @@ -495,12 +471,6 @@ } private: - size_t _bytes_in_collection_set_before_gc; - size_t _bytes_copied_during_gc; - - // Used to count used bytes in CS. - friend class CountCSClosure; - // Statistics kept per GC stoppage, pause or full. TruncatedSeq* _recent_prev_end_times_for_all_gcs_sec; @@ -514,9 +484,13 @@ // The number of bytes in the collection set before the pause. Set from // the incrementally built collection set at the start of an evacuation - // pause. + // pause, and incremented in finalize_cset() when adding old regions + // (if any) to the collection set. size_t _collection_set_bytes_used_before; + // The number of bytes copied during the GC. + size_t _bytes_copied_during_gc; + // The associated information that is maintained while the incremental // collection set is being built with young regions. Used to populate // the recorded info for the evacuation pause. @@ -646,9 +620,6 @@ bool predict_will_fit(uint young_length, double base_time_ms, uint base_free_regions, double target_pause_time_ms); - // Count the number of bytes used in the CS. - void count_CS_bytes_used(); - public: G1CollectorPolicy(); @@ -666,10 +637,6 @@ // higher, recalculate the young list target length prediction. void revise_young_list_target_length_if_necessary(); - size_t bytes_in_collection_set() { - return _bytes_in_collection_set_before_gc; - } - // This should be called after the heap is resized. void record_new_heap_size(uint new_number_of_regions); @@ -716,6 +683,7 @@ void record_collection_pause_end(double pause_time); void print_heap_transition(); + void print_detailed_heap_transition(); // Record the fact that a full collection occurred. void record_full_collection_start();
--- a/src/share/vm/gc_implementation/g1/g1ErgoVerbose.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/gc_implementation/g1/g1ErgoVerbose.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -125,6 +125,7 @@ #define ergo_format_double(_name_) ", " _name_ ": %1.2f" #define ergo_format_perc(_name_) ", " _name_ ": %1.2f %%" #define ergo_format_ms(_name_) ", " _name_ ": %1.2f ms" +#define ergo_format_size(_name_) ", " _name_ ": "SIZE_FORMAT // Double parameter format strings #define ergo_format_byte_perc(_name_) \
--- a/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -79,119 +79,145 @@ } }; +template <class T> +void WorkerDataArray<T>::print(int level, const char* title) { + if (_length == 1) { + // No need for min, max, average and sum for only one worker + LineBuffer buf(level); + buf.append("[%s: ", title); + buf.append(_print_format, _data[0]); + buf.append_and_print_cr("]"); + return; + } + + T min = _data[0]; + T max = _data[0]; + T sum = 0; + + LineBuffer buf(level); + buf.append("[%s:", title); + for (uint i = 0; i < _length; ++i) { + T val = _data[i]; + min = MIN2(val, min); + max = MAX2(val, max); + sum += val; + if (G1Log::finest()) { + buf.append(" "); + buf.append(_print_format, val); + } + } + + if (G1Log::finest()) { + buf.append_and_print_cr(""); + } + + double avg = (double)sum / (double)_length; + buf.append(" Min: "); + buf.append(_print_format, min); + buf.append(", Avg: "); + buf.append("%.1lf", avg); // Always print average as a double + buf.append(", Max: "); + buf.append(_print_format, max); + buf.append(", Diff: "); + buf.append(_print_format, max - min); + if (_print_sum) { + // for things like the start and end times the sum is not + // that relevant + buf.append(", Sum: "); + buf.append(_print_format, sum); + } + buf.append_and_print_cr("]"); +} + +#ifdef ASSERT + +template <class T> +void WorkerDataArray<T>::reset() { + for (uint i = 0; i < _length; i++) { + _data[i] = (T)-1; + } +} + +template <class T> +void WorkerDataArray<T>::verify() { + for (uint i = 0; i < _length; i++) { + assert(_data[i] >= (T)0, err_msg("Invalid data for worker %d", i)); + } +} + +#endif + G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : _max_gc_threads(max_gc_threads), _min_clear_cc_time_ms(-1.0), _max_clear_cc_time_ms(-1.0), _cur_clear_cc_time_ms(0.0), _cum_clear_cc_time_ms(0.0), - _num_cc_clears(0L) + _num_cc_clears(0L), + _last_gc_worker_start_times_ms(_max_gc_threads, "%.1lf", false), + _last_ext_root_scan_times_ms(_max_gc_threads, "%.1lf"), + _last_satb_filtering_times_ms(_max_gc_threads, "%.1lf"), + _last_update_rs_times_ms(_max_gc_threads, "%.1lf"), + _last_update_rs_processed_buffers(_max_gc_threads, "%d"), + _last_scan_rs_times_ms(_max_gc_threads, "%.1lf"), + _last_obj_copy_times_ms(_max_gc_threads, "%.1lf"), + _last_termination_times_ms(_max_gc_threads, "%.1lf"), + _last_termination_attempts(_max_gc_threads, SIZE_FORMAT), + _last_gc_worker_end_times_ms(_max_gc_threads, "%.1lf", false), + _last_gc_worker_times_ms(_max_gc_threads, "%.1lf"), + _last_gc_worker_other_times_ms(_max_gc_threads, "%.1lf") { assert(max_gc_threads > 0, "Must have some GC threads"); - _par_last_gc_worker_start_times_ms = new double[_max_gc_threads]; - _par_last_ext_root_scan_times_ms = new double[_max_gc_threads]; - _par_last_satb_filtering_times_ms = new double[_max_gc_threads]; - _par_last_update_rs_times_ms = new double[_max_gc_threads]; - _par_last_update_rs_processed_buffers = new double[_max_gc_threads]; - _par_last_scan_rs_times_ms = new double[_max_gc_threads]; - _par_last_obj_copy_times_ms = new double[_max_gc_threads]; - _par_last_termination_times_ms = new double[_max_gc_threads]; - _par_last_termination_attempts = new double[_max_gc_threads]; - _par_last_gc_worker_end_times_ms = new double[_max_gc_threads]; - _par_last_gc_worker_times_ms = new double[_max_gc_threads]; - _par_last_gc_worker_other_times_ms = new double[_max_gc_threads]; } -void G1GCPhaseTimes::note_gc_start(double pause_start_time_sec, uint active_gc_threads, - bool is_young_gc, bool is_initial_mark_gc, GCCause::Cause gc_cause) { +void G1GCPhaseTimes::note_gc_start(uint active_gc_threads) { assert(active_gc_threads > 0, "The number of threads must be > 0"); assert(active_gc_threads <= _max_gc_threads, "The number of active threads must be <= the max nubmer of threads"); _active_gc_threads = active_gc_threads; - _pause_start_time_sec = pause_start_time_sec; - _is_young_gc = is_young_gc; - _is_initial_mark_gc = is_initial_mark_gc; - _gc_cause = gc_cause; -#ifdef ASSERT - // initialise the timing data to something well known so that we can spot - // if something is not set properly - - for (uint i = 0; i < _max_gc_threads; ++i) { - _par_last_gc_worker_start_times_ms[i] = -1234.0; - _par_last_ext_root_scan_times_ms[i] = -1234.0; - _par_last_satb_filtering_times_ms[i] = -1234.0; - _par_last_update_rs_times_ms[i] = -1234.0; - _par_last_update_rs_processed_buffers[i] = -1234.0; - _par_last_scan_rs_times_ms[i] = -1234.0; - _par_last_obj_copy_times_ms[i] = -1234.0; - _par_last_termination_times_ms[i] = -1234.0; - _par_last_termination_attempts[i] = -1234.0; - _par_last_gc_worker_end_times_ms[i] = -1234.0; - _par_last_gc_worker_times_ms[i] = -1234.0; - _par_last_gc_worker_other_times_ms[i] = -1234.0; - } -#endif + _last_gc_worker_start_times_ms.reset(); + _last_ext_root_scan_times_ms.reset(); + _last_satb_filtering_times_ms.reset(); + _last_update_rs_times_ms.reset(); + _last_update_rs_processed_buffers.reset(); + _last_scan_rs_times_ms.reset(); + _last_obj_copy_times_ms.reset(); + _last_termination_times_ms.reset(); + _last_termination_attempts.reset(); + _last_gc_worker_end_times_ms.reset(); + _last_gc_worker_times_ms.reset(); + _last_gc_worker_other_times_ms.reset(); } -void G1GCPhaseTimes::note_gc_end(double pause_end_time_sec) { - if (G1Log::fine()) { - double pause_time_ms = (pause_end_time_sec - _pause_start_time_sec) * MILLIUNITS; +void G1GCPhaseTimes::note_gc_end() { + _last_gc_worker_start_times_ms.verify(); + _last_ext_root_scan_times_ms.verify(); + _last_satb_filtering_times_ms.verify(); + _last_update_rs_times_ms.verify(); + _last_update_rs_processed_buffers.verify(); + _last_scan_rs_times_ms.verify(); + _last_obj_copy_times_ms.verify(); + _last_termination_times_ms.verify(); + _last_termination_attempts.verify(); + _last_gc_worker_end_times_ms.verify(); for (uint i = 0; i < _active_gc_threads; i++) { - _par_last_gc_worker_times_ms[i] = _par_last_gc_worker_end_times_ms[i] - - _par_last_gc_worker_start_times_ms[i]; + double worker_time = _last_gc_worker_end_times_ms.get(i) - _last_gc_worker_start_times_ms.get(i); + _last_gc_worker_times_ms.set(i, worker_time); - double worker_known_time = _par_last_ext_root_scan_times_ms[i] + - _par_last_satb_filtering_times_ms[i] + - _par_last_update_rs_times_ms[i] + - _par_last_scan_rs_times_ms[i] + - _par_last_obj_copy_times_ms[i] + - _par_last_termination_times_ms[i]; + double worker_known_time = _last_ext_root_scan_times_ms.get(i) + + _last_satb_filtering_times_ms.get(i) + + _last_update_rs_times_ms.get(i) + + _last_scan_rs_times_ms.get(i) + + _last_obj_copy_times_ms.get(i) + + _last_termination_times_ms.get(i); - _par_last_gc_worker_other_times_ms[i] = _par_last_gc_worker_times_ms[i] - - worker_known_time; + double worker_other_time = worker_time - worker_known_time; + _last_gc_worker_other_times_ms.set(i, worker_other_time); } - print(pause_time_ms); - } - -} - -void G1GCPhaseTimes::print_par_stats(int level, - const char* str, - double* data, - bool showDecimals) { - double min = data[0], max = data[0]; - double total = 0.0; - LineBuffer buf(level); - buf.append("[%s (ms):", str); - for (uint i = 0; i < _active_gc_threads; ++i) { - double val = data[i]; - if (val < min) - min = val; - if (val > max) - max = val; - total += val; - if (G1Log::finest()) { - if (showDecimals) { - buf.append(" %.1lf", val); - } else { - buf.append(" %d", (int)val); - } - } - } - - if (G1Log::finest()) { - buf.append_and_print_cr(""); - } - double avg = total / (double) _active_gc_threads; - if (showDecimals) { - buf.append_and_print_cr(" Min: %.1lf, Avg: %.1lf, Max: %.1lf, Diff: %.1lf, Sum: %.1lf]", - min, avg, max, max - min, total); - } else { - buf.append_and_print_cr(" Min: %d, Avg: %d, Max: %d, Diff: %d, Sum: %d]", - (int)min, (int)avg, (int)max, (int)max - (int)min, (int)total); - } + _last_gc_worker_times_ms.verify(); + _last_gc_worker_other_times_ms.verify(); } void G1GCPhaseTimes::print_stats(int level, const char* str, double value) { @@ -202,73 +228,6 @@ LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %d]", str, value, workers); } -void G1GCPhaseTimes::print_stats(int level, const char* str, int value) { - LineBuffer(level).append_and_print_cr("[%s: %d]", str, value); -} - -double G1GCPhaseTimes::avg_value(double* data) { - if (G1CollectedHeap::use_parallel_gc_threads()) { - double ret = 0.0; - for (uint i = 0; i < _active_gc_threads; ++i) { - ret += data[i]; - } - return ret / (double) _active_gc_threads; - } else { - return data[0]; - } -} - -double G1GCPhaseTimes::max_value(double* data) { - if (G1CollectedHeap::use_parallel_gc_threads()) { - double ret = data[0]; - for (uint i = 1; i < _active_gc_threads; ++i) { - if (data[i] > ret) { - ret = data[i]; - } - } - return ret; - } else { - return data[0]; - } -} - -double G1GCPhaseTimes::sum_of_values(double* data) { - if (G1CollectedHeap::use_parallel_gc_threads()) { - double sum = 0.0; - for (uint i = 0; i < _active_gc_threads; i++) { - sum += data[i]; - } - return sum; - } else { - return data[0]; - } -} - -double G1GCPhaseTimes::max_sum(double* data1, double* data2) { - double ret = data1[0] + data2[0]; - - if (G1CollectedHeap::use_parallel_gc_threads()) { - for (uint i = 1; i < _active_gc_threads; ++i) { - double data = data1[i] + data2[i]; - if (data > ret) { - ret = data; - } - } - } - return ret; -} - -void G1GCPhaseTimes::collapse_par_times() { - _ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms); - _satb_filtering_time = avg_value(_par_last_satb_filtering_times_ms); - _update_rs_time = avg_value(_par_last_update_rs_times_ms); - _update_rs_processed_buffers = - sum_of_values(_par_last_update_rs_processed_buffers); - _scan_rs_time = avg_value(_par_last_scan_rs_times_ms); - _obj_copy_time = avg_value(_par_last_obj_copy_times_ms); - _termination_time = avg_value(_par_last_termination_times_ms); -} - double G1GCPhaseTimes::accounted_time_ms() { // Subtract the root region scanning wait time. It's initialized to // zero at the start of the pause. @@ -286,58 +245,37 @@ return misc_time_ms; } -void G1GCPhaseTimes::print(double pause_time_ms) { - - if (PrintGCTimeStamps) { - gclog_or_tty->stamp(); - gclog_or_tty->print(": "); - } - - GCCauseString gc_cause_str = GCCauseString("GC pause", _gc_cause) - .append(_is_young_gc ? " (young)" : " (mixed)") - .append(_is_initial_mark_gc ? " (initial-mark)" : ""); - gclog_or_tty->print_cr("[%s, %3.7f secs]", (const char*)gc_cause_str, pause_time_ms / 1000.0); - - if (!G1Log::finer()) { - return; - } - +void G1GCPhaseTimes::print(double pause_time_sec) { if (_root_region_scan_wait_time_ms > 0.0) { print_stats(1, "Root Region Scan Waiting", _root_region_scan_wait_time_ms); } if (G1CollectedHeap::use_parallel_gc_threads()) { print_stats(1, "Parallel Time", _cur_collection_par_time_ms, _active_gc_threads); - print_par_stats(2, "GC Worker Start", _par_last_gc_worker_start_times_ms); - print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms); - if (_satb_filtering_time > 0.0) { - print_par_stats(2, "SATB Filtering", _par_last_satb_filtering_times_ms); + _last_gc_worker_start_times_ms.print(2, "GC Worker Start (ms)"); + _last_ext_root_scan_times_ms.print(2, "Ext Root Scanning (ms)"); + if (_last_satb_filtering_times_ms.sum() > 0.0) { + _last_satb_filtering_times_ms.print(2, "SATB Filtering (ms)"); } - print_par_stats(2, "Update RS", _par_last_update_rs_times_ms); - if (G1Log::finest()) { - print_par_stats(3, "Processed Buffers", _par_last_update_rs_processed_buffers, - false /* showDecimals */); - } - print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms); - print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms); - print_par_stats(2, "Termination", _par_last_termination_times_ms); + _last_update_rs_times_ms.print(2, "Update RS (ms)"); + _last_update_rs_processed_buffers.print(3, "Processed Buffers"); + _last_scan_rs_times_ms.print(2, "Scan RS (ms)"); + _last_obj_copy_times_ms.print(2, "Object Copy (ms)"); + _last_termination_times_ms.print(2, "Termination (ms)"); if (G1Log::finest()) { - print_par_stats(3, "Termination Attempts", _par_last_termination_attempts, - false /* showDecimals */); + _last_termination_attempts.print(3, "Termination Attempts"); } - print_par_stats(2, "GC Worker Other", _par_last_gc_worker_other_times_ms); - print_par_stats(2, "GC Worker Total", _par_last_gc_worker_times_ms); - print_par_stats(2, "GC Worker End", _par_last_gc_worker_end_times_ms); + _last_gc_worker_other_times_ms.print(2, "GC Worker Other (ms)"); + _last_gc_worker_times_ms.print(2, "GC Worker Total (ms)"); + _last_gc_worker_end_times_ms.print(2, "GC Worker End (ms)"); } else { - print_stats(1, "Ext Root Scanning", _ext_root_scan_time); - if (_satb_filtering_time > 0.0) { - print_stats(1, "SATB Filtering", _satb_filtering_time); + _last_ext_root_scan_times_ms.print(1, "Ext Root Scanning (ms)"); + if (_last_satb_filtering_times_ms.sum() > 0.0) { + _last_satb_filtering_times_ms.print(1, "SATB Filtering (ms)"); } - print_stats(1, "Update RS", _update_rs_time); - if (G1Log::finest()) { - print_stats(2, "Processed Buffers", (int)_update_rs_processed_buffers); - } - print_stats(1, "Scan RS", _scan_rs_time); - print_stats(1, "Object Copying", _obj_copy_time); + _last_update_rs_times_ms.print(1, "Update RS (ms)"); + _last_update_rs_processed_buffers.print(2, "Processed Buffers"); + _last_scan_rs_times_ms.print(1, "Scan RS (ms)"); + _last_obj_copy_times_ms.print(1, "Object Copy (ms)"); } print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms); print_stats(1, "Clear CT", _cur_clear_ct_time_ms); @@ -350,8 +288,11 @@ print_stats(1, "Avg Clear CC", _cum_clear_cc_time_ms / ((double)_num_cc_clears)); } } - double misc_time_ms = pause_time_ms - accounted_time_ms(); + double misc_time_ms = pause_time_sec * MILLIUNITS - accounted_time_ms(); print_stats(1, "Other", misc_time_ms); + if (_cur_verify_before_time_ms > 0.0) { + print_stats(2, "Verify Before", _cur_verify_before_time_ms); + } print_stats(2, "Choose CSet", (_recorded_young_cset_choice_time_ms + _recorded_non_young_cset_choice_time_ms)); @@ -360,6 +301,9 @@ print_stats(2, "Free CSet", (_recorded_young_free_cset_time_ms + _recorded_non_young_free_cset_time_ms)); + if (_cur_verify_after_time_ms > 0.0) { + print_stats(2, "Verify After", _cur_verify_after_time_ms); + } } void G1GCPhaseTimes::record_cc_clear_time_ms(double ms) {
--- a/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -28,52 +28,109 @@ #include "memory/allocation.hpp" #include "gc_interface/gcCause.hpp" +template <class T> +class WorkerDataArray : public CHeapObj<mtGC> { + T* _data; + uint _length; + const char* _print_format; + bool _print_sum; + + // We are caching the sum and average to only have to calculate them once. + // This is not done in an MT-safe way. It is intetened to allow single + // threaded code to call sum() and average() multiple times in any order + // without having to worry about the cost. + bool _has_new_data; + T _sum; + double _average; + + public: + WorkerDataArray(uint length, const char* print_format, bool print_sum = true) : + _length(length), _print_format(print_format), _print_sum(print_sum), _has_new_data(true) { + assert(length > 0, "Must have some workers to store data for"); + _data = NEW_C_HEAP_ARRAY(T, _length, mtGC); + } + + ~WorkerDataArray() { + FREE_C_HEAP_ARRAY(T, _data, mtGC); + } + + void set(uint worker_i, T value) { + assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length)); + assert(_data[worker_i] == (T)-1, err_msg("Overwriting data for worker %d", worker_i)); + _data[worker_i] = value; + _has_new_data = true; + } + + T get(uint worker_i) { + assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length)); + assert(_data[worker_i] != (T)-1, err_msg("No data to add to for worker %d", worker_i)); + return _data[worker_i]; + } + + void add(uint worker_i, T value) { + assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length)); + assert(_data[worker_i] != (T)-1, err_msg("No data to add to for worker %d", worker_i)); + _data[worker_i] += value; + _has_new_data = true; + } + + double average(){ + if (_has_new_data) { + calculate_totals(); + } + return _average; + } + + T sum() { + if (_has_new_data) { + calculate_totals(); + } + return _sum; + } + + void print(int level, const char* title); + + void reset() PRODUCT_RETURN; + void verify() PRODUCT_RETURN; + + private: + + void calculate_totals(){ + _sum = (T)0; + for (uint i = 0; i < _length; ++i) { + _sum += _data[i]; + } + _average = (double)_sum / (double)_length; + _has_new_data = false; + } +}; + class G1GCPhaseTimes : public CHeapObj<mtGC> { - friend class G1CollectorPolicy; - friend class TraceGen0TimeData; private: uint _active_gc_threads; uint _max_gc_threads; - GCCause::Cause _gc_cause; - bool _is_young_gc; - bool _is_initial_mark_gc; - - double _pause_start_time_sec; - - double* _par_last_gc_worker_start_times_ms; - double* _par_last_ext_root_scan_times_ms; - double* _par_last_satb_filtering_times_ms; - double* _par_last_update_rs_times_ms; - double* _par_last_update_rs_processed_buffers; - double* _par_last_scan_rs_times_ms; - double* _par_last_obj_copy_times_ms; - double* _par_last_termination_times_ms; - double* _par_last_termination_attempts; - double* _par_last_gc_worker_end_times_ms; - double* _par_last_gc_worker_times_ms; - double* _par_last_gc_worker_other_times_ms; + WorkerDataArray<double> _last_gc_worker_start_times_ms; + WorkerDataArray<double> _last_ext_root_scan_times_ms; + WorkerDataArray<double> _last_satb_filtering_times_ms; + WorkerDataArray<double> _last_update_rs_times_ms; + WorkerDataArray<int> _last_update_rs_processed_buffers; + WorkerDataArray<double> _last_scan_rs_times_ms; + WorkerDataArray<double> _last_obj_copy_times_ms; + WorkerDataArray<double> _last_termination_times_ms; + WorkerDataArray<size_t> _last_termination_attempts; + WorkerDataArray<double> _last_gc_worker_end_times_ms; + WorkerDataArray<double> _last_gc_worker_times_ms; + WorkerDataArray<double> _last_gc_worker_other_times_ms; double _cur_collection_par_time_ms; - double _cur_collection_code_root_fixup_time_ms; double _cur_clear_ct_time_ms; double _cur_ref_proc_time_ms; double _cur_ref_enq_time_ms; - // Helper methods for detailed logging - void print_par_stats(int level, const char* str, double* data, bool showDecimals = true); - void print_stats(int level, const char* str, double value); - void print_stats(int level, const char* str, double value, int workers); - void print_stats(int level, const char* str, int value); - double avg_value(double* data); - double max_value(double* data); - double sum_of_values(double* data); - double max_sum(double* data1, double* data2); - double accounted_time_ms(); - // Card Table Count Cache stats double _min_clear_cc_time_ms; // min double _max_clear_cc_time_ms; // max @@ -81,19 +138,6 @@ double _cum_clear_cc_time_ms; // cummulative clearing time jlong _num_cc_clears; // number of times the card count cache has been cleared - // The following insance variables are directly accessed by G1CollectorPolicy - // and TraceGen0TimeData. This is why those classes are declared friends. - // An alternative is to add getters and setters for all of these fields. - // It might also be possible to restructure the code to reduce these - // dependencies. - double _ext_root_scan_time; - double _satb_filtering_time; - double _update_rs_time; - double _update_rs_processed_buffers; - double _scan_rs_time; - double _obj_copy_time; - double _termination_time; - double _cur_collection_start_sec; double _root_region_scan_wait_time_ms; @@ -103,79 +147,58 @@ double _recorded_young_free_cset_time_ms; double _recorded_non_young_free_cset_time_ms; - void print(double pause_time_ms); + double _cur_verify_before_time_ms; + double _cur_verify_after_time_ms; + + // Helper methods for detailed logging + void print_stats(int level, const char* str, double value); + void print_stats(int level, const char* str, double value, int workers); public: G1GCPhaseTimes(uint max_gc_threads); - void note_gc_start(double pause_start_time_sec, uint active_gc_threads, - bool is_young_gc, bool is_initial_mark_gc, GCCause::Cause gc_cause); - void note_gc_end(double pause_end_time_sec); - void collapse_par_times(); + void note_gc_start(uint active_gc_threads); + void note_gc_end(); + void print(double pause_time_sec); void record_gc_worker_start_time(uint worker_i, double ms) { - assert(worker_i >= 0, "worker index must be > 0"); - assert(worker_i < _active_gc_threads, "worker index out of bounds"); - _par_last_gc_worker_start_times_ms[worker_i] = ms; + _last_gc_worker_start_times_ms.set(worker_i, ms); } void record_ext_root_scan_time(uint worker_i, double ms) { - assert(worker_i >= 0, "worker index must be > 0"); - assert(worker_i < _active_gc_threads, "worker index out of bounds"); - _par_last_ext_root_scan_times_ms[worker_i] = ms; + _last_ext_root_scan_times_ms.set(worker_i, ms); } void record_satb_filtering_time(uint worker_i, double ms) { - assert(worker_i >= 0, "worker index must be > 0"); - assert(worker_i < _active_gc_threads, "worker index out of bounds"); - _par_last_satb_filtering_times_ms[worker_i] = ms; + _last_satb_filtering_times_ms.set(worker_i, ms); } void record_update_rs_time(uint worker_i, double ms) { - assert(worker_i >= 0, "worker index must be > 0"); - assert(worker_i < _active_gc_threads, "worker index out of bounds"); - _par_last_update_rs_times_ms[worker_i] = ms; + _last_update_rs_times_ms.set(worker_i, ms); } - void record_update_rs_processed_buffers (uint worker_i, - double processed_buffers) { - assert(worker_i >= 0, "worker index must be > 0"); - assert(worker_i < _active_gc_threads, "worker index out of bounds"); - _par_last_update_rs_processed_buffers[worker_i] = processed_buffers; + void record_update_rs_processed_buffers(uint worker_i, int processed_buffers) { + _last_update_rs_processed_buffers.set(worker_i, processed_buffers); } void record_scan_rs_time(uint worker_i, double ms) { - assert(worker_i >= 0, "worker index must be > 0"); - assert(worker_i < _active_gc_threads, "worker index out of bounds"); - _par_last_scan_rs_times_ms[worker_i] = ms; - } - - void reset_obj_copy_time(uint worker_i) { - assert(worker_i >= 0, "worker index must be > 0"); - assert(worker_i < _active_gc_threads, "worker index out of bounds"); - _par_last_obj_copy_times_ms[worker_i] = 0.0; - } - - void reset_obj_copy_time() { - reset_obj_copy_time(0); + _last_scan_rs_times_ms.set(worker_i, ms); } void record_obj_copy_time(uint worker_i, double ms) { - assert(worker_i >= 0, "worker index must be > 0"); - assert(worker_i < _active_gc_threads, "worker index out of bounds"); - _par_last_obj_copy_times_ms[worker_i] += ms; + _last_obj_copy_times_ms.set(worker_i, ms); + } + + void add_obj_copy_time(uint worker_i, double ms) { + _last_obj_copy_times_ms.add(worker_i, ms); } void record_termination(uint worker_i, double ms, size_t attempts) { - assert(worker_i >= 0, "worker index must be > 0"); - assert(worker_i < _active_gc_threads, "worker index out of bounds"); - _par_last_termination_times_ms[worker_i] = ms; - _par_last_termination_attempts[worker_i] = (double) attempts; + _last_termination_times_ms.set(worker_i, ms); + _last_termination_attempts.set(worker_i, attempts); } void record_gc_worker_end_time(uint worker_i, double ms) { - assert(worker_i >= 0, "worker index must be > 0"); - assert(worker_i < _active_gc_threads, "worker index out of bounds"); - _par_last_gc_worker_end_times_ms[worker_i] = ms; + _last_gc_worker_end_times_ms.set(worker_i, ms); } void record_clear_ct_time(double ms) { @@ -211,6 +234,88 @@ void record_non_young_free_cset_time_ms(double time_ms) { _recorded_non_young_free_cset_time_ms = time_ms; } + + void record_young_cset_choice_time_ms(double time_ms) { + _recorded_young_cset_choice_time_ms = time_ms; + } + + void record_non_young_cset_choice_time_ms(double time_ms) { + _recorded_non_young_cset_choice_time_ms = time_ms; + } + + void record_cur_collection_start_sec(double time_ms) { + _cur_collection_start_sec = time_ms; + } + + void record_verify_before_time_ms(double time_ms) { + _cur_verify_before_time_ms = time_ms; + } + + void record_verify_after_time_ms(double time_ms) { + _cur_verify_after_time_ms = time_ms; + } + + double accounted_time_ms(); + + double cur_collection_start_sec() { + return _cur_collection_start_sec; + } + + double cur_collection_par_time_ms() { + return _cur_collection_par_time_ms; + } + + double cur_clear_ct_time_ms() { + return _cur_clear_ct_time_ms; + } + + double root_region_scan_wait_time_ms() { + return _root_region_scan_wait_time_ms; + } + + double young_cset_choice_time_ms() { + return _recorded_young_cset_choice_time_ms; + } + + double young_free_cset_time_ms() { + return _recorded_young_free_cset_time_ms; + } + + double non_young_cset_choice_time_ms() { + return _recorded_non_young_cset_choice_time_ms; + } + + double non_young_free_cset_time_ms() { + return _recorded_non_young_free_cset_time_ms; + } + + double average_last_update_rs_time() { + return _last_update_rs_times_ms.average(); + } + + int sum_last_update_rs_processed_buffers() { + return _last_update_rs_processed_buffers.sum(); + } + + double average_last_scan_rs_time(){ + return _last_scan_rs_times_ms.average(); + } + + double average_last_obj_copy_time() { + return _last_obj_copy_times_ms.average(); + } + + double average_last_termination_time() { + return _last_termination_times_ms.average(); + } + + double average_last_ext_root_scan_time() { + return _last_ext_root_scan_times_ms.average(); + } + + double average_last_satb_filtering_times_ms() { + return _last_satb_filtering_times_ms.average(); + } }; #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
--- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -324,7 +324,7 @@ if (G1UseParallelRSetUpdating || (worker_i == 0)) { updateRS(&into_cset_dcq, worker_i); } else { - _g1p->phase_times()->record_update_rs_processed_buffers(worker_i, 0.0); + _g1p->phase_times()->record_update_rs_processed_buffers(worker_i, 0); _g1p->phase_times()->record_update_rs_time(worker_i, 0.0); } if (G1UseParallelRSetScanning || (worker_i == 0)) {
--- a/src/share/vm/gc_implementation/g1/g1_globals.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -287,17 +287,17 @@ "The number of times we'll force an overflow during " \ "concurrent marking") \ \ - develop(uintx, G1DefaultMinNewGenPercent, 20, \ + experimental(uintx, G1DefaultMinNewGenPercent, 20, \ "Percentage (0-100) of the heap size to use as minimum " \ "young gen size.") \ \ - develop(uintx, G1DefaultMaxNewGenPercent, 80, \ + experimental(uintx, G1DefaultMaxNewGenPercent, 80, \ "Percentage (0-100) of the heap size to use as maximum " \ "young gen size.") \ \ - develop(uintx, G1OldCSetRegionLiveThresholdPercent, 90, \ + experimental(uintx, G1OldCSetRegionLiveThresholdPercent, 90, \ "Threshold for regions to be added to the collection set. " \ - "Regions with more live bytes that this will not be collected.") \ + "Regions with more live bytes than this will not be collected.") \ \ product(uintx, G1HeapWastePercent, 5, \ "Amount of space, expressed as a percentage of the heap size, " \ @@ -306,12 +306,40 @@ product(uintx, G1MixedGCCountTarget, 4, \ "The target number of mixed GCs after a marking cycle.") \ \ - develop(uintx, G1OldCSetRegionThresholdPercent, 10, \ + experimental(uintx, G1OldCSetRegionThresholdPercent, 10, \ "An upper bound for the number of old CSet regions expressed " \ "as a percentage of the heap size.") \ \ experimental(ccstr, G1LogLevel, NULL, \ - "Log level for G1 logging: fine, finer, finest") + "Log level for G1 logging: fine, finer, finest") \ + \ + notproduct(bool, G1EvacuationFailureALot, false, \ + "Force use of evacuation failure handling during certain " \ + "evacuation pauses") \ + \ + develop(uintx, G1EvacuationFailureALotCount, 1000, \ + "Number of successful evacuations between evacuation failures " \ + "occurring at object copying") \ + \ + develop(uintx, G1EvacuationFailureALotInterval, 5, \ + "Total collections between forced triggering of evacuation " \ + "failures") \ + \ + develop(bool, G1EvacuationFailureALotDuringConcMark, true, \ + "Force use of evacuation failure handling during evacuation " \ + "pauses when marking is in progress") \ + \ + develop(bool, G1EvacuationFailureALotDuringInitialMark, true, \ + "Force use of evacuation failure handling during initial mark " \ + "evacuation pauses") \ + \ + develop(bool, G1EvacuationFailureALotDuringYoungGC, true, \ + "Force use of evacuation failure handling during young " \ + "evacuation pauses") \ + \ + develop(bool, G1EvacuationFailureALotDuringMixedGC, true, \ + "Force use of evacuation failure handling during mixed " \ + "evacuation pauses") G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG)
--- a/src/share/vm/gc_implementation/g1/heapRegion.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -384,10 +384,17 @@ } void HeapRegion::calc_gc_efficiency() { + // GC efficiency is the ratio of how much space would be + // reclaimed over how long we predict it would take to reclaim it. G1CollectedHeap* g1h = G1CollectedHeap::heap(); G1CollectorPolicy* g1p = g1h->g1_policy(); - _gc_efficiency = (double) reclaimable_bytes() / - g1p->predict_region_elapsed_time_ms(this, false); + + // Retrieve a prediction of the elapsed time for this region for + // a mixed gc because the region will only be evacuated during a + // mixed gc. + double region_elapsed_time_ms = + g1p->predict_region_elapsed_time_ms(this, false /* for_young_gc */); + _gc_efficiency = (double) reclaimable_bytes() / region_elapsed_time_ms; } void HeapRegion::set_startsHumongous(HeapWord* new_top, HeapWord* new_end) {
--- a/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.cpp Fri Nov 09 13:32:53 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,344 +0,0 @@ -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "gc_implementation/parNew/parGCAllocBuffer.hpp" -#include "memory/sharedHeap.hpp" -#include "oops/arrayOop.hpp" -#include "oops/oop.inline.hpp" - -ParGCAllocBuffer::ParGCAllocBuffer(size_t desired_plab_sz_) : - _word_sz(desired_plab_sz_), _bottom(NULL), _top(NULL), - _end(NULL), _hard_end(NULL), - _retained(false), _retained_filler(), - _allocated(0), _wasted(0) -{ - assert (min_size() > AlignmentReserve, "Inconsistency!"); - // arrayOopDesc::header_size depends on command line initialization. - FillerHeaderSize = align_object_size(arrayOopDesc::header_size(T_INT)); - AlignmentReserve = oopDesc::header_size() > MinObjAlignment ? FillerHeaderSize : 0; -} - -size_t ParGCAllocBuffer::FillerHeaderSize; - -// If the minimum object size is greater than MinObjAlignment, we can -// end up with a shard at the end of the buffer that's smaller than -// the smallest object. We can't allow that because the buffer must -// look like it's full of objects when we retire it, so we make -// sure we have enough space for a filler int array object. -size_t ParGCAllocBuffer::AlignmentReserve; - -void ParGCAllocBuffer::retire(bool end_of_gc, bool retain) { - assert(!retain || end_of_gc, "Can only retain at GC end."); - if (_retained) { - // If the buffer had been retained shorten the previous filler object. - assert(_retained_filler.end() <= _top, "INVARIANT"); - CollectedHeap::fill_with_object(_retained_filler); - // Wasted space book-keeping, otherwise (normally) done in invalidate() - _wasted += _retained_filler.word_size(); - _retained = false; - } - assert(!end_of_gc || !_retained, "At this point, end_of_gc ==> !_retained."); - if (_top < _hard_end) { - CollectedHeap::fill_with_object(_top, _hard_end); - if (!retain) { - invalidate(); - } else { - // Is there wasted space we'd like to retain for the next GC? - if (pointer_delta(_end, _top) > FillerHeaderSize) { - _retained = true; - _retained_filler = MemRegion(_top, FillerHeaderSize); - _top = _top + FillerHeaderSize; - } else { - invalidate(); - } - } - } -} - -void ParGCAllocBuffer::flush_stats(PLABStats* stats) { - assert(ResizePLAB, "Wasted work"); - stats->add_allocated(_allocated); - stats->add_wasted(_wasted); - stats->add_unused(pointer_delta(_end, _top)); -} - -// Compute desired plab size and latch result for later -// use. This should be called once at the end of parallel -// scavenge; it clears the sensor accumulators. -void PLABStats::adjust_desired_plab_sz() { - assert(ResizePLAB, "Not set"); - if (_allocated == 0) { - assert(_unused == 0, "Inconsistency in PLAB stats"); - _allocated = 1; - } - double wasted_frac = (double)_unused/(double)_allocated; - size_t target_refills = (size_t)((wasted_frac*TargetSurvivorRatio)/ - TargetPLABWastePct); - if (target_refills == 0) { - target_refills = 1; - } - _used = _allocated - _wasted - _unused; - size_t plab_sz = _used/(target_refills*ParallelGCThreads); - if (PrintPLAB) gclog_or_tty->print(" (plab_sz = %d ", plab_sz); - // Take historical weighted average - _filter.sample(plab_sz); - // Clip from above and below, and align to object boundary - plab_sz = MAX2(min_size(), (size_t)_filter.average()); - plab_sz = MIN2(max_size(), plab_sz); - plab_sz = align_object_size(plab_sz); - // Latch the result - if (PrintPLAB) gclog_or_tty->print(" desired_plab_sz = %d) ", plab_sz); - if (ResizePLAB) { - _desired_plab_sz = plab_sz; - } - // Now clear the accumulators for next round: - // note this needs to be fixed in the case where we - // are retaining across scavenges. FIX ME !!! XXX - _allocated = 0; - _wasted = 0; - _unused = 0; -} - -#ifndef PRODUCT -void ParGCAllocBuffer::print() { - gclog_or_tty->print("parGCAllocBuffer: _bottom: %p _top: %p _end: %p _hard_end: %p" - "_retained: %c _retained_filler: [%p,%p)\n", - _bottom, _top, _end, _hard_end, - "FT"[_retained], _retained_filler.start(), _retained_filler.end()); -} -#endif // !PRODUCT - -const size_t ParGCAllocBufferWithBOT::ChunkSizeInWords = -MIN2(CardTableModRefBS::par_chunk_heapword_alignment(), - ((size_t)Generation::GenGrain)/HeapWordSize); -const size_t ParGCAllocBufferWithBOT::ChunkSizeInBytes = -MIN2(CardTableModRefBS::par_chunk_heapword_alignment() * HeapWordSize, - (size_t)Generation::GenGrain); - -ParGCAllocBufferWithBOT::ParGCAllocBufferWithBOT(size_t word_sz, - BlockOffsetSharedArray* bsa) : - ParGCAllocBuffer(word_sz), - _bsa(bsa), - _bt(bsa, MemRegion(_bottom, _hard_end)), - _true_end(_hard_end) -{} - -// The buffer comes with its own BOT, with a shared (obviously) underlying -// BlockOffsetSharedArray. We manipulate this BOT in the normal way -// as we would for any contiguous space. However, on accasion we -// need to do some buffer surgery at the extremities before we -// start using the body of the buffer for allocations. Such surgery -// (as explained elsewhere) is to prevent allocation on a card that -// is in the process of being walked concurrently by another GC thread. -// When such surgery happens at a point that is far removed (to the -// right of the current allocation point, top), we use the "contig" -// parameter below to directly manipulate the shared array without -// modifying the _next_threshold state in the BOT. -void ParGCAllocBufferWithBOT::fill_region_with_block(MemRegion mr, - bool contig) { - CollectedHeap::fill_with_object(mr); - if (contig) { - _bt.alloc_block(mr.start(), mr.end()); - } else { - _bt.BlockOffsetArray::alloc_block(mr.start(), mr.end()); - } -} - -HeapWord* ParGCAllocBufferWithBOT::allocate_slow(size_t word_sz) { - HeapWord* res = NULL; - if (_true_end > _hard_end) { - assert((HeapWord*)align_size_down(intptr_t(_hard_end), - ChunkSizeInBytes) == _hard_end, - "or else _true_end should be equal to _hard_end"); - assert(_retained, "or else _true_end should be equal to _hard_end"); - assert(_retained_filler.end() <= _top, "INVARIANT"); - CollectedHeap::fill_with_object(_retained_filler); - if (_top < _hard_end) { - fill_region_with_block(MemRegion(_top, _hard_end), true); - } - HeapWord* next_hard_end = MIN2(_true_end, _hard_end + ChunkSizeInWords); - _retained_filler = MemRegion(_hard_end, FillerHeaderSize); - _bt.alloc_block(_retained_filler.start(), _retained_filler.word_size()); - _top = _retained_filler.end(); - _hard_end = next_hard_end; - _end = _hard_end - AlignmentReserve; - res = ParGCAllocBuffer::allocate(word_sz); - if (res != NULL) { - _bt.alloc_block(res, word_sz); - } - } - return res; -} - -void -ParGCAllocBufferWithBOT::undo_allocation(HeapWord* obj, size_t word_sz) { - ParGCAllocBuffer::undo_allocation(obj, word_sz); - // This may back us up beyond the previous threshold, so reset. - _bt.set_region(MemRegion(_top, _hard_end)); - _bt.initialize_threshold(); -} - -void ParGCAllocBufferWithBOT::retire(bool end_of_gc, bool retain) { - assert(!retain || end_of_gc, "Can only retain at GC end."); - if (_retained) { - // We're about to make the retained_filler into a block. - _bt.BlockOffsetArray::alloc_block(_retained_filler.start(), - _retained_filler.end()); - } - // Reset _hard_end to _true_end (and update _end) - if (retain && _hard_end != NULL) { - assert(_hard_end <= _true_end, "Invariant."); - _hard_end = _true_end; - _end = MAX2(_top, _hard_end - AlignmentReserve); - assert(_end <= _hard_end, "Invariant."); - } - _true_end = _hard_end; - HeapWord* pre_top = _top; - - ParGCAllocBuffer::retire(end_of_gc, retain); - // Now any old _retained_filler is cut back to size, the free part is - // filled with a filler object, and top is past the header of that - // object. - - if (retain && _top < _end) { - assert(end_of_gc && retain, "Or else retain should be false."); - // If the lab does not start on a card boundary, we don't want to - // allocate onto that card, since that might lead to concurrent - // allocation and card scanning, which we don't support. So we fill - // the first card with a garbage object. - size_t first_card_index = _bsa->index_for(pre_top); - HeapWord* first_card_start = _bsa->address_for_index(first_card_index); - if (first_card_start < pre_top) { - HeapWord* second_card_start = - _bsa->inc_by_region_size(first_card_start); - - // Ensure enough room to fill with the smallest block - second_card_start = MAX2(second_card_start, pre_top + AlignmentReserve); - - // If the end is already in the first card, don't go beyond it! - // Or if the remainder is too small for a filler object, gobble it up. - if (_hard_end < second_card_start || - pointer_delta(_hard_end, second_card_start) < AlignmentReserve) { - second_card_start = _hard_end; - } - if (pre_top < second_card_start) { - MemRegion first_card_suffix(pre_top, second_card_start); - fill_region_with_block(first_card_suffix, true); - } - pre_top = second_card_start; - _top = pre_top; - _end = MAX2(_top, _hard_end - AlignmentReserve); - } - - // If the lab does not end on a card boundary, we don't want to - // allocate onto that card, since that might lead to concurrent - // allocation and card scanning, which we don't support. So we fill - // the last card with a garbage object. - size_t last_card_index = _bsa->index_for(_hard_end); - HeapWord* last_card_start = _bsa->address_for_index(last_card_index); - if (last_card_start < _hard_end) { - - // Ensure enough room to fill with the smallest block - last_card_start = MIN2(last_card_start, _hard_end - AlignmentReserve); - - // If the top is already in the last card, don't go back beyond it! - // Or if the remainder is too small for a filler object, gobble it up. - if (_top > last_card_start || - pointer_delta(last_card_start, _top) < AlignmentReserve) { - last_card_start = _top; - } - if (last_card_start < _hard_end) { - MemRegion last_card_prefix(last_card_start, _hard_end); - fill_region_with_block(last_card_prefix, false); - } - _hard_end = last_card_start; - _end = MAX2(_top, _hard_end - AlignmentReserve); - _true_end = _hard_end; - assert(_end <= _hard_end, "Invariant."); - } - - // At this point: - // 1) we had a filler object from the original top to hard_end. - // 2) We've filled in any partial cards at the front and back. - if (pre_top < _hard_end) { - // Now we can reset the _bt to do allocation in the given area. - MemRegion new_filler(pre_top, _hard_end); - fill_region_with_block(new_filler, false); - _top = pre_top + ParGCAllocBuffer::FillerHeaderSize; - // If there's no space left, don't retain. - if (_top >= _end) { - _retained = false; - invalidate(); - return; - } - _retained_filler = MemRegion(pre_top, _top); - _bt.set_region(MemRegion(_top, _hard_end)); - _bt.initialize_threshold(); - assert(_bt.threshold() > _top, "initialize_threshold failed!"); - - // There may be other reasons for queries into the middle of the - // filler object. When such queries are done in parallel with - // allocation, bad things can happen, if the query involves object - // iteration. So we ensure that such queries do not involve object - // iteration, by putting another filler object on the boundaries of - // such queries. One such is the object spanning a parallel card - // chunk boundary. - - // "chunk_boundary" is the address of the first chunk boundary less - // than "hard_end". - HeapWord* chunk_boundary = - (HeapWord*)align_size_down(intptr_t(_hard_end-1), ChunkSizeInBytes); - assert(chunk_boundary < _hard_end, "Or else above did not work."); - assert(pointer_delta(_true_end, chunk_boundary) >= AlignmentReserve, - "Consequence of last card handling above."); - - if (_top <= chunk_boundary) { - assert(_true_end == _hard_end, "Invariant."); - while (_top <= chunk_boundary) { - assert(pointer_delta(_hard_end, chunk_boundary) >= AlignmentReserve, - "Consequence of last card handling above."); - _bt.BlockOffsetArray::alloc_block(chunk_boundary, _hard_end); - CollectedHeap::fill_with_object(chunk_boundary, _hard_end); - _hard_end = chunk_boundary; - chunk_boundary -= ChunkSizeInWords; - } - _end = _hard_end - AlignmentReserve; - assert(_top <= _end, "Invariant."); - // Now reset the initial filler chunk so it doesn't overlap with - // the one(s) inserted above. - MemRegion new_filler(pre_top, _hard_end); - fill_region_with_block(new_filler, false); - } - } else { - _retained = false; - invalidate(); - } - } else { - assert(!end_of_gc || - (!_retained && _true_end == _hard_end), "Checking."); - } - assert(_end <= _hard_end, "Invariant."); - assert(_top < _end || _top == _hard_end, "Invariant"); -}
--- a/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp Fri Nov 09 13:32:53 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP -#define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP - -#include "memory/allocation.hpp" -#include "memory/blockOffsetTable.hpp" -#include "memory/threadLocalAllocBuffer.hpp" -#include "utilities/globalDefinitions.hpp" - -// Forward decl. - -class PLABStats; - -// A per-thread allocation buffer used during GC. -class ParGCAllocBuffer: public CHeapObj<mtGC> { -protected: - char head[32]; - size_t _word_sz; // in HeapWord units - HeapWord* _bottom; - HeapWord* _top; - HeapWord* _end; // last allocatable address + 1 - HeapWord* _hard_end; // _end + AlignmentReserve - bool _retained; // whether we hold a _retained_filler - MemRegion _retained_filler; - // In support of ergonomic sizing of PLAB's - size_t _allocated; // in HeapWord units - size_t _wasted; // in HeapWord units - char tail[32]; - static size_t FillerHeaderSize; - static size_t AlignmentReserve; - -public: - // Initializes the buffer to be empty, but with the given "word_sz". - // Must get initialized with "set_buf" for an allocation to succeed. - ParGCAllocBuffer(size_t word_sz); - - static const size_t min_size() { - return ThreadLocalAllocBuffer::min_size(); - } - - static const size_t max_size() { - return ThreadLocalAllocBuffer::max_size(); - } - - // If an allocation of the given "word_sz" can be satisfied within the - // buffer, do the allocation, returning a pointer to the start of the - // allocated block. If the allocation request cannot be satisfied, - // return NULL. - HeapWord* allocate(size_t word_sz) { - HeapWord* res = _top; - if (pointer_delta(_end, _top) >= word_sz) { - _top = _top + word_sz; - return res; - } else { - return NULL; - } - } - - // Undo the last allocation in the buffer, which is required to be of the - // "obj" of the given "word_sz". - void undo_allocation(HeapWord* obj, size_t word_sz) { - assert(pointer_delta(_top, _bottom) >= word_sz, "Bad undo"); - assert(pointer_delta(_top, obj) == word_sz, "Bad undo"); - _top = obj; - } - - // The total (word) size of the buffer, including both allocated and - // unallocted space. - size_t word_sz() { return _word_sz; } - - // Should only be done if we are about to reset with a new buffer of the - // given size. - void set_word_size(size_t new_word_sz) { - assert(new_word_sz > AlignmentReserve, "Too small"); - _word_sz = new_word_sz; - } - - // The number of words of unallocated space remaining in the buffer. - size_t words_remaining() { - assert(_end >= _top, "Negative buffer"); - return pointer_delta(_end, _top, HeapWordSize); - } - - bool contains(void* addr) { - return (void*)_bottom <= addr && addr < (void*)_hard_end; - } - - // Sets the space of the buffer to be [buf, space+word_sz()). - void set_buf(HeapWord* buf) { - _bottom = buf; - _top = _bottom; - _hard_end = _bottom + word_sz(); - _end = _hard_end - AlignmentReserve; - assert(_end >= _top, "Negative buffer"); - // In support of ergonomic sizing - _allocated += word_sz(); - } - - // Flush the stats supporting ergonomic sizing of PLAB's - void flush_stats(PLABStats* stats); - void flush_stats_and_retire(PLABStats* stats, bool retain) { - // We flush the stats first in order to get a reading of - // unused space in the last buffer. - if (ResizePLAB) { - flush_stats(stats); - } - // Retire the last allocation buffer. - retire(true, retain); - } - - // Force future allocations to fail and queries for contains() - // to return false - void invalidate() { - assert(!_retained, "Shouldn't retain an invalidated buffer."); - _end = _hard_end; - _wasted += pointer_delta(_end, _top); // unused space - _top = _end; // force future allocations to fail - _bottom = _end; // force future contains() queries to return false - } - - // Fills in the unallocated portion of the buffer with a garbage object. - // If "end_of_gc" is TRUE, is after the last use in the GC. IF "retain" - // is true, attempt to re-use the unused portion in the next GC. - void retire(bool end_of_gc, bool retain); - - void print() PRODUCT_RETURN; -}; - -// PLAB stats book-keeping -class PLABStats VALUE_OBJ_CLASS_SPEC { - size_t _allocated; // total allocated - size_t _wasted; // of which wasted (internal fragmentation) - size_t _unused; // Unused in last buffer - size_t _used; // derived = allocated - wasted - unused - size_t _desired_plab_sz;// output of filter (below), suitably trimmed and quantized - AdaptiveWeightedAverage - _filter; // integrator with decay - - public: - PLABStats(size_t desired_plab_sz_, unsigned wt) : - _allocated(0), - _wasted(0), - _unused(0), - _used(0), - _desired_plab_sz(desired_plab_sz_), - _filter(wt) - { - size_t min_sz = min_size(); - size_t max_sz = max_size(); - size_t aligned_min_sz = align_object_size(min_sz); - size_t aligned_max_sz = align_object_size(max_sz); - assert(min_sz <= aligned_min_sz && max_sz >= aligned_max_sz && - min_sz <= max_sz, - "PLAB clipping computation in adjust_desired_plab_sz()" - " may be incorrect"); - } - - static const size_t min_size() { - return ParGCAllocBuffer::min_size(); - } - - static const size_t max_size() { - return ParGCAllocBuffer::max_size(); - } - - size_t desired_plab_sz() { - return _desired_plab_sz; - } - - void adjust_desired_plab_sz(); // filter computation, latches output to - // _desired_plab_sz, clears sensor accumulators - - void add_allocated(size_t v) { - Atomic::add_ptr(v, &_allocated); - } - - void add_unused(size_t v) { - Atomic::add_ptr(v, &_unused); - } - - void add_wasted(size_t v) { - Atomic::add_ptr(v, &_wasted); - } -}; - -class ParGCAllocBufferWithBOT: public ParGCAllocBuffer { - BlockOffsetArrayContigSpace _bt; - BlockOffsetSharedArray* _bsa; - HeapWord* _true_end; // end of the whole ParGCAllocBuffer - - static const size_t ChunkSizeInWords; - static const size_t ChunkSizeInBytes; - HeapWord* allocate_slow(size_t word_sz); - - void fill_region_with_block(MemRegion mr, bool contig); - -public: - ParGCAllocBufferWithBOT(size_t word_sz, BlockOffsetSharedArray* bsa); - - HeapWord* allocate(size_t word_sz) { - HeapWord* res = ParGCAllocBuffer::allocate(word_sz); - if (res != NULL) { - _bt.alloc_block(res, word_sz); - } else { - res = allocate_slow(word_sz); - } - return res; - } - - void undo_allocation(HeapWord* obj, size_t word_sz); - - void set_buf(HeapWord* buf_start) { - ParGCAllocBuffer::set_buf(buf_start); - _true_end = _hard_end; - _bt.set_region(MemRegion(buf_start, word_sz())); - _bt.initialize_threshold(); - } - - void retire(bool end_of_gc, bool retain); - - MemRegion range() { - return MemRegion(_top, _true_end); - } -}; - -#endif // SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP
--- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -24,11 +24,11 @@ #include "precompiled.hpp" #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp" -#include "gc_implementation/parNew/parGCAllocBuffer.hpp" #include "gc_implementation/parNew/parNewGeneration.hpp" #include "gc_implementation/parNew/parOopClosures.inline.hpp" #include "gc_implementation/shared/adaptiveSizePolicy.hpp" #include "gc_implementation/shared/ageTable.hpp" +#include "gc_implementation/shared/parGCAllocBuffer.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" #include "memory/defNewGeneration.inline.hpp" #include "memory/genCollectedHeap.hpp" @@ -453,7 +453,8 @@ // retire the last buffer. par_scan_state.to_space_alloc_buffer()-> flush_stats_and_retire(_gen.plab_stats(), - false /* !retain */); + true /* end_of_gc */, + false /* retain */); // Every thread has its own age table. We need to merge // them all into one.
--- a/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARNEWGENERATION_HPP #define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARNEWGENERATION_HPP -#include "gc_implementation/parNew/parGCAllocBuffer.hpp" +#include "gc_implementation/shared/parGCAllocBuffer.hpp" #include "memory/defNewGeneration.hpp" #include "utilities/taskqueue.hpp"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/gc_implementation/shared/parGCAllocBuffer.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc_implementation/shared/parGCAllocBuffer.hpp" +#include "memory/sharedHeap.hpp" +#include "oops/arrayOop.hpp" +#include "oops/oop.inline.hpp" + +ParGCAllocBuffer::ParGCAllocBuffer(size_t desired_plab_sz_) : + _word_sz(desired_plab_sz_), _bottom(NULL), _top(NULL), + _end(NULL), _hard_end(NULL), + _retained(false), _retained_filler(), + _allocated(0), _wasted(0) +{ + assert (min_size() > AlignmentReserve, "Inconsistency!"); + // arrayOopDesc::header_size depends on command line initialization. + FillerHeaderSize = align_object_size(arrayOopDesc::header_size(T_INT)); + AlignmentReserve = oopDesc::header_size() > MinObjAlignment ? FillerHeaderSize : 0; +} + +size_t ParGCAllocBuffer::FillerHeaderSize; + +// If the minimum object size is greater than MinObjAlignment, we can +// end up with a shard at the end of the buffer that's smaller than +// the smallest object. We can't allow that because the buffer must +// look like it's full of objects when we retire it, so we make +// sure we have enough space for a filler int array object. +size_t ParGCAllocBuffer::AlignmentReserve; + +void ParGCAllocBuffer::retire(bool end_of_gc, bool retain) { + assert(!retain || end_of_gc, "Can only retain at GC end."); + if (_retained) { + // If the buffer had been retained shorten the previous filler object. + assert(_retained_filler.end() <= _top, "INVARIANT"); + CollectedHeap::fill_with_object(_retained_filler); + // Wasted space book-keeping, otherwise (normally) done in invalidate() + _wasted += _retained_filler.word_size(); + _retained = false; + } + assert(!end_of_gc || !_retained, "At this point, end_of_gc ==> !_retained."); + if (_top < _hard_end) { + CollectedHeap::fill_with_object(_top, _hard_end); + if (!retain) { + invalidate(); + } else { + // Is there wasted space we'd like to retain for the next GC? + if (pointer_delta(_end, _top) > FillerHeaderSize) { + _retained = true; + _retained_filler = MemRegion(_top, FillerHeaderSize); + _top = _top + FillerHeaderSize; + } else { + invalidate(); + } + } + } +} + +void ParGCAllocBuffer::flush_stats(PLABStats* stats) { + assert(ResizePLAB, "Wasted work"); + stats->add_allocated(_allocated); + stats->add_wasted(_wasted); + stats->add_unused(pointer_delta(_end, _top)); +} + +// Compute desired plab size and latch result for later +// use. This should be called once at the end of parallel +// scavenge; it clears the sensor accumulators. +void PLABStats::adjust_desired_plab_sz() { + assert(ResizePLAB, "Not set"); + if (_allocated == 0) { + assert(_unused == 0, "Inconsistency in PLAB stats"); + _allocated = 1; + } + double wasted_frac = (double)_unused/(double)_allocated; + size_t target_refills = (size_t)((wasted_frac*TargetSurvivorRatio)/ + TargetPLABWastePct); + if (target_refills == 0) { + target_refills = 1; + } + _used = _allocated - _wasted - _unused; + size_t plab_sz = _used/(target_refills*ParallelGCThreads); + if (PrintPLAB) gclog_or_tty->print(" (plab_sz = %d ", plab_sz); + // Take historical weighted average + _filter.sample(plab_sz); + // Clip from above and below, and align to object boundary + plab_sz = MAX2(min_size(), (size_t)_filter.average()); + plab_sz = MIN2(max_size(), plab_sz); + plab_sz = align_object_size(plab_sz); + // Latch the result + if (PrintPLAB) gclog_or_tty->print(" desired_plab_sz = %d) ", plab_sz); + _desired_plab_sz = plab_sz; + // Now clear the accumulators for next round: + // note this needs to be fixed in the case where we + // are retaining across scavenges. FIX ME !!! XXX + _allocated = 0; + _wasted = 0; + _unused = 0; +} + +#ifndef PRODUCT +void ParGCAllocBuffer::print() { + gclog_or_tty->print("parGCAllocBuffer: _bottom: %p _top: %p _end: %p _hard_end: %p" + "_retained: %c _retained_filler: [%p,%p)\n", + _bottom, _top, _end, _hard_end, + "FT"[_retained], _retained_filler.start(), _retained_filler.end()); +} +#endif // !PRODUCT + +const size_t ParGCAllocBufferWithBOT::ChunkSizeInWords = +MIN2(CardTableModRefBS::par_chunk_heapword_alignment(), + ((size_t)Generation::GenGrain)/HeapWordSize); +const size_t ParGCAllocBufferWithBOT::ChunkSizeInBytes = +MIN2(CardTableModRefBS::par_chunk_heapword_alignment() * HeapWordSize, + (size_t)Generation::GenGrain); + +ParGCAllocBufferWithBOT::ParGCAllocBufferWithBOT(size_t word_sz, + BlockOffsetSharedArray* bsa) : + ParGCAllocBuffer(word_sz), + _bsa(bsa), + _bt(bsa, MemRegion(_bottom, _hard_end)), + _true_end(_hard_end) +{} + +// The buffer comes with its own BOT, with a shared (obviously) underlying +// BlockOffsetSharedArray. We manipulate this BOT in the normal way +// as we would for any contiguous space. However, on accasion we +// need to do some buffer surgery at the extremities before we +// start using the body of the buffer for allocations. Such surgery +// (as explained elsewhere) is to prevent allocation on a card that +// is in the process of being walked concurrently by another GC thread. +// When such surgery happens at a point that is far removed (to the +// right of the current allocation point, top), we use the "contig" +// parameter below to directly manipulate the shared array without +// modifying the _next_threshold state in the BOT. +void ParGCAllocBufferWithBOT::fill_region_with_block(MemRegion mr, + bool contig) { + CollectedHeap::fill_with_object(mr); + if (contig) { + _bt.alloc_block(mr.start(), mr.end()); + } else { + _bt.BlockOffsetArray::alloc_block(mr.start(), mr.end()); + } +} + +HeapWord* ParGCAllocBufferWithBOT::allocate_slow(size_t word_sz) { + HeapWord* res = NULL; + if (_true_end > _hard_end) { + assert((HeapWord*)align_size_down(intptr_t(_hard_end), + ChunkSizeInBytes) == _hard_end, + "or else _true_end should be equal to _hard_end"); + assert(_retained, "or else _true_end should be equal to _hard_end"); + assert(_retained_filler.end() <= _top, "INVARIANT"); + CollectedHeap::fill_with_object(_retained_filler); + if (_top < _hard_end) { + fill_region_with_block(MemRegion(_top, _hard_end), true); + } + HeapWord* next_hard_end = MIN2(_true_end, _hard_end + ChunkSizeInWords); + _retained_filler = MemRegion(_hard_end, FillerHeaderSize); + _bt.alloc_block(_retained_filler.start(), _retained_filler.word_size()); + _top = _retained_filler.end(); + _hard_end = next_hard_end; + _end = _hard_end - AlignmentReserve; + res = ParGCAllocBuffer::allocate(word_sz); + if (res != NULL) { + _bt.alloc_block(res, word_sz); + } + } + return res; +} + +void +ParGCAllocBufferWithBOT::undo_allocation(HeapWord* obj, size_t word_sz) { + ParGCAllocBuffer::undo_allocation(obj, word_sz); + // This may back us up beyond the previous threshold, so reset. + _bt.set_region(MemRegion(_top, _hard_end)); + _bt.initialize_threshold(); +} + +void ParGCAllocBufferWithBOT::retire(bool end_of_gc, bool retain) { + assert(!retain || end_of_gc, "Can only retain at GC end."); + if (_retained) { + // We're about to make the retained_filler into a block. + _bt.BlockOffsetArray::alloc_block(_retained_filler.start(), + _retained_filler.end()); + } + // Reset _hard_end to _true_end (and update _end) + if (retain && _hard_end != NULL) { + assert(_hard_end <= _true_end, "Invariant."); + _hard_end = _true_end; + _end = MAX2(_top, _hard_end - AlignmentReserve); + assert(_end <= _hard_end, "Invariant."); + } + _true_end = _hard_end; + HeapWord* pre_top = _top; + + ParGCAllocBuffer::retire(end_of_gc, retain); + // Now any old _retained_filler is cut back to size, the free part is + // filled with a filler object, and top is past the header of that + // object. + + if (retain && _top < _end) { + assert(end_of_gc && retain, "Or else retain should be false."); + // If the lab does not start on a card boundary, we don't want to + // allocate onto that card, since that might lead to concurrent + // allocation and card scanning, which we don't support. So we fill + // the first card with a garbage object. + size_t first_card_index = _bsa->index_for(pre_top); + HeapWord* first_card_start = _bsa->address_for_index(first_card_index); + if (first_card_start < pre_top) { + HeapWord* second_card_start = + _bsa->inc_by_region_size(first_card_start); + + // Ensure enough room to fill with the smallest block + second_card_start = MAX2(second_card_start, pre_top + AlignmentReserve); + + // If the end is already in the first card, don't go beyond it! + // Or if the remainder is too small for a filler object, gobble it up. + if (_hard_end < second_card_start || + pointer_delta(_hard_end, second_card_start) < AlignmentReserve) { + second_card_start = _hard_end; + } + if (pre_top < second_card_start) { + MemRegion first_card_suffix(pre_top, second_card_start); + fill_region_with_block(first_card_suffix, true); + } + pre_top = second_card_start; + _top = pre_top; + _end = MAX2(_top, _hard_end - AlignmentReserve); + } + + // If the lab does not end on a card boundary, we don't want to + // allocate onto that card, since that might lead to concurrent + // allocation and card scanning, which we don't support. So we fill + // the last card with a garbage object. + size_t last_card_index = _bsa->index_for(_hard_end); + HeapWord* last_card_start = _bsa->address_for_index(last_card_index); + if (last_card_start < _hard_end) { + + // Ensure enough room to fill with the smallest block + last_card_start = MIN2(last_card_start, _hard_end - AlignmentReserve); + + // If the top is already in the last card, don't go back beyond it! + // Or if the remainder is too small for a filler object, gobble it up. + if (_top > last_card_start || + pointer_delta(last_card_start, _top) < AlignmentReserve) { + last_card_start = _top; + } + if (last_card_start < _hard_end) { + MemRegion last_card_prefix(last_card_start, _hard_end); + fill_region_with_block(last_card_prefix, false); + } + _hard_end = last_card_start; + _end = MAX2(_top, _hard_end - AlignmentReserve); + _true_end = _hard_end; + assert(_end <= _hard_end, "Invariant."); + } + + // At this point: + // 1) we had a filler object from the original top to hard_end. + // 2) We've filled in any partial cards at the front and back. + if (pre_top < _hard_end) { + // Now we can reset the _bt to do allocation in the given area. + MemRegion new_filler(pre_top, _hard_end); + fill_region_with_block(new_filler, false); + _top = pre_top + ParGCAllocBuffer::FillerHeaderSize; + // If there's no space left, don't retain. + if (_top >= _end) { + _retained = false; + invalidate(); + return; + } + _retained_filler = MemRegion(pre_top, _top); + _bt.set_region(MemRegion(_top, _hard_end)); + _bt.initialize_threshold(); + assert(_bt.threshold() > _top, "initialize_threshold failed!"); + + // There may be other reasons for queries into the middle of the + // filler object. When such queries are done in parallel with + // allocation, bad things can happen, if the query involves object + // iteration. So we ensure that such queries do not involve object + // iteration, by putting another filler object on the boundaries of + // such queries. One such is the object spanning a parallel card + // chunk boundary. + + // "chunk_boundary" is the address of the first chunk boundary less + // than "hard_end". + HeapWord* chunk_boundary = + (HeapWord*)align_size_down(intptr_t(_hard_end-1), ChunkSizeInBytes); + assert(chunk_boundary < _hard_end, "Or else above did not work."); + assert(pointer_delta(_true_end, chunk_boundary) >= AlignmentReserve, + "Consequence of last card handling above."); + + if (_top <= chunk_boundary) { + assert(_true_end == _hard_end, "Invariant."); + while (_top <= chunk_boundary) { + assert(pointer_delta(_hard_end, chunk_boundary) >= AlignmentReserve, + "Consequence of last card handling above."); + _bt.BlockOffsetArray::alloc_block(chunk_boundary, _hard_end); + CollectedHeap::fill_with_object(chunk_boundary, _hard_end); + _hard_end = chunk_boundary; + chunk_boundary -= ChunkSizeInWords; + } + _end = _hard_end - AlignmentReserve; + assert(_top <= _end, "Invariant."); + // Now reset the initial filler chunk so it doesn't overlap with + // the one(s) inserted above. + MemRegion new_filler(pre_top, _hard_end); + fill_region_with_block(new_filler, false); + } + } else { + _retained = false; + invalidate(); + } + } else { + assert(!end_of_gc || + (!_retained && _true_end == _hard_end), "Checking."); + } + assert(_end <= _hard_end, "Invariant."); + assert(_top < _end || _top == _hard_end, "Invariant"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP +#define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP + +#include "memory/allocation.hpp" +#include "memory/blockOffsetTable.hpp" +#include "memory/threadLocalAllocBuffer.hpp" +#include "utilities/globalDefinitions.hpp" + +// Forward decl. + +class PLABStats; + +// A per-thread allocation buffer used during GC. +class ParGCAllocBuffer: public CHeapObj<mtGC> { +protected: + char head[32]; + size_t _word_sz; // in HeapWord units + HeapWord* _bottom; + HeapWord* _top; + HeapWord* _end; // last allocatable address + 1 + HeapWord* _hard_end; // _end + AlignmentReserve + bool _retained; // whether we hold a _retained_filler + MemRegion _retained_filler; + // In support of ergonomic sizing of PLAB's + size_t _allocated; // in HeapWord units + size_t _wasted; // in HeapWord units + char tail[32]; + static size_t FillerHeaderSize; + static size_t AlignmentReserve; + +public: + // Initializes the buffer to be empty, but with the given "word_sz". + // Must get initialized with "set_buf" for an allocation to succeed. + ParGCAllocBuffer(size_t word_sz); + + static const size_t min_size() { + return ThreadLocalAllocBuffer::min_size(); + } + + static const size_t max_size() { + return ThreadLocalAllocBuffer::max_size(); + } + + // If an allocation of the given "word_sz" can be satisfied within the + // buffer, do the allocation, returning a pointer to the start of the + // allocated block. If the allocation request cannot be satisfied, + // return NULL. + HeapWord* allocate(size_t word_sz) { + HeapWord* res = _top; + if (pointer_delta(_end, _top) >= word_sz) { + _top = _top + word_sz; + return res; + } else { + return NULL; + } + } + + // Undo the last allocation in the buffer, which is required to be of the + // "obj" of the given "word_sz". + void undo_allocation(HeapWord* obj, size_t word_sz) { + assert(pointer_delta(_top, _bottom) >= word_sz, "Bad undo"); + assert(pointer_delta(_top, obj) == word_sz, "Bad undo"); + _top = obj; + } + + // The total (word) size of the buffer, including both allocated and + // unallocted space. + size_t word_sz() { return _word_sz; } + + // Should only be done if we are about to reset with a new buffer of the + // given size. + void set_word_size(size_t new_word_sz) { + assert(new_word_sz > AlignmentReserve, "Too small"); + _word_sz = new_word_sz; + } + + // The number of words of unallocated space remaining in the buffer. + size_t words_remaining() { + assert(_end >= _top, "Negative buffer"); + return pointer_delta(_end, _top, HeapWordSize); + } + + bool contains(void* addr) { + return (void*)_bottom <= addr && addr < (void*)_hard_end; + } + + // Sets the space of the buffer to be [buf, space+word_sz()). + void set_buf(HeapWord* buf) { + _bottom = buf; + _top = _bottom; + _hard_end = _bottom + word_sz(); + _end = _hard_end - AlignmentReserve; + assert(_end >= _top, "Negative buffer"); + // In support of ergonomic sizing + _allocated += word_sz(); + } + + // Flush the stats supporting ergonomic sizing of PLAB's + void flush_stats(PLABStats* stats); + void flush_stats_and_retire(PLABStats* stats, bool end_of_gc, bool retain) { + // We flush the stats first in order to get a reading of + // unused space in the last buffer. + if (ResizePLAB) { + flush_stats(stats); + } + // Retire the last allocation buffer. + retire(end_of_gc, retain); + } + + // Force future allocations to fail and queries for contains() + // to return false + void invalidate() { + assert(!_retained, "Shouldn't retain an invalidated buffer."); + _end = _hard_end; + _wasted += pointer_delta(_end, _top); // unused space + _top = _end; // force future allocations to fail + _bottom = _end; // force future contains() queries to return false + } + + // Fills in the unallocated portion of the buffer with a garbage object. + // If "end_of_gc" is TRUE, is after the last use in the GC. IF "retain" + // is true, attempt to re-use the unused portion in the next GC. + void retire(bool end_of_gc, bool retain); + + void print() PRODUCT_RETURN; +}; + +// PLAB stats book-keeping +class PLABStats VALUE_OBJ_CLASS_SPEC { + size_t _allocated; // total allocated + size_t _wasted; // of which wasted (internal fragmentation) + size_t _unused; // Unused in last buffer + size_t _used; // derived = allocated - wasted - unused + size_t _desired_plab_sz;// output of filter (below), suitably trimmed and quantized + AdaptiveWeightedAverage + _filter; // integrator with decay + + public: + PLABStats(size_t desired_plab_sz_, unsigned wt) : + _allocated(0), + _wasted(0), + _unused(0), + _used(0), + _desired_plab_sz(desired_plab_sz_), + _filter(wt) + { + size_t min_sz = min_size(); + size_t max_sz = max_size(); + size_t aligned_min_sz = align_object_size(min_sz); + size_t aligned_max_sz = align_object_size(max_sz); + assert(min_sz <= aligned_min_sz && max_sz >= aligned_max_sz && + min_sz <= max_sz, + "PLAB clipping computation in adjust_desired_plab_sz()" + " may be incorrect"); + } + + static const size_t min_size() { + return ParGCAllocBuffer::min_size(); + } + + static const size_t max_size() { + return ParGCAllocBuffer::max_size(); + } + + size_t desired_plab_sz() { + return _desired_plab_sz; + } + + void adjust_desired_plab_sz(); // filter computation, latches output to + // _desired_plab_sz, clears sensor accumulators + + void add_allocated(size_t v) { + Atomic::add_ptr(v, &_allocated); + } + + void add_unused(size_t v) { + Atomic::add_ptr(v, &_unused); + } + + void add_wasted(size_t v) { + Atomic::add_ptr(v, &_wasted); + } +}; + +class ParGCAllocBufferWithBOT: public ParGCAllocBuffer { + BlockOffsetArrayContigSpace _bt; + BlockOffsetSharedArray* _bsa; + HeapWord* _true_end; // end of the whole ParGCAllocBuffer + + static const size_t ChunkSizeInWords; + static const size_t ChunkSizeInBytes; + HeapWord* allocate_slow(size_t word_sz); + + void fill_region_with_block(MemRegion mr, bool contig); + +public: + ParGCAllocBufferWithBOT(size_t word_sz, BlockOffsetSharedArray* bsa); + + HeapWord* allocate(size_t word_sz) { + HeapWord* res = ParGCAllocBuffer::allocate(word_sz); + if (res != NULL) { + _bt.alloc_block(res, word_sz); + } else { + res = allocate_slow(word_sz); + } + return res; + } + + void undo_allocation(HeapWord* obj, size_t word_sz); + + void set_buf(HeapWord* buf_start) { + ParGCAllocBuffer::set_buf(buf_start); + _true_end = _hard_end; + _bt.set_region(MemRegion(buf_start, word_sz())); + _bt.initialize_threshold(); + } + + void retire(bool end_of_gc, bool retain); + + MemRegion range() { + return MemRegion(_top, _true_end); + } +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP
--- a/src/share/vm/graal/graalCodeInstaller.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -247,7 +247,7 @@ _env->set_oop_recorder(_oop_recorder); _env->set_dependencies(_dependencies); _dependencies = new Dependencies(_env); - Handle assumptions_handle = InstalledCode::assumptions(HotSpotCompilationResult::comp(target_method)); + Handle assumptions_handle = CompilationResult::assumptions(HotSpotCompilationResult::comp(target_method)); if (!assumptions_handle.is_null()) { objArrayHandle assumptions(Thread::current(), (objArrayOop)Assumptions::list(assumptions_handle())); int length = assumptions->length(); @@ -275,6 +275,7 @@ GraalCompiler::initialize_buffer_blob(); CodeBuffer buffer(JavaThread::current()->get_buffer_blob()); jobject comp_result_obj = JNIHandles::make_local(comp_result()); + jint entry_bci = HotSpotCompilationResult::entryBCI(comp_result); initialize_assumptions(JNIHandles::resolve(comp_result_obj)); { @@ -287,7 +288,7 @@ int stack_slots = _total_frame_size / HeapWordSize; // conversion to words methodHandle method = getMethodFromHotSpotMethod(HotSpotCompilationResult::method(JNIHandles::resolve(comp_result_obj))); - nm = GraalEnv::register_method(method, -1, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, + nm = GraalEnv::register_method(method, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, &_implicit_exception_table, GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, true, false, install_code); method->clear_queued_for_compilation(); @@ -326,11 +327,11 @@ _sites = (arrayOop) HotSpotCompilationResult::sites(comp_result); _exception_handlers = (arrayOop) HotSpotCompilationResult::exceptionHandlers(comp_result); - _code = (arrayOop) InstalledCode::targetCode(_comp_result); - _code_size = InstalledCode::targetCodeSize(_comp_result); + _code = (arrayOop) CompilationResult::targetCode(_comp_result); + _code_size = CompilationResult::targetCodeSize(_comp_result); // The frame size we get from the target method does not include the return address, so add one word for it here. - _total_frame_size = InstalledCode::frameSize(_comp_result) + HeapWordSize; - _custom_stack_area_offset = InstalledCode::customStackAreaOffset(_comp_result); + _total_frame_size = CompilationResult::frameSize(_comp_result) + HeapWordSize; + _custom_stack_area_offset = CompilationResult::customStackAreaOffset(_comp_result); // (very) conservative estimate: each site needs a constant section entry _constants_size = _sites->length() * (BytesPerLong*2); @@ -363,18 +364,18 @@ oop* sites = (oop*) _sites->base(T_OBJECT); for (int i = 0; i < _sites->length(); i++) { oop site = sites[i]; - jint pc_offset = InstalledCode_Site::pcOffset(site); + jint pc_offset = CompilationResult_Site::pcOffset(site); - if (site->is_a(InstalledCode_Call::klass())) { + if (site->is_a(CompilationResult_Call::klass())) { TRACE_graal_4("call at %i", pc_offset); site_Call(buffer, pc_offset, site); - } else if (site->is_a(InstalledCode_Safepoint::klass())) { + } else if (site->is_a(CompilationResult_Safepoint::klass())) { TRACE_graal_4("safepoint at %i", pc_offset); site_Safepoint(buffer, pc_offset, site); - } else if (site->is_a(InstalledCode_DataPatch::klass())) { + } else if (site->is_a(CompilationResult_DataPatch::klass())) { TRACE_graal_4("datapatch at %i", pc_offset); site_DataPatch(buffer, pc_offset, site); - } else if (site->is_a(InstalledCode_Mark::klass())) { + } else if (site->is_a(CompilationResult_Mark::klass())) { TRACE_graal_4("mark at %i", pc_offset); site_Mark(buffer, pc_offset, site); } else { @@ -426,8 +427,8 @@ oop* exception_handlers = (oop*) _exception_handlers->base(T_OBJECT); for (int i = 0; i < _exception_handlers->length(); i++) { oop exc = exception_handlers[i]; - jint pc_offset = InstalledCode_Site::pcOffset(exc); - jint handler_offset = InstalledCode_ExceptionHandler::handlerPos(exc); + jint pc_offset = CompilationResult_Site::pcOffset(exc); + jint handler_offset = CompilationResult_ExceptionHandler::handlerPos(exc); // Subtable header _exception_handler_table.add_entry(HandlerTableEntry(1, pc_offset, 0)); @@ -517,7 +518,7 @@ } void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) { - oop debug_info = InstalledCode_Safepoint::debugInfo(site); + oop debug_info = CompilationResult_Safepoint::debugInfo(site); assert(debug_info != NULL, "debug info expected"); // address instruction = _instructions->start() + pc_offset; @@ -531,7 +532,7 @@ } void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, oop site) { - oop target = InstalledCode_Call::target(site); + oop target = CompilationResult_Call::target(site); instanceKlass* target_klass = instanceKlass::cast(target->klass()); oop hotspot_method = NULL; // JavaMethod @@ -543,7 +544,7 @@ hotspot_method = target; } - oop debug_info = InstalledCode_Call::debugInfo(site); + oop debug_info = CompilationResult_Call::debugInfo(site); assert((hotspot_method ? 1 : 0) + (global_stub ? 1 : 0) == 1, "Call site needs exactly one type"); @@ -659,8 +660,8 @@ } void CodeInstaller::site_DataPatch(CodeBuffer& buffer, jint pc_offset, oop site) { - oop constant = InstalledCode_DataPatch::constant(site); - int alignment = InstalledCode_DataPatch::alignment(site); + oop constant = CompilationResult_DataPatch::constant(site); + int alignment = CompilationResult_DataPatch::alignment(site); oop kind = Constant::kind(constant); address instruction = _instructions->start() + pc_offset; @@ -723,8 +724,8 @@ } void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, oop site) { - oop id_obj = InstalledCode_Mark::id(site); - arrayOop references = (arrayOop) InstalledCode_Mark::references(site); + oop id_obj = CompilationResult_Mark::id(site); + arrayOop references = (arrayOop) CompilationResult_Mark::references(site); if (id_obj != NULL) { assert(java_lang_boxing_object::is_instance(id_obj, T_INT), "Integer id expected"); @@ -751,7 +752,7 @@ case MARK_STATIC_CALL_STUB: { assert(references->length() == 1, "static call stub needs one reference"); oop ref = ((oop*) references->base(T_OBJECT))[0]; - address call_pc = _instructions->start() + InstalledCode_Site::pcOffset(ref); + address call_pc = _instructions->start() + CompilationResult_Site::pcOffset(ref); _instructions->relocate(instruction, static_stub_Relocation::spec(call_pc)); _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); break; @@ -805,14 +806,14 @@ assert(references->length() == 2, "MARK_KLASS_PATCHING/MARK_ACCESS_FIELD_PATCHING needs 2 references"); oop ref1 = ((oop*) references->base(T_OBJECT))[0]; oop ref2 = ((oop*) references->base(T_OBJECT))[1]; - int i_byte_count = InstalledCode_Site::pcOffset(ref2) - InstalledCode_Site::pcOffset(ref1); + int i_byte_count = CompilationResult_Site::pcOffset(ref2) - CompilationResult_Site::pcOffset(ref1); assert(i_byte_count == (unsigned char)i_byte_count, "invalid offset"); *byte_count = i_byte_count; *being_initialized_entry_offset = *byte_count + *byte_skip; // we need to correct the offset of a field access - it's created with MAX_INT to ensure the correct size, and hotspot expects 0 if (id == MARK_ACCESS_FIELD_PATCHING) { - NativeMovRegMem* inst = nativeMovRegMem_at(_instructions->start() + InstalledCode_Site::pcOffset(ref1)); + NativeMovRegMem* inst = nativeMovRegMem_at(_instructions->start() + CompilationResult_Site::pcOffset(ref1)); assert(inst->offset() == max_jint, "unexpected offset value"); inst->set_offset(0); }
--- a/src/share/vm/graal/graalCodeInstaller.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -29,7 +29,7 @@ */ class CodeInstaller { private: - // these need to correspond to HotSpotXirGenerator.java + // these need to correspond to Marks.java enum MarkId { MARK_VERIFIED_ENTRY = 0x0001, MARK_UNVERIFIED_ENTRY = 0x0002,
--- a/src/share/vm/graal/graalCompiler.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/graal/graalCompiler.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -50,7 +50,7 @@ // Native / OSR not supported virtual bool supports_native() { return true; } - virtual bool supports_osr () { return false; } + virtual bool supports_osr () { return true; } // Pretend to be C1 bool is_c1 () { return true; }
--- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -52,19 +52,19 @@ // Entry to native method implementation that transitions current thread to '_thread_in_vm'. #define C2V_VMENTRY(result_type, name, signature) \ - JNIEXPORT result_type JNICALL name signature { \ + JNIEXPORT result_type JNICALL c2v_ ## name signature { \ TRACE_graal_3("CompilerToVM::" #name); \ VM_ENTRY_MARK; \ // Entry to native method implementation that calls a JNI function // and hence cannot transition current thread to '_thread_in_vm'. #define C2V_ENTRY(result_type, name, signature) \ - JNIEXPORT result_type JNICALL name signature { \ + JNIEXPORT result_type JNICALL c2v_ ## name signature { \ TRACE_graal_3("CompilerToVM::" #name); \ #define C2V_END } -C2V_ENTRY(jbyteArray, JavaMethod_code, (JNIEnv *env, jobject, jobject hotspot_method)) +C2V_ENTRY(jbyteArray, getBytecode, (JNIEnv *env, jobject, jobject hotspot_method)) methodHandle method = getMethodFromHotSpotMethod(hotspot_method); // copy all bytecodes @@ -99,13 +99,13 @@ return result; C2V_END -C2V_VMENTRY(jstring, JavaMethod_signature, (JNIEnv *env, jobject, jobject hotspot_method)) +C2V_VMENTRY(jstring, getSignature, (JNIEnv *env, jobject, jobject hotspot_method)) methodOop method = getMethodFromHotSpotMethod(hotspot_method); assert(method != NULL && method->signature() != NULL, "signature required"); return VmIds::toString<jstring>(method->signature(), THREAD); C2V_END -C2V_VMENTRY(jobjectArray, JavaMethod_exceptionHandlers, (JNIEnv *, jobject, jobject hotspot_method)) +C2V_VMENTRY(jobjectArray, getExceptionHandlers, (JNIEnv *, jobject, jobject hotspot_method)) ResourceMark rm; methodHandle method = getMethodFromHotSpotMethod(hotspot_method); int handler_count = method->exception_table_length(); @@ -142,7 +142,7 @@ return (jobjectArray) JNIHandles::make_local(array()); C2V_END -C2V_VMENTRY(jint, JavaMethod_hasBalancedMonitors, (JNIEnv *, jobject, jobject hotspot_method)) +C2V_VMENTRY(jint, hasBalancedMonitors, (JNIEnv *, jobject, jobject hotspot_method)) // Analyze the method to see if monitors are used properly. methodHandle method(THREAD, getMethodFromHotSpotMethod(hotspot_method)); @@ -192,7 +192,7 @@ return JNIHandles::make_local(THREAD, ret()); } -C2V_VMENTRY(jobject, JavaMethod_uniqueConcreteMethod, (JNIEnv *, jobject, jobject hotspot_method)) +C2V_VMENTRY(jobject, getUniqueConcreteMethod, (JNIEnv *, jobject, jobject hotspot_method)) methodHandle method = getMethodFromHotSpotMethod(hotspot_method); KlassHandle holder = method->method_holder(); if (holder->is_interface()) { @@ -219,11 +219,11 @@ } C2V_END -C2V_ENTRY(jint, JavaMethod_invocationCount, (JNIEnv *, jobject, jobject hotspot_method)) +C2V_ENTRY(jint, getInvocationCount, (JNIEnv *, jobject, jobject hotspot_method)) return getMethodFromHotSpotMethod(hotspot_method)->invocation_count(); C2V_END -C2V_VMENTRY(jobject, JavaMethod_methodData,(JNIEnv *, jobject, jobject hotspot_method)) +C2V_VMENTRY(jobject, getMethodData,(JNIEnv *, jobject, jobject hotspot_method)) methodDataHandle method_data = getMethodFromHotSpotMethod(hotspot_method)->method_data(); if(method_data.is_null()) { @@ -260,16 +260,12 @@ return count; } -C2V_ENTRY(jboolean, JavaMethod_hasCompiledCode, (JNIEnv *, jobject, jobject hotspot_method)) - return getMethodFromHotSpotMethod(hotspot_method)->has_compiled_code(); -C2V_END - -C2V_ENTRY(jint, JavaMethod_getCompiledCodeSize, (JNIEnv *env, jobject, jobject hotspot_method)) +C2V_ENTRY(jint, getCompiledCodeSize, (JNIEnv *env, jobject, jobject hotspot_method)) nmethod* code = getMethodFromHotSpotMethod(hotspot_method)->code(); return code == NULL ? 0 : code->insts_size(); C2V_END -C2V_VMENTRY(jobject, Signature_lookupType, (JNIEnv *env, jobject, jstring jname, jobject accessingClass, jboolean eagerResolve)) +C2V_VMENTRY(jobject, lookupType, (JNIEnv *env, jobject, jstring jname, jobject accessingClass, jboolean eagerResolve)) ResourceMark rm; Symbol* nameSymbol = VmIds::toSymbol(jname); @@ -334,7 +330,7 @@ return JNIHandles::make_local(THREAD, result); C2V_END -C2V_VMENTRY(jobject, ConstantPool_lookupConstant, (JNIEnv *env, jobject, jobject type, jint index)) +C2V_VMENTRY(jobject, lookupConstantInPool, (JNIEnv *env, jobject, jobject type, jint index)) constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotResolvedJavaType::javaMirror(type)))->constants(); @@ -376,7 +372,7 @@ return JNIHandles::make_local(THREAD, result); C2V_END -C2V_VMENTRY(jobject, ConstantPool_lookupMethod, (JNIEnv *env, jobject, jobject type, jint index, jbyte byteCode)) +C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte byteCode)) index = GraalCompiler::to_cp_index_u2(index); constantPoolHandle cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotResolvedJavaType::javaMirror(type)))->constants(); instanceKlassHandle pool_holder(cp->pool_holder()); @@ -396,18 +392,18 @@ } C2V_END -C2V_VMENTRY(jobject, ConstantPool_lookupType, (JNIEnv *env, jobject, jobject type, jint index)) +C2V_VMENTRY(jobject, lookupTypeInPool, (JNIEnv *env, jobject, jobject type, jint index)) constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotResolvedJavaType::javaMirror(type)))->constants(); Handle result = GraalCompiler::get_JavaType(cp, index, cp->pool_holder(), CHECK_NULL); return JNIHandles::make_local(THREAD, result()); C2V_END -C2V_VMENTRY(void, ConstantPool_loadReferencedType, (JNIEnv *env, jobject, jobject type, jint index, jbyte op)) +C2V_VMENTRY(void, lookupReferencedTypeInPool, (JNIEnv *env, jobject, jobject type, jint index, jbyte op)) constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotResolvedJavaType::javaMirror(type)))->constants(); - int byteCode = (op & 0xFF); - if (byteCode != Bytecodes::_checkcast && byteCode != Bytecodes::_instanceof && byteCode != Bytecodes::_new && byteCode != Bytecodes::_anewarray - && byteCode != Bytecodes::_multianewarray && byteCode != Bytecodes::_ldc && byteCode != Bytecodes::_ldc_w && byteCode != Bytecodes::_ldc2_w) + int opcode = (op & 0xFF); + if (opcode != Bytecodes::_checkcast && opcode != Bytecodes::_instanceof && opcode != Bytecodes::_new && opcode != Bytecodes::_anewarray + && opcode != Bytecodes::_multianewarray && opcode != Bytecodes::_ldc && opcode != Bytecodes::_ldc_w && opcode != Bytecodes::_ldc2_w) { index = cp->remap_instruction_operand_from_cache(GraalCompiler::to_cp_index_u2(index)); } @@ -425,7 +421,7 @@ } C2V_END -C2V_VMENTRY(jobject, ConstantPool_lookupField, (JNIEnv *env, jobject, jobject constantPoolHolder, jint index, jbyte byteCode)) +C2V_VMENTRY(jobject, lookupFieldInPool, (JNIEnv *env, jobject, jobject constantPoolHolder, jint index, jbyte byteCode)) ResourceMark rm; index = GraalCompiler::to_cp_index_u2(index); @@ -466,7 +462,7 @@ return JNIHandles::make_local(THREAD, field_handle()); C2V_END -C2V_VMENTRY(jobject, JavaType_resolveMethodImpl, (JNIEnv *, jobject, jobject resolved_type, jstring name, jstring signature)) +C2V_VMENTRY(jobject, resolveMethod, (JNIEnv *, jobject, jobject resolved_type, jstring name, jstring signature)) assert(JNIHandles::resolve(resolved_type) != NULL, ""); klassOop klass = java_lang_Class::as_klassOop(HotSpotResolvedJavaType::javaMirror(resolved_type)); @@ -484,7 +480,7 @@ return JNIHandles::make_local(THREAD, ret()); C2V_END -C2V_VMENTRY(jboolean, JavaType_isSubtypeOf, (JNIEnv *, jobject, jobject klass, jobject jother)) +C2V_VMENTRY(jboolean, isSubtypeOf, (JNIEnv *, jobject, jobject klass, jobject jother)) oop other = JNIHandles::resolve(jother); assert(other->is_a(HotSpotResolvedJavaType::klass()), "resolved hotspot type expected"); assert(JNIHandles::resolve(klass) != NULL, ""); @@ -500,7 +496,7 @@ } C2V_END -C2V_VMENTRY(jobject, JavaType_leastCommonAncestor, (JNIEnv *, jobject, jobject this_type, jobject other_type)) +C2V_VMENTRY(jobject, getLeastCommonAncestor, (JNIEnv *, jobject, jobject this_type, jobject other_type)) Klass* this_klass = java_lang_Class::as_klassOop(HotSpotResolvedJavaType::javaMirror(this_type))->klass_part(); Klass* other_klass = java_lang_Class::as_klassOop(HotSpotResolvedJavaType::javaMirror(other_type))->klass_part(); @@ -509,7 +505,7 @@ return JNIHandles::make_local(GraalCompiler::get_JavaType(lca, THREAD)()); C2V_END -C2V_VMENTRY(jobject, JavaType_componentType, (JNIEnv *, jobject, jobject klass)) +C2V_VMENTRY(jobject, getComponentType, (JNIEnv *, jobject, jobject klass)) KlassHandle array_klass = java_lang_Class::as_klassOop(HotSpotResolvedJavaType::javaMirror(klass)); if(array_klass->oop_is_typeArray()) { BasicType t = typeArrayKlass::cast(array_klass())->element_type(); @@ -522,7 +518,7 @@ return JNIHandles::make_local(GraalCompiler::get_JavaType(element_type, THREAD)()); C2V_END -C2V_VMENTRY(jlong, JavaType_prototypeMarkWord, (JNIEnv *, jobject, jobject klass)) +C2V_VMENTRY(jlong, getPrototypeMarkWord, (JNIEnv *, jobject, jobject klass)) KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotResolvedJavaType::javaMirror(klass))); if (klass_handle->oop_is_array()) { return (int32_t)(intptr_t) markOopDesc::prototype(); @@ -531,7 +527,7 @@ } C2V_END -C2V_VMENTRY(jobject, JavaType_superType, (JNIEnv *, jobject, jobject klass)) +C2V_VMENTRY(jobject, getSuperType, (JNIEnv *, jobject, jobject klass)) KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotResolvedJavaType::javaMirror(klass))); klassOop k; @@ -549,7 +545,7 @@ } C2V_END -C2V_VMENTRY(jobject, JavaType_uniqueConcreteSubtype, (JNIEnv *, jobject, jobject klass)) +C2V_VMENTRY(jobject, getUniqueConcreteSubtype, (JNIEnv *, jobject, jobject klass)) KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotResolvedJavaType::javaMirror(klass))); Klass *up_cast = klass_handle->up_cast_abstract(); if (!up_cast->is_interface() && up_cast->subklass() == NULL) { @@ -558,20 +554,19 @@ return NULL; C2V_END -C2V_VMENTRY(jboolean, JavaType_isInitialized,(JNIEnv *, jobject, jobject hotspot_klass)) +C2V_VMENTRY(jboolean, isTypeInitialized,(JNIEnv *, jobject, jobject hotspot_klass)) klassOop klass = java_lang_Class::as_klassOop(HotSpotResolvedJavaType::javaMirror(hotspot_klass)); assert(klass != NULL, "method must not be called for primitive types"); return instanceKlass::cast(klass)->is_initialized(); C2V_END -// public bool JavaType_isInitialized(HotSpotResolvedType klass); -C2V_VMENTRY(void, JavaType_initialize, (JNIEnv *, jobject, jobject hotspot_klass)) +C2V_VMENTRY(void, initializeType, (JNIEnv *, jobject, jobject hotspot_klass)) klassOop klass = java_lang_Class::as_klassOop(HotSpotResolvedJavaType::javaMirror(hotspot_klass)); assert(klass != NULL, "method must not be called for primitive types"); instanceKlass::cast(klass)->initialize(JavaThread::current()); C2V_END -C2V_VMENTRY(jobject, JavaType_arrayOf, (JNIEnv *, jobject, jobject klass)) +C2V_VMENTRY(jobject, getArrayOf, (JNIEnv *, jobject, jobject klass)) KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotResolvedJavaType::javaMirror(klass))); KlassHandle arr = klass_handle->array_klass(THREAD); Handle name = VmIds::toString<Handle>(arr->name(), CHECK_NULL); @@ -579,7 +574,7 @@ return JNIHandles::make_local(THREAD, GraalCompiler::createHotSpotResolvedJavaType(arr, name, THREAD)()); C2V_END -C2V_VMENTRY(jobject, JavaType_fields, (JNIEnv *, jobject, jobject klass)) +C2V_VMENTRY(jobject, getFields, (JNIEnv *, jobject, jobject klass)) ResourceMark rm; instanceKlassHandle k = java_lang_Class::as_klassOop(HotSpotResolvedJavaType::javaMirror(klass)); @@ -744,6 +739,7 @@ set_long(env, config, "vmErrorStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_vm_error_id))); set_long(env, config, "deoptimizeStub", VmIds::addStub(SharedRuntime::deopt_blob()->uncommon_trap())); set_long(env, config, "unwindExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_unwind_exception_call_id))); + set_long(env, config, "osrMigrationEndStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_OSR_migration_end_id))); set_long(env, config, "registerFinalizerStub", VmIds::addStub(Runtime1::entry_for(Runtime1::register_finalizer_id))); set_long(env, config, "setDeoptInfoStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_set_deopt_info_id))); set_long(env, config, "createNullPointerExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_create_null_pointer_exception_id))); @@ -833,7 +829,7 @@ return JNIHandles::make_local(result()); C2V_END -C2V_VMENTRY(jobject, JavaMethod_toStackTraceElement, (JNIEnv *env, jobject, jobject hotspot_method, int bci)) +C2V_VMENTRY(jobject, getStackTraceElement, (JNIEnv *env, jobject, jobject hotspot_method, int bci)) ResourceMark rm; HandleMark hm; @@ -893,7 +889,7 @@ return JNIHandles::make_local((oop) result.get_jobject()); C2V_END -C2V_VMENTRY(jint, JavaMethod_vtableEntryOffset, (JNIEnv *, jobject, jobject hotspot_method)) +C2V_VMENTRY(jint, getVtableEntryOffset, (JNIEnv *, jobject, jobject hotspot_method)) methodOop method = getMethodFromHotSpotMethod(hotspot_method); assert(!instanceKlass::cast(method->method_holder())->is_interface(), "vtableEntryOffset cannot be called for interface methods"); @@ -939,7 +935,7 @@ #define CC (char*) /*cast a literal from (const char*)*/ -#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(f)) +#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f)) #define PROXY "J" #define TYPE "Lcom/oracle/graal/api/meta/JavaType;" @@ -968,50 +964,45 @@ #define STACK_TRACE_ELEMENT "Ljava/lang/StackTraceElement;" JNINativeMethod CompilerToVM_methods[] = { - {CC"JavaMethod_code", CC"("RESOLVED_METHOD")[B", FN_PTR(JavaMethod_code)}, - {CC"JavaMethod_signature", CC"("RESOLVED_METHOD")"STRING, FN_PTR(JavaMethod_signature)}, - {CC"JavaMethod_exceptionHandlers", CC"("RESOLVED_METHOD")"EXCEPTION_HANDLERS, FN_PTR(JavaMethod_exceptionHandlers)}, - {CC"JavaMethod_hasBalancedMonitors", CC"("RESOLVED_METHOD")Z", FN_PTR(JavaMethod_hasBalancedMonitors)}, - {CC"JavaMethod_uniqueConcreteMethod", CC"("RESOLVED_METHOD")"METHOD, FN_PTR(JavaMethod_uniqueConcreteMethod)}, - {CC"JavaMethod_toStackTraceElement", CC"("RESOLVED_METHOD"I)"STACK_TRACE_ELEMENT, FN_PTR(JavaMethod_toStackTraceElement)}, - {CC"JavaMethod_methodData", CC"("RESOLVED_METHOD")"METHOD_DATA, FN_PTR(JavaMethod_methodData)}, - {CC"JavaMethod_invocationCount", CC"("RESOLVED_METHOD")I", FN_PTR(JavaMethod_invocationCount)}, - {CC"JavaMethod_hasCompiledCode", CC"("RESOLVED_METHOD")Z", FN_PTR(JavaMethod_hasCompiledCode)}, - {CC"JavaMethod_getCompiledCodeSize", CC"("RESOLVED_METHOD")I", FN_PTR(JavaMethod_getCompiledCodeSize)}, - {CC"JavaMethod_vtableEntryOffset", CC"("RESOLVED_METHOD")I", FN_PTR(JavaMethod_vtableEntryOffset)}, - - {CC"Signature_lookupType", CC"("STRING RESOLVED_TYPE"Z)"TYPE, FN_PTR(Signature_lookupType)}, - - {CC"ConstantPool_lookupConstant", CC"("RESOLVED_TYPE"I)"OBJECT, FN_PTR(ConstantPool_lookupConstant)}, - {CC"ConstantPool_lookupMethod", CC"("RESOLVED_TYPE"IB)"METHOD, FN_PTR(ConstantPool_lookupMethod)}, - {CC"ConstantPool_lookupType", CC"("RESOLVED_TYPE"I)"TYPE, FN_PTR(ConstantPool_lookupType)}, - {CC"ConstantPool_loadReferencedType", CC"("RESOLVED_TYPE"IB)V", FN_PTR(ConstantPool_loadReferencedType)}, - {CC"ConstantPool_lookupField", CC"("RESOLVED_TYPE"IB)"FIELD, FN_PTR(ConstantPool_lookupField)}, - - {CC"JavaType_resolveMethodImpl", CC"("RESOLVED_TYPE STRING STRING")"METHOD, FN_PTR(JavaType_resolveMethodImpl)}, - {CC"JavaType_isSubtypeOf", CC"("RESOLVED_TYPE TYPE")Z", FN_PTR(JavaType_isSubtypeOf)}, - {CC"JavaType_leastCommonAncestor", CC"("RESOLVED_TYPE RESOLVED_TYPE")"TYPE, FN_PTR(JavaType_leastCommonAncestor)}, - {CC"JavaType_componentType", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(JavaType_componentType)}, - {CC"JavaType_uniqueConcreteSubtype", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(JavaType_uniqueConcreteSubtype)}, - {CC"JavaType_superType", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(JavaType_superType)}, - {CC"JavaType_prototypeMarkWord", CC"("RESOLVED_TYPE")J", FN_PTR(JavaType_prototypeMarkWord)}, - {CC"JavaType_arrayOf", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(JavaType_arrayOf)}, - {CC"JavaType_fields", CC"("RESOLVED_TYPE")["RESOLVED_FIELD, FN_PTR(JavaType_fields)}, - {CC"JavaType_isInitialized", CC"("RESOLVED_TYPE")Z", FN_PTR(JavaType_isInitialized)}, - {CC"JavaType_initialize", CC"("RESOLVED_TYPE")V", FN_PTR(JavaType_initialize)}, - - {CC"getPrimitiveArrayType", CC"("KIND")"TYPE, FN_PTR(getPrimitiveArrayType)}, - {CC"getMaxCallTargetOffset", CC"(J)J", FN_PTR(getMaxCallTargetOffset)}, - {CC"getType", CC"("CLASS")"TYPE, FN_PTR(getType)}, - {CC"getJavaMethod", CC"("REFLECT_METHOD")"METHOD , FN_PTR(getJavaMethod)}, - {CC"getJavaField", CC"("REFLECT_FIELD")"RESOLVED_FIELD, FN_PTR(getJavaField)}, - {CC"initializeConfiguration", CC"("CONFIG")V", FN_PTR(initializeConfiguration)}, - {CC"installMethod", CC"("HS_COMP_RESULT"Z"HS_CODE_INFO")"HS_COMP_METHOD, FN_PTR(installMethod)}, - {CC"disassembleNative", CC"([BJ)"STRING, FN_PTR(disassembleNative)}, - {CC"executeCompiledMethod", CC"("HS_COMP_METHOD OBJECT OBJECT OBJECT")"OBJECT, FN_PTR(executeCompiledMethod)}, - {CC"executeCompiledMethodVarargs", CC"("HS_COMP_METHOD "["OBJECT")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, - {CC"getDeoptedLeafGraphIds", CC"()[J", FN_PTR(getDeoptedLeafGraphIds)}, - {CC"decodePC", CC"(J)"STRING, FN_PTR(decodePC)}, + {CC"getBytecode", CC"("RESOLVED_METHOD")[B", FN_PTR(getBytecode)}, + {CC"getSignature", CC"("RESOLVED_METHOD")"STRING, FN_PTR(getSignature)}, + {CC"getExceptionHandlers", CC"("RESOLVED_METHOD")"EXCEPTION_HANDLERS, FN_PTR(getExceptionHandlers)}, + {CC"hasBalancedMonitors", CC"("RESOLVED_METHOD")Z", FN_PTR(hasBalancedMonitors)}, + {CC"getUniqueConcreteMethod", CC"("RESOLVED_METHOD")"METHOD, FN_PTR(getUniqueConcreteMethod)}, + {CC"getStackTraceElement", CC"("RESOLVED_METHOD"I)"STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)}, + {CC"getMethodData", CC"("RESOLVED_METHOD")"METHOD_DATA, FN_PTR(getMethodData)}, + {CC"getInvocationCount", CC"("RESOLVED_METHOD")I", FN_PTR(getInvocationCount)}, + {CC"getCompiledCodeSize", CC"("RESOLVED_METHOD")I", FN_PTR(getCompiledCodeSize)}, + {CC"getVtableEntryOffset", CC"("RESOLVED_METHOD")I", FN_PTR(getVtableEntryOffset)}, + {CC"lookupType", CC"("STRING RESOLVED_TYPE"Z)"TYPE, FN_PTR(lookupType)}, + {CC"lookupConstantInPool", CC"("RESOLVED_TYPE"I)"OBJECT, FN_PTR(lookupConstantInPool)}, + {CC"lookupMethodInPool", CC"("RESOLVED_TYPE"IB)"METHOD, FN_PTR(lookupMethodInPool)}, + {CC"lookupTypeInPool", CC"("RESOLVED_TYPE"I)"TYPE, FN_PTR(lookupTypeInPool)}, + {CC"lookupReferencedTypeInPool", CC"("RESOLVED_TYPE"IB)V", FN_PTR(lookupReferencedTypeInPool)}, + {CC"lookupFieldInPool", CC"("RESOLVED_TYPE"IB)"FIELD, FN_PTR(lookupFieldInPool)}, + {CC"resolveMethod", CC"("RESOLVED_TYPE STRING STRING")"METHOD, FN_PTR(resolveMethod)}, + {CC"isSubtypeOf", CC"("RESOLVED_TYPE TYPE")Z", FN_PTR(isSubtypeOf)}, + {CC"getLeastCommonAncestor", CC"("RESOLVED_TYPE RESOLVED_TYPE")"TYPE, FN_PTR(getLeastCommonAncestor)}, + {CC"getComponentType", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(getComponentType)}, + {CC"getUniqueConcreteSubtype", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(getUniqueConcreteSubtype)}, + {CC"getSuperType", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(getSuperType)}, + {CC"getPrototypeMarkWord", CC"("RESOLVED_TYPE")J", FN_PTR(getPrototypeMarkWord)}, + {CC"getArrayOf", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(getArrayOf)}, + {CC"getFields", CC"("RESOLVED_TYPE")["RESOLVED_FIELD, FN_PTR(getFields)}, + {CC"isTypeInitialized", CC"("RESOLVED_TYPE")Z", FN_PTR(isTypeInitialized)}, + {CC"initializeType", CC"("RESOLVED_TYPE")V", FN_PTR(initializeType)}, + {CC"getPrimitiveArrayType", CC"("KIND")"TYPE, FN_PTR(getPrimitiveArrayType)}, + {CC"getMaxCallTargetOffset", CC"(J)J", FN_PTR(getMaxCallTargetOffset)}, + {CC"getType", CC"("CLASS")"TYPE, FN_PTR(getType)}, + {CC"getJavaMethod", CC"("REFLECT_METHOD")"METHOD , FN_PTR(getJavaMethod)}, + {CC"getJavaField", CC"("REFLECT_FIELD")"RESOLVED_FIELD, FN_PTR(getJavaField)}, + {CC"initializeConfiguration", CC"("CONFIG")V", FN_PTR(initializeConfiguration)}, + {CC"installMethod", CC"("HS_COMP_RESULT"Z"HS_CODE_INFO")"HS_COMP_METHOD, FN_PTR(installMethod)}, + {CC"disassembleNative", CC"([BJ)"STRING, FN_PTR(disassembleNative)}, + {CC"executeCompiledMethod", CC"("HS_COMP_METHOD OBJECT OBJECT OBJECT")"OBJECT, FN_PTR(executeCompiledMethod)}, + {CC"executeCompiledMethodVarargs", CC"("HS_COMP_METHOD "["OBJECT")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, + {CC"getDeoptedLeafGraphIds", CC"()[J", FN_PTR(getDeoptedLeafGraphIds)}, + {CC"decodePC", CC"(J)"STRING, FN_PTR(decodePC)}, }; int CompilerToVM_methods_count() {
--- a/src/share/vm/graal/graalJavaAccess.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/graal/graalJavaAccess.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -29,7 +29,7 @@ #include "classfile/systemDictionary.hpp" #include "oops/instanceMirrorKlass.hpp" -/* This macro defines the structure of the InstalledCode - classes. +/* This macro defines the structure of the CompilationResult - classes. * It will generate classes with accessors similar to javaClasses.hpp, but with specializations for oops, Handles and jni handles. * * The public interface of these classes will look like this: @@ -72,147 +72,148 @@ int_field(HotSpotResolvedJavaMethod, maxLocals) \ int_field(HotSpotResolvedJavaMethod, maxStackSize) \ boolean_field(HotSpotResolvedJavaMethod, canBeInlined) \ - end_class \ - start_class(HotSpotMethodData) \ - oop_field(HotSpotMethodData, hotspotMirror, "Ljava/lang/Object;") \ - int_field(HotSpotMethodData, normalDataSize) \ - int_field(HotSpotMethodData, extraDataSize) \ - end_class \ + end_class \ + start_class(HotSpotMethodData) \ + oop_field(HotSpotMethodData, hotspotMirror, "Ljava/lang/Object;") \ + int_field(HotSpotMethodData, normalDataSize) \ + int_field(HotSpotMethodData, extraDataSize) \ + end_class \ start_class(HotSpotJavaType) \ oop_field(HotSpotJavaType, name, "Ljava/lang/String;") \ - end_class \ - start_class(HotSpotResolvedJavaField) \ - oop_field(HotSpotResolvedJavaField, constant, "Lcom/oracle/graal/api/meta/Constant;") \ - int_field(HotSpotResolvedJavaField, offset) \ - int_field(HotSpotResolvedJavaField, accessFlags) \ - end_class \ - start_class(HotSpotCompiledMethod) \ - long_field(HotSpotCompiledMethod, nmethod) \ - oop_field(HotSpotCompiledMethod, method, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;")\ - end_class \ - start_class(HotSpotCodeInfo) \ - long_field(HotSpotCodeInfo, start) \ - oop_field(HotSpotCodeInfo, code, "[B") \ - end_class \ - start_class(HotSpotCompilationResult) \ + end_class \ + start_class(HotSpotResolvedJavaField) \ + oop_field(HotSpotResolvedJavaField, constant, "Lcom/oracle/graal/api/meta/Constant;") \ + int_field(HotSpotResolvedJavaField, offset) \ + int_field(HotSpotResolvedJavaField, accessFlags) \ + end_class \ + start_class(HotSpotCompiledMethod) \ + long_field(HotSpotCompiledMethod, nmethod) \ + oop_field(HotSpotCompiledMethod, method, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;") \ + end_class \ + start_class(HotSpotCodeInfo) \ + long_field(HotSpotCodeInfo, start) \ + oop_field(HotSpotCodeInfo, code, "[B") \ + end_class \ + start_class(HotSpotCompilationResult) \ oop_field(HotSpotCompilationResult, comp, "Lcom/oracle/graal/api/code/CompilationResult;") \ oop_field(HotSpotCompilationResult, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;") \ - oop_field(HotSpotCompilationResult, name, "Ljava/lang/String;") \ + int_field(HotSpotCompilationResult, entryBCI) \ + oop_field(HotSpotCompilationResult, name, "Ljava/lang/String;") \ oop_field(HotSpotCompilationResult, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;") \ oop_field(HotSpotCompilationResult, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;") \ - end_class \ - start_class(ExceptionHandler) \ - int_field(ExceptionHandler, startBCI) \ - int_field(ExceptionHandler, endBCI) \ - int_field(ExceptionHandler, handlerBCI) \ - int_field(ExceptionHandler, catchTypeCPI) \ - oop_field(ExceptionHandler, catchType, "Lcom/oracle/graal/api/meta/JavaType;") \ - end_class \ - start_class(InstalledCode) \ - int_field(InstalledCode, frameSize) \ - int_field(InstalledCode, customStackAreaOffset) \ - oop_field(InstalledCode, targetCode, "[B") \ - oop_field(InstalledCode, assumptions, "Lcom/oracle/graal/api/code/Assumptions;") \ - int_field(InstalledCode, targetCodeSize) \ - end_class \ - start_class(Assumptions) \ - oop_field(Assumptions, list, "[Lcom/oracle/graal/api/code/Assumptions$Assumption;") \ - end_class \ - start_class(Assumptions_MethodContents) \ + end_class \ + start_class(ExceptionHandler) \ + int_field(ExceptionHandler, startBCI) \ + int_field(ExceptionHandler, endBCI) \ + int_field(ExceptionHandler, handlerBCI) \ + int_field(ExceptionHandler, catchTypeCPI) \ + oop_field(ExceptionHandler, catchType, "Lcom/oracle/graal/api/meta/JavaType;") \ + end_class \ + start_class(CompilationResult) \ + int_field(CompilationResult, frameSize) \ + int_field(CompilationResult, customStackAreaOffset) \ + oop_field(CompilationResult, targetCode, "[B") \ + oop_field(CompilationResult, assumptions, "Lcom/oracle/graal/api/code/Assumptions;") \ + int_field(CompilationResult, targetCodeSize) \ + end_class \ + start_class(Assumptions) \ + oop_field(Assumptions, list, "[Lcom/oracle/graal/api/code/Assumptions$Assumption;") \ + end_class \ + start_class(Assumptions_MethodContents) \ oop_field(Assumptions_MethodContents, method, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;") \ - end_class \ - start_class(Assumptions_ConcreteSubtype) \ + end_class \ + start_class(Assumptions_ConcreteSubtype) \ oop_field(Assumptions_ConcreteSubtype, context, "Lcom/oracle/graal/api/meta/ResolvedJavaType;") \ oop_field(Assumptions_ConcreteSubtype, subtype, "Lcom/oracle/graal/api/meta/ResolvedJavaType;") \ - end_class \ - start_class(Assumptions_ConcreteMethod) \ + end_class \ + start_class(Assumptions_ConcreteMethod) \ oop_field(Assumptions_ConcreteMethod, method, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;") \ oop_field(Assumptions_ConcreteMethod, context, "Lcom/oracle/graal/api/meta/ResolvedJavaType;") \ oop_field(Assumptions_ConcreteMethod, impl, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;") \ - end_class \ - start_class(InstalledCode_Site) \ - int_field(InstalledCode_Site, pcOffset) \ - end_class \ - start_class(InstalledCode_Call) \ - oop_field(InstalledCode_Call, target, "Ljava/lang/Object;") \ - oop_field(InstalledCode_Call, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;") \ - end_class \ - start_class(InstalledCode_DataPatch) \ - oop_field(InstalledCode_DataPatch, constant, "Lcom/oracle/graal/api/meta/Constant;") \ - int_field(InstalledCode_DataPatch, alignment) \ - end_class \ - start_class(InstalledCode_Safepoint) \ - oop_field(InstalledCode_Safepoint, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;") \ - end_class \ - start_class(InstalledCode_ExceptionHandler) \ - int_field(InstalledCode_ExceptionHandler, handlerPos) \ - end_class \ - start_class(InstalledCode_Mark) \ - oop_field(InstalledCode_Mark, id, "Ljava/lang/Object;") \ - oop_field(InstalledCode_Mark, references, "[Lcom/oracle/graal/api/code/CompilationResult$Mark;") \ - end_class \ - start_class(DebugInfo) \ - oop_field(DebugInfo, bytecodePosition, "Lcom/oracle/graal/api/code/BytecodePosition;") \ - oop_field(DebugInfo, registerRefMap, "Ljava/util/BitSet;") \ - oop_field(DebugInfo, frameRefMap, "Ljava/util/BitSet;") \ - end_class \ - start_class(GraalBitMap) \ - oop_field(GraalBitMap, words, "[J") \ - end_class \ - start_class(BytecodeFrame) \ - oop_field(BytecodeFrame, values, "[Lcom/oracle/graal/api/meta/Value;") \ - int_field(BytecodeFrame, numLocals) \ - int_field(BytecodeFrame, numStack) \ - int_field(BytecodeFrame, numLocks) \ - long_field(BytecodeFrame, leafGraphId) \ - boolean_field(BytecodeFrame, rethrowException) \ - boolean_field(BytecodeFrame, duringCall) \ - end_class \ - start_class(BytecodePosition) \ - oop_field(BytecodePosition, caller, "Lcom/oracle/graal/api/code/BytecodePosition;") \ - oop_field(BytecodePosition, method, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;") \ - int_field(BytecodePosition, bci) \ - end_class \ - start_class(Constant) \ - oop_field(Constant, kind, "Lcom/oracle/graal/api/meta/Kind;") \ - oop_field(Constant, object, "Ljava/lang/Object;") \ - long_field(Constant, primitive) \ - end_class \ - start_class(Kind) \ - char_field(Kind, typeChar) \ - static_oop_field(Kind, Boolean, "Lcom/oracle/graal/api/meta/Kind;"); \ - static_oop_field(Kind, Byte, "Lcom/oracle/graal/api/meta/Kind;"); \ - static_oop_field(Kind, Char, "Lcom/oracle/graal/api/meta/Kind;"); \ - static_oop_field(Kind, Short, "Lcom/oracle/graal/api/meta/Kind;"); \ - static_oop_field(Kind, Int, "Lcom/oracle/graal/api/meta/Kind;"); \ - static_oop_field(Kind, Long, "Lcom/oracle/graal/api/meta/Kind;"); \ - end_class \ - start_class(JavaMethod) \ - end_class \ - start_class(Value) \ - oop_field(Value, kind, "Lcom/oracle/graal/api/meta/Kind;") \ - static_oop_field(Value, ILLEGAL, "Lcom/oracle/graal/api/meta/Value;"); \ - end_class \ - start_class(RegisterValue) \ - oop_field(RegisterValue, reg, "Lcom/oracle/graal/api/code/Register;") \ - end_class \ - start_class(code_Register) \ - int_field(code_Register, number) \ - end_class \ - start_class(StackSlot) \ - int_field(StackSlot, offset) \ - boolean_field(StackSlot, addFrameSize) \ - end_class \ - start_class(VirtualObject) \ - int_field(VirtualObject, id) \ + end_class \ + start_class(CompilationResult_Site) \ + int_field(CompilationResult_Site, pcOffset) \ + end_class \ + start_class(CompilationResult_Call) \ + oop_field(CompilationResult_Call, target, "Ljava/lang/Object;") \ + oop_field(CompilationResult_Call, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;") \ + end_class \ + start_class(CompilationResult_DataPatch) \ + oop_field(CompilationResult_DataPatch, constant, "Lcom/oracle/graal/api/meta/Constant;") \ + int_field(CompilationResult_DataPatch, alignment) \ + end_class \ + start_class(CompilationResult_Safepoint) \ + oop_field(CompilationResult_Safepoint, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;") \ + end_class \ + start_class(CompilationResult_ExceptionHandler) \ + int_field(CompilationResult_ExceptionHandler, handlerPos) \ + end_class \ + start_class(CompilationResult_Mark) \ + oop_field(CompilationResult_Mark, id, "Ljava/lang/Object;") \ + oop_field(CompilationResult_Mark, references, "[Lcom/oracle/graal/api/code/CompilationResult$Mark;") \ + end_class \ + start_class(DebugInfo) \ + oop_field(DebugInfo, bytecodePosition, "Lcom/oracle/graal/api/code/BytecodePosition;") \ + oop_field(DebugInfo, registerRefMap, "Ljava/util/BitSet;") \ + oop_field(DebugInfo, frameRefMap, "Ljava/util/BitSet;") \ + end_class \ + start_class(GraalBitMap) \ + oop_field(GraalBitMap, words, "[J") \ + end_class \ + start_class(BytecodeFrame) \ + oop_field(BytecodeFrame, values, "[Lcom/oracle/graal/api/meta/Value;") \ + int_field(BytecodeFrame, numLocals) \ + int_field(BytecodeFrame, numStack) \ + int_field(BytecodeFrame, numLocks) \ + long_field(BytecodeFrame, leafGraphId) \ + boolean_field(BytecodeFrame, rethrowException) \ + boolean_field(BytecodeFrame, duringCall) \ + end_class \ + start_class(BytecodePosition) \ + oop_field(BytecodePosition, caller, "Lcom/oracle/graal/api/code/BytecodePosition;") \ + oop_field(BytecodePosition, method, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;") \ + int_field(BytecodePosition, bci) \ + end_class \ + start_class(Constant) \ + oop_field(Constant, kind, "Lcom/oracle/graal/api/meta/Kind;") \ + oop_field(Constant, object, "Ljava/lang/Object;") \ + long_field(Constant, primitive) \ + end_class \ + start_class(Kind) \ + char_field(Kind, typeChar) \ + static_oop_field(Kind, Boolean, "Lcom/oracle/graal/api/meta/Kind;"); \ + static_oop_field(Kind, Byte, "Lcom/oracle/graal/api/meta/Kind;"); \ + static_oop_field(Kind, Char, "Lcom/oracle/graal/api/meta/Kind;"); \ + static_oop_field(Kind, Short, "Lcom/oracle/graal/api/meta/Kind;"); \ + static_oop_field(Kind, Int, "Lcom/oracle/graal/api/meta/Kind;"); \ + static_oop_field(Kind, Long, "Lcom/oracle/graal/api/meta/Kind;"); \ + end_class \ + start_class(JavaMethod) \ + end_class \ + start_class(Value) \ + oop_field(Value, kind, "Lcom/oracle/graal/api/meta/Kind;") \ + static_oop_field(Value, ILLEGAL, "Lcom/oracle/graal/api/meta/Value;"); \ + end_class \ + start_class(RegisterValue) \ + oop_field(RegisterValue, reg, "Lcom/oracle/graal/api/code/Register;") \ + end_class \ + start_class(code_Register) \ + int_field(code_Register, number) \ + end_class \ + start_class(StackSlot) \ + int_field(StackSlot, offset) \ + boolean_field(StackSlot, addFrameSize) \ + end_class \ + start_class(VirtualObject) \ + int_field(VirtualObject, id) \ oop_field(VirtualObject, type, "Lcom/oracle/graal/api/meta/JavaType;") \ - oop_field(VirtualObject, values, "[Lcom/oracle/graal/api/meta/Value;") \ - end_class \ - start_class(code_MonitorValue) \ - oop_field(code_MonitorValue, owner, "Lcom/oracle/graal/api/meta/Value;") \ - oop_field(code_MonitorValue, lockData, "Lcom/oracle/graal/api/meta/Value;") \ - boolean_field(code_MonitorValue, eliminated) \ - end_class \ + oop_field(VirtualObject, values, "[Lcom/oracle/graal/api/meta/Value;") \ + end_class \ + start_class(code_MonitorValue) \ + oop_field(code_MonitorValue, owner, "Lcom/oracle/graal/api/meta/Value;") \ + oop_field(code_MonitorValue, lockData, "Lcom/oracle/graal/api/meta/Value;") \ + boolean_field(code_MonitorValue, eliminated) \ + end_class \ /* end*/ #define START_CLASS(name) \
--- a/src/share/vm/interpreter/bytecodes.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/interpreter/bytecodes.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -424,6 +424,8 @@ || code == _fconst_0 || code == _dconst_0); } static bool is_invoke (Code code) { return (_invokevirtual <= code && code <= _invokedynamic); } + static bool has_optional_appendix(Code code) { return code == _invokedynamic || code == _invokehandle; } + static int compute_flags (const char* format, int more_flags = 0); // compute the flags static int flags (int code, bool is_wide) { assert(code == (u_char)code, "must be a byte");
--- a/src/share/vm/memory/tenuredGeneration.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/memory/tenuredGeneration.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,8 +23,8 @@ */ #include "precompiled.hpp" -#include "gc_implementation/parNew/parGCAllocBuffer.hpp" #include "gc_implementation/shared/collectorCounters.hpp" +#include "gc_implementation/shared/parGCAllocBuffer.hpp" #include "memory/allocation.inline.hpp" #include "memory/blockOffsetTable.inline.hpp" #include "memory/generation.inline.hpp"
--- a/src/share/vm/opto/c2_globals.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/c2_globals.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -353,27 +353,9 @@ develop(bool, StressRecompilation, false, \ "Recompile each compiled method without subsuming loads or escape analysis.") \ \ - /* controls for tier 1 compilations */ \ - \ - develop(bool, Tier1CountInvocations, true, \ - "Generate code, during tier 1, to update invocation counter") \ - \ - product(intx, Tier1Inline, false, \ - "enable inlining during tier 1") \ - \ - product(intx, Tier1MaxInlineSize, 8, \ - "maximum bytecode size of a method to be inlined, during tier 1") \ - \ - product(intx, Tier1FreqInlineSize, 35, \ - "max bytecode size of a frequent method to be inlined, tier 1") \ - \ develop(intx, ImplicitNullCheckThreshold, 3, \ "Don't do implicit null checks if NPE's in a method exceeds limit") \ \ - /* controls for loop optimization */ \ - product(intx, Tier1LoopOptsCount, 0, \ - "Set level of loop optimization for tier 1 compiles") \ - \ product(intx, LoopOptsCount, 43, \ "Set level of loop optimization for tier 1 compiles") \ \ @@ -505,6 +487,116 @@ \ product(bool, BlockLayoutRotateLoops, true, \ "Allow back branches to be fall throughs in the block layour") \ + \ + develop(bool, InlineReflectionGetCallerClass, true, \ + "inline sun.reflect.Reflection.getCallerClass(), known to be part "\ + "of base library DLL") \ + \ + develop(bool, InlineObjectCopy, true, \ + "inline Object.clone and Arrays.copyOf[Range] intrinsics") \ + \ + develop(bool, SpecialStringCompareTo, true, \ + "special version of string compareTo") \ + \ + develop(bool, SpecialStringIndexOf, true, \ + "special version of string indexOf") \ + \ + develop(bool, SpecialStringEquals, true, \ + "special version of string equals") \ + \ + develop(bool, SpecialArraysEquals, true, \ + "special version of Arrays.equals(char[],char[])") \ + \ + develop(bool, BailoutToInterpreterForThrows, false, \ + "Compiled methods which throws/catches exceptions will be " \ + "deopt and intp.") \ + \ + develop(bool, ConvertCmpD2CmpF, true, \ + "Convert cmpD to cmpF when one input is constant in float range") \ + \ + develop(bool, ConvertFloat2IntClipping, true, \ + "Convert float2int clipping idiom to integer clipping") \ + \ + develop(bool, Use24BitFPMode, true, \ + "Set 24-bit FPU mode on a per-compile basis ") \ + \ + develop(bool, Use24BitFP, true, \ + "use FP instructions that produce 24-bit precise results") \ + \ + develop(bool, MonomorphicArrayCheck, true, \ + "Uncommon-trap array store checks that require full type check") \ + \ + notproduct(bool, TracePhaseCCP, false, \ + "Print progress during Conditional Constant Propagation") \ + \ + develop(bool, PrintDominators, false, \ + "Print out dominator trees for GVN") \ + \ + notproduct(bool, TraceSpilling, false, \ + "Trace spilling") \ + \ + notproduct(bool, TraceTypeProfile, false, \ + "Trace type profile") \ + \ + develop(bool, PoisonOSREntry, true, \ + "Detect abnormal calls to OSR code") \ + \ + product(bool, UseCondCardMark, false, \ + "Check for already marked card before updating card table") \ + \ + develop(bool, SoftMatchFailure, trueInProduct, \ + "If the DFA fails to match a node, print a message and bail out") \ + \ + develop(bool, InlineAccessors, true, \ + "inline accessor methods (get/set)") \ + \ + product(intx, TypeProfileMajorReceiverPercent, 90, \ + "% of major receiver type to all profiled receivers") \ + \ + notproduct(bool, TimeCompiler2, false, \ + "detailed time the compiler (requires +TimeCompiler)") \ + \ + diagnostic(bool, PrintIntrinsics, false, \ + "prints attempted and successful inlining of intrinsics") \ + \ + diagnostic(ccstrlist, DisableIntrinsic, "", \ + "do not expand intrinsics whose (internal) names appear here") \ + \ + develop(bool, StressReflectiveCode, false, \ + "Use inexact types at allocations, etc., to test reflection") \ + \ + diagnostic(bool, DebugInlinedCalls, true, \ + "If false, restricts profiled locations to the root method only") \ + \ + notproduct(bool, VerifyLoopOptimizations, false, \ + "verify major loop optimizations") \ + \ + diagnostic(bool, ProfileDynamicTypes, true, \ + "do extra type profiling and use it more aggressively") \ + \ + develop(bool, TraceIterativeGVN, false, \ + "Print progress during Iterative Global Value Numbering") \ + \ + develop(bool, VerifyIterativeGVN, false, \ + "Verify Def-Use modifications during sparse Iterative Global " \ + "Value Numbering") \ + \ + notproduct(bool, TraceCISCSpill, false, \ + "Trace allocators use of cisc spillable instructions") \ + \ + product(bool, SplitIfBlocks, true, \ + "Clone compares and control flow through merge points to fold " \ + "some branches") \ + \ + develop(intx, FreqCountInvocations, 1, \ + "Scaling factor for branch frequencies (deprecated)") \ + \ + product(intx, AliasLevel, 3, \ + "0 for no aliasing, 1 for oop/field/static/array split, " \ + "2 for class split, 3 for unique instances") \ + \ + develop(bool, VerifyAliases, false, \ + "perform extra checks on the results of alias analysis") \ C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG)
--- a/src/share/vm/opto/callGenerator.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/callGenerator.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -158,74 +158,6 @@ return kit.transfer_exceptions_into_jvms(); } -//---------------------------DynamicCallGenerator----------------------------- -// Internal class which handles all out-of-line invokedynamic calls. -class DynamicCallGenerator : public CallGenerator { -public: - DynamicCallGenerator(ciMethod* method) - : CallGenerator(method) - { - } - virtual JVMState* generate(JVMState* jvms); -}; - -JVMState* DynamicCallGenerator::generate(JVMState* jvms) { - GraphKit kit(jvms); - Compile* C = kit.C; - PhaseGVN& gvn = kit.gvn(); - - if (C->log() != NULL) { - C->log()->elem("dynamic_call bci='%d'", jvms->bci()); - } - - // Get the constant pool cache from the caller class. - ciMethod* caller_method = jvms->method(); - ciBytecodeStream str(caller_method); - str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. - assert(str.cur_bc() == Bytecodes::_invokedynamic, "wrong place to issue a dynamic call!"); - ciCPCache* cpcache = str.get_cpcache(); - - // Get the offset of the CallSite from the constant pool cache - // pointer. - int index = str.get_method_index(); - size_t call_site_offset = cpcache->get_f1_offset(index); - - // Load the CallSite object from the constant pool cache. - const TypeOopPtr* cpcache_type = TypeOopPtr::make_from_constant(cpcache); // returns TypeAryPtr of type T_OBJECT - const TypeOopPtr* call_site_type = TypeOopPtr::make_from_klass(C->env()->CallSite_klass()); - Node* cpcache_adr = kit.makecon(cpcache_type); - Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, call_site_offset); - // The oops in the constant pool cache are not compressed; load then as raw pointers. - Node* call_site = kit.make_load(kit.control(), call_site_adr, call_site_type, T_ADDRESS, Compile::AliasIdxRaw); - - // Load the target MethodHandle from the CallSite object. - const TypeOopPtr* target_type = TypeOopPtr::make_from_klass(C->env()->MethodHandle_klass()); - Node* target_mh_adr = kit.basic_plus_adr(call_site, java_lang_invoke_CallSite::target_offset_in_bytes()); - Node* target_mh = kit.make_load(kit.control(), target_mh_adr, target_type, T_OBJECT); - - address resolve_stub = SharedRuntime::get_resolve_opt_virtual_call_stub(); - - CallStaticJavaNode* call = new (C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), resolve_stub, method(), kit.bci()); - // invokedynamic is treated as an optimized invokevirtual. - call->set_optimized_virtual(true); - // Take extra care (in the presence of argument motion) not to trash the SP: - call->set_method_handle_invoke(true); - - // Pass the target MethodHandle as first argument and shift the - // other arguments. - call->init_req(0 + TypeFunc::Parms, target_mh); - uint nargs = call->method()->arg_size(); - for (uint i = 1; i < nargs; i++) { - Node* arg = kit.argument(i - 1); - call->init_req(i + TypeFunc::Parms, arg); - } - - kit.set_edges_for_java_call(call); - Node* ret = kit.set_results_for_java_call(call); - kit.push_node(method()->return_type()->basic_type(), ret); - return kit.transfer_exceptions_into_jvms(); -} - //--------------------------VirtualCallGenerator------------------------------ // Internal class which handles all out-of-line calls checking receiver type. class VirtualCallGenerator : public CallGenerator { @@ -328,12 +260,6 @@ return new VirtualCallGenerator(m, vtable_index); } -CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) { - assert(m->is_compiled_lambda_form(), "for_dynamic_call mismatch"); - //@@ FIXME: this should be done via a direct call - return new DynamicCallGenerator(m); -} - // Allow inlining decisions to be delayed class LateInlineCallGenerator : public DirectCallGenerator { CallGenerator* _inline_cg; @@ -347,7 +273,7 @@ // Convert the CallStaticJava into an inline virtual void do_late_inline(); - JVMState* generate(JVMState* jvms) { + virtual JVMState* generate(JVMState* jvms) { // Record that this call site should be revisited once the main // parse is finished. Compile::current()->add_late_inline(this);
--- a/src/share/vm/opto/chaitin.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/chaitin.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -222,6 +222,7 @@ _alternate = 0; _matcher._allocation_started = true; + ResourceArea split_arena; // Arena for Split local resources ResourceArea live_arena; // Arena for liveness & IFG info ResourceMark rm(&live_arena); @@ -324,7 +325,7 @@ // Bail out if unique gets too large (ie - unique > MaxNodeLimit) C->check_node_count(10*must_spill, "out of nodes before split"); if (C->failing()) return; - _maxlrg = Split( _maxlrg ); // Split spilling LRG everywhere + _maxlrg = Split(_maxlrg, &split_arena); // Split spilling LRG everywhere // Bail out if unique gets too large (ie - unique > MaxNodeLimit - 2*NodeLimitFudgeFactor) // or we failed to split C->check_node_count(2*NodeLimitFudgeFactor, "out of nodes after physical split"); @@ -390,7 +391,7 @@ } if( !_maxlrg ) return; - _maxlrg = Split( _maxlrg ); // Split spilling LRG everywhere + _maxlrg = Split(_maxlrg, &split_arena); // Split spilling LRG everywhere // Bail out if unique gets too large (ie - unique > MaxNodeLimit - 2*NodeLimitFudgeFactor) C->check_node_count(2*NodeLimitFudgeFactor, "out of nodes after split"); if (C->failing()) return; @@ -484,24 +485,33 @@ if (_names[i]) { // Live range associated with Node? LRG &lrg = lrgs(_names[i]); if (!lrg.alive()) { - _node_regs[i].set_bad(); + set_bad(i); } else if (lrg.num_regs() == 1) { - _node_regs[i].set1(lrg.reg()); - } else { // Must be a register-pair - if (!lrg._fat_proj) { // Must be aligned adjacent register pair + set1(i, lrg.reg()); + } else { // Must be a register-set + if (!lrg._fat_proj) { // Must be aligned adjacent register set // Live ranges record the highest register in their mask. // We want the low register for the AD file writer's convenience. - _node_regs[i].set2( OptoReg::add(lrg.reg(),(1-lrg.num_regs())) ); + OptoReg::Name hi = lrg.reg(); // Get hi register + OptoReg::Name lo = OptoReg::add(hi, (1-lrg.num_regs())); // Find lo + // We have to use pair [lo,lo+1] even for wide vectors because + // the rest of code generation works only with pairs. It is safe + // since for registers encoding only 'lo' is used. + // Second reg from pair is used in ScheduleAndBundle on SPARC where + // vector max size is 8 which corresponds to registers pair. + // It is also used in BuildOopMaps but oop operations are not + // vectorized. + set2(i, lo); } else { // Misaligned; extract 2 bits OptoReg::Name hi = lrg.reg(); // Get hi register lrg.Remove(hi); // Yank from mask int lo = lrg.mask().find_first_elem(); // Find lo - _node_regs[i].set_pair( hi, lo ); + set_pair(i, hi, lo); } } if( lrg._is_oop ) _node_oops.set(i); } else { - _node_regs[i].set_bad(); + set_bad(i); } } @@ -1121,6 +1131,33 @@ } +//------------------------------is_legal_reg----------------------------------- +// Is 'reg' register legal for 'lrg'? +static bool is_legal_reg(LRG &lrg, OptoReg::Name reg, int chunk) { + if (reg >= chunk && reg < (chunk + RegMask::CHUNK_SIZE) && + lrg.mask().Member(OptoReg::add(reg,-chunk))) { + // RA uses OptoReg which represent the highest element of a registers set. + // For example, vectorX (128bit) on x86 uses [XMM,XMMb,XMMc,XMMd] set + // in which XMMd is used by RA to represent such vectors. A double value + // uses [XMM,XMMb] pairs and XMMb is used by RA for it. + // The register mask uses largest bits set of overlapping register sets. + // On x86 with AVX it uses 8 bits for each XMM registers set. + // + // The 'lrg' already has cleared-to-set register mask (done in Select() + // before calling choose_color()). Passing mask.Member(reg) check above + // indicates that the size (num_regs) of 'reg' set is less or equal to + // 'lrg' set size. + // For set size 1 any register which is member of 'lrg' mask is legal. + if (lrg.num_regs()==1) + return true; + // For larger sets only an aligned register with the same set size is legal. + int mask = lrg.num_regs()-1; + if ((reg&mask) == mask) + return true; + } + return false; +} + //------------------------------bias_color------------------------------------- // Choose a color using the biasing heuristic OptoReg::Name PhaseChaitin::bias_color( LRG &lrg, int chunk ) { @@ -1137,10 +1174,7 @@ while ((datum = elements.next()) != 0) { OptoReg::Name reg = lrgs(datum).reg(); // If this LRG's register is legal for us, choose it - if( reg >= chunk && reg < chunk + RegMask::CHUNK_SIZE && - lrg.mask().Member(OptoReg::add(reg,-chunk)) && - (lrg.num_regs()==1 || // either size 1 - (reg&1) == 1) ) // or aligned (adjacent reg is available since we already cleared-to-pairs) + if (is_legal_reg(lrg, reg, chunk)) return reg; } } @@ -1151,10 +1185,7 @@ if( !(*(_ifg->_yanked))[copy_lrg] ) { OptoReg::Name reg = lrgs(copy_lrg).reg(); // And it is legal for you, - if( reg >= chunk && reg < chunk + RegMask::CHUNK_SIZE && - lrg.mask().Member(OptoReg::add(reg,-chunk)) && - (lrg.num_regs()==1 || // either size 1 - (reg&1) == 1) ) // or aligned (adjacent reg is available since we already cleared-to-pairs) + if (is_legal_reg(lrg, reg, chunk)) return reg; } else if( chunk == 0 ) { // Choose a color which is legal for him
--- a/src/share/vm/opto/chaitin.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/chaitin.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -470,7 +470,7 @@ // Split uncolorable live ranges // Return new number of live ranges - uint Split( uint maxlrg ); + uint Split(uint maxlrg, ResourceArea* split_arena); // Copy 'was_spilled'-edness from one Node to another. void copy_was_spilled( Node *src, Node *dst );
--- a/src/share/vm/opto/classes.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/classes.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -256,6 +256,8 @@ macro(SubVL) macro(SubVF) macro(SubVD) +macro(MulVS) +macro(MulVI) macro(MulVF) macro(MulVD) macro(DivVF) @@ -263,9 +265,15 @@ macro(LShiftVB) macro(LShiftVS) macro(LShiftVI) +macro(LShiftVL) macro(RShiftVB) macro(RShiftVS) macro(RShiftVI) +macro(RShiftVL) +macro(URShiftVB) +macro(URShiftVS) +macro(URShiftVI) +macro(URShiftVL) macro(AndV) macro(OrV) macro(XorV)
--- a/src/share/vm/opto/compile.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/compile.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -2604,7 +2604,7 @@ if (n->req()-1 > 2) { // Replace many operand PackNodes with a binary tree for matching PackNode* p = (PackNode*) n; - Node* btp = p->binaryTreePack(Compile::current(), 1, n->req()); + Node* btp = p->binary_tree_pack(Compile::current(), 1, n->req()); n->subsume_by(btp); } break;
--- a/src/share/vm/opto/doCall.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/doCall.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -341,25 +341,26 @@ kill_dead_locals(); // Set frequently used booleans - bool is_virtual = bc() == Bytecodes::_invokevirtual; - bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface; - bool has_receiver = is_virtual_or_interface || bc() == Bytecodes::_invokespecial; - bool is_invokedynamic = bc() == Bytecodes::_invokedynamic; + const bool is_virtual = bc() == Bytecodes::_invokevirtual; + const bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface; + const bool has_receiver = is_virtual_or_interface || bc() == Bytecodes::_invokespecial; // Find target being called bool will_link; - ciMethod* bc_callee = iter().get_method(will_link); // actual callee from bytecode - ciInstanceKlass* holder_klass = bc_callee->holder(); - ciKlass* holder = iter().get_declared_method_holder(); + ciSignature* declared_signature = NULL; + ciMethod* orig_callee = iter().get_method(will_link, &declared_signature); // callee in the bytecode + ciInstanceKlass* holder_klass = orig_callee->holder(); + ciKlass* holder = iter().get_declared_method_holder(); ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder); + assert(declared_signature != NULL, "cannot be null"); // uncommon-trap when callee is unloaded, uninitialized or will not link // bailout when too many arguments for register representation - if (!will_link || can_not_compile_call_site(bc_callee, klass)) { + if (!will_link || can_not_compile_call_site(orig_callee, klass)) { #ifndef PRODUCT if (PrintOpto && (Verbose || WizardMode)) { method()->print_name(); tty->print_cr(" can not compile call at bci %d to:", bci()); - bc_callee->print_name(); tty->cr(); + orig_callee->print_name(); tty->cr(); } #endif return; @@ -372,7 +373,7 @@ // Note: In the absence of miranda methods, an abstract class K can perform // an invokevirtual directly on an interface method I.m if K implements I. - const int nargs = bc_callee->arg_size(); + const int nargs = orig_callee->arg_size(); // Push appendix argument (MethodType, CallSite, etc.), if one. if (iter().has_appendix()) { @@ -392,13 +393,13 @@ // Choose call strategy. bool call_is_virtual = is_virtual_or_interface; int vtable_index = methodOopDesc::invalid_vtable_index; - ciMethod* callee = bc_callee; + ciMethod* callee = orig_callee; // Try to get the most accurate receiver type if (is_virtual_or_interface) { Node* receiver_node = stack(sp() - nargs); const TypeOopPtr* receiver_type = _gvn.type(receiver_node)->isa_oopptr(); - ciMethod* optimized_virtual_method = optimize_inlining(method(), bci(), klass, bc_callee, receiver_type); + ciMethod* optimized_virtual_method = optimize_inlining(method(), bci(), klass, orig_callee, receiver_type); // Have the call been sufficiently improved such that it is no longer a virtual? if (optimized_virtual_method != NULL) { @@ -425,7 +426,8 @@ // It decides whether inlining is desirable or not. CallGenerator* cg = C->call_generator(callee, vtable_index, call_is_virtual, jvms, try_inline, prof_factor()); - bc_callee = callee = NULL; // don't use bc_callee and callee after this point + // NOTE: Don't use orig_callee and callee after this point! Use cg->method() instead. + orig_callee = callee = NULL; // --------------------- // Round double arguments before call @@ -497,9 +499,9 @@ round_double_result(cg->method()); ciType* rtype = cg->method()->return_type(); - if (iter().cur_bc_raw() == Bytecodes::_invokehandle || is_invokedynamic) { + if (Bytecodes::has_optional_appendix(iter().cur_bc_raw())) { // Be careful here with return types. - ciType* ctype = iter().get_declared_method_signature()->return_type(); + ciType* ctype = declared_signature->return_type(); if (ctype != rtype) { BasicType rt = rtype->basic_type(); BasicType ct = ctype->basic_type(); @@ -528,15 +530,13 @@ } else if (rt == T_OBJECT || rt == T_ARRAY) { assert(ct == T_OBJECT || ct == T_ARRAY, err_msg_res("rt=%s, ct=%s", type2name(rt), type2name(ct))); if (ctype->is_loaded()) { - Node* if_fail = top(); - retnode = gen_checkcast(retnode, makecon(TypeKlassPtr::make(ctype->as_klass())), &if_fail); - if (if_fail != top()) { - PreserveJVMState pjvms(this); - set_control(if_fail); - builtin_throw(Deoptimization::Reason_class_check); + const TypeOopPtr* arg_type = TypeOopPtr::make_from_klass(rtype->as_klass()); + const Type* sig_type = TypeOopPtr::make_from_klass(ctype->as_klass()); + if (arg_type != NULL && !arg_type->higher_equal(sig_type)) { + Node* cast_obj = _gvn.transform(new (C, 2) CheckCastPPNode(control(), retnode, sig_type)); + pop(); + push(cast_obj); } - pop(); - push(retnode); } } else { assert(ct == rt, err_msg_res("unexpected mismatch rt=%d, ct=%d", rt, ct));
--- a/src/share/vm/opto/graphKit.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/graphKit.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -1006,11 +1006,11 @@ case Bytecodes::_putfield: { bool is_get = (depth >= 0), is_static = (depth & 1); - bool ignore; ciBytecodeStream iter(method()); iter.reset_to_bci(bci()); iter.next(); - ciField* field = iter.get_field(ignore); + bool ignored_will_link; + ciField* field = iter.get_field(ignored_will_link); int size = field->type()->size(); inputs = (is_static ? 0 : 1); if (is_get) { @@ -1028,11 +1028,13 @@ case Bytecodes::_invokedynamic: case Bytecodes::_invokeinterface: { - bool ignore; ciBytecodeStream iter(method()); iter.reset_to_bci(bci()); iter.next(); - ciMethod* callee = iter.get_method(ignore); + bool ignored_will_link; + ciSignature* declared_signature = NULL; + ciMethod* callee = iter.get_method(ignored_will_link, &declared_signature); + assert(declared_signature != NULL, "cannot be null"); // (Do not use ciMethod::arg_size(), because // it might be an unloaded method, which doesn't // know whether it is static or not.) @@ -1046,7 +1048,7 @@ // remove any appendix arguments that were popped. inputs = callee->invoke_arg_size(code) - (callee->has_member_arg() ? 1 : 0); } - int size = callee->return_type()->size(); + int size = declared_signature->return_type()->size(); depth = size - inputs; } break;
--- a/src/share/vm/opto/idealKit.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/idealKit.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -295,7 +295,11 @@ if (_delay_all_transforms) { return delay_transform(n); } else { - return gvn().transform(n); + n = gvn().transform(n); + if (!gvn().is_IterGVN()) { + C->record_for_igvn(n); + } + return n; } }
--- a/src/share/vm/opto/library_call.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/library_call.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -171,7 +171,7 @@ // Helper for inline_unsafe_access. // Generates the guards that check whether the result of // Unsafe.getObject should be recorded in an SATB log buffer. - void insert_g1_pre_barrier(Node* base_oop, Node* offset, Node* pre_val); + void insert_pre_barrier(Node* base_oop, Node* offset, Node* pre_val, int nargs, bool need_mem_bar); bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, bool is_volatile); bool inline_unsafe_prefetch(bool is_native_ptr, bool is_store, bool is_static); bool inline_unsafe_allocate(); @@ -291,6 +291,8 @@ case vmIntrinsics::_equals: case vmIntrinsics::_equalsC: break; // InlineNatives does not control String.compareTo + case vmIntrinsics::_Reference_get: + break; // InlineNatives does not control Reference.get default: return NULL; } @@ -361,11 +363,10 @@ break; case vmIntrinsics::_Reference_get: - // It is only when G1 is enabled that we absolutely - // need to use the intrinsic version of Reference.get() - // so that the value in the referent field, if necessary, - // can be registered by the pre-barrier code. - if (!UseG1GC) return NULL; + // Use the intrinsic version of Reference.get() so that the value in + // the referent field can be registered by the G1 pre-barrier code. + // Also add memory barrier to prevent commoning reads from this field + // across safepoint since GC can change it value. break; default: @@ -2195,14 +2196,17 @@ const static BasicType T_ADDRESS_HOLDER = T_LONG; -// Helper that guards and inserts a G1 pre-barrier. -void LibraryCallKit::insert_g1_pre_barrier(Node* base_oop, Node* offset, Node* pre_val) { - assert(UseG1GC, "should not call this otherwise"); - +// Helper that guards and inserts a pre-barrier. +void LibraryCallKit::insert_pre_barrier(Node* base_oop, Node* offset, + Node* pre_val, int nargs, bool need_mem_bar) { // We could be accessing the referent field of a reference object. If so, when G1 // is enabled, we need to log the value in the referent field in an SATB buffer. // This routine performs some compile time filters and generates suitable // runtime filters that guard the pre-barrier code. + // Also add memory barrier for non volatile load from the referent field + // to prevent commoning of loads across safepoint. + if (!UseG1GC && !need_mem_bar) + return; // Some compile time checks. @@ -2224,11 +2228,12 @@ const TypeInstPtr* itype = btype->isa_instptr(); if (itype != NULL) { - // Can the klass of base_oop be statically determined - // to be _not_ a sub-class of Reference? + // Can the klass of base_oop be statically determined to be + // _not_ a sub-class of Reference and _not_ Object? ciKlass* klass = itype->klass(); - if (klass->is_subtype_of(env()->Reference_klass()) && - !env()->Reference_klass()->is_subtype_of(klass)) { + if ( klass->is_loaded() && + !klass->is_subtype_of(env()->Reference_klass()) && + !env()->Object_klass()->is_subtype_of(klass)) { return; } } @@ -2238,10 +2243,8 @@ // we need to generate the following runtime filters // // if (offset == java_lang_ref_Reference::_reference_offset) { - // if (base != null) { - // if (instance_of(base, java.lang.ref.Reference)) { - // pre_barrier(_, pre_val, ...); - // } + // if (instance_of(base, java.lang.ref.Reference)) { + // pre_barrier(_, pre_val, ...); // } // } @@ -2254,19 +2257,19 @@ Node* referent_off = __ ConX(java_lang_ref_Reference::referent_offset); __ if_then(offset, BoolTest::eq, referent_off, unlikely); { - __ if_then(base_oop, BoolTest::ne, null(), likely); { - // Update graphKit memory and control from IdealKit. sync_kit(ideal); Node* ref_klass_con = makecon(TypeKlassPtr::make(env()->Reference_klass())); + _sp += nargs; // gen_instanceof might do an uncommon trap Node* is_instof = gen_instanceof(base_oop, ref_klass_con); + _sp -= nargs; // Update IdealKit memory and control from graphKit. __ sync_kit(this); Node* one = __ ConI(1); - + // is_instof == 0 if base_oop == NULL __ if_then(is_instof, BoolTest::eq, one, unlikely); { // Update graphKit from IdeakKit. @@ -2278,12 +2281,15 @@ NULL /* obj */, NULL /* adr */, max_juint /* alias_idx */, NULL /* val */, NULL /* val_type */, pre_val /* pre_val */, T_OBJECT); - + if (need_mem_bar) { + // Add memory barrier to prevent commoning reads from this field + // across safepoint since GC can change its value. + insert_mem_bar(Op_MemBarCPUOrder); + } // Update IdealKit from graphKit. __ sync_kit(this); } __ end_if(); // _ref_type != ref_none - } __ end_if(); // base != NULL } __ end_if(); // offset == referent_offset // Final sync IdealKit and GraphKit. @@ -2418,7 +2424,9 @@ // object (either by using Unsafe directly or through reflection) // then, if G1 is enabled, we need to record the referent in an // SATB log buffer using the pre-barrier mechanism. - bool need_read_barrier = UseG1GC && !is_native_ptr && !is_store && + // Also we need to add memory barrier to prevent commoning reads + // from this field across safepoint since GC can change its value. + bool need_read_barrier = !is_native_ptr && !is_store && offset != top() && heap_base_oop != top(); if (!is_store && type == T_OBJECT) { @@ -2508,7 +2516,7 @@ break; case T_OBJECT: if (need_read_barrier) { - insert_g1_pre_barrier(heap_base_oop, offset, p); + insert_pre_barrier(heap_base_oop, offset, p, nargs, !(is_volatile || need_mem_bar)); } push(p); break; @@ -5484,6 +5492,10 @@ result /* pre_val */, T_OBJECT); + // Add memory barrier to prevent commoning reads from this field + // across safepoint since GC can change its value. + insert_mem_bar(Op_MemBarCPUOrder); + push(result); return true; }
--- a/src/share/vm/opto/loopTransform.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/loopTransform.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -547,11 +547,6 @@ Node *nnn = old_new[old->_idx]; if (!has_ctrl(nnn)) set_idom(nnn, idom(nnn), dd-1); - // While we're at it, remove any SafePoints from the peeled code - if (old->Opcode() == Op_SafePoint) { - Node *nnn = old_new[old->_idx]; - lazy_replace(nnn,nnn->in(TypeFunc::Control)); - } } // Now force out all loop-invariant dominating tests. The optimizer
--- a/src/share/vm/opto/loopnode.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/loopnode.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -577,6 +577,9 @@ Node *sfpt = x->in(LoopNode::LoopBackControl); if (sfpt->Opcode() == Op_SafePoint && is_deleteable_safept(sfpt)) { lazy_replace( sfpt, iftrue ); + if (loop->_safepts != NULL) { + loop->_safepts->yank(sfpt); + } loop->_tail = iftrue; } @@ -668,8 +671,12 @@ // Check for immediately preceding SafePoint and remove Node *sfpt2 = le->in(0); - if (sfpt2->Opcode() == Op_SafePoint && is_deleteable_safept(sfpt2)) + if (sfpt2->Opcode() == Op_SafePoint && is_deleteable_safept(sfpt2)) { lazy_replace( sfpt2, sfpt2->in(TypeFunc::Control)); + if (loop->_safepts != NULL) { + loop->_safepts->yank(sfpt2); + } + } // Free up intermediate goo _igvn.remove_dead_node(hook); @@ -1526,10 +1533,8 @@ void IdealLoopTree::check_safepts(VectorSet &visited, Node_List &stack) { // Bottom up traversal IdealLoopTree* ch = _child; - while (ch != NULL) { - ch->check_safepts(visited, stack); - ch = ch->_next; - } + if (_child) _child->check_safepts(visited, stack); + if (_next) _next ->check_safepts(visited, stack); if (!_head->is_CountedLoop() && !_has_sfpt && _parent != NULL && !_irreducible) { bool has_call = false; // call on dom-path @@ -1702,29 +1707,39 @@ phase->is_counted_loop(_head, this)) { _has_sfpt = 1; // Indicate we do not need a safepoint here - // Look for a safepoint to remove - for (Node* n = tail(); n != _head; n = phase->idom(n)) - if (n->Opcode() == Op_SafePoint && phase->get_loop(n) == this && - phase->is_deleteable_safept(n)) - phase->lazy_replace(n,n->in(TypeFunc::Control)); + // Look for safepoints to remove. + Node_List* sfpts = _safepts; + if (sfpts != NULL) { + for (uint i = 0; i < sfpts->size(); i++) { + Node* n = sfpts->at(i); + assert(phase->get_loop(n) == this, ""); + if (phase->is_deleteable_safept(n)) { + phase->lazy_replace(n, n->in(TypeFunc::Control)); + } + } + } // Look for induction variables phase->replace_parallel_iv(this); } else if (_parent != NULL && !_irreducible) { // Not a counted loop. - // Look for a safepoint on the idom-path to remove, preserving the first one - bool found = false; - Node* n = tail(); - for (; n != _head && !found; n = phase->idom(n)) { - if (n->Opcode() == Op_SafePoint && phase->get_loop(n) == this) - found = true; // Found one + // Look for a safepoint on the idom-path. + Node* sfpt = tail(); + for (; sfpt != _head; sfpt = phase->idom(sfpt)) { + if (sfpt->Opcode() == Op_SafePoint && phase->get_loop(sfpt) == this) + break; // Found one } - // Skip past it and delete the others - for (; n != _head; n = phase->idom(n)) { - if (n->Opcode() == Op_SafePoint && phase->get_loop(n) == this && - phase->is_deleteable_safept(n)) - phase->lazy_replace(n,n->in(TypeFunc::Control)); + // Delete other safepoints in this loop. + Node_List* sfpts = _safepts; + if (sfpts != NULL && sfpt != _head && sfpt->Opcode() == Op_SafePoint) { + for (uint i = 0; i < sfpts->size(); i++) { + Node* n = sfpts->at(i); + assert(phase->get_loop(n) == this, ""); + if (n != sfpt && phase->is_deleteable_safept(n)) { + phase->lazy_replace(n, n->in(TypeFunc::Control)); + } + } } } @@ -1773,6 +1788,8 @@ if (stride_con > 0) tty->print("+"); tty->print("%d", stride_con); + tty->print(" (%d iters) ", (int)cl->profile_trip_cnt()); + if (cl->is_pre_loop ()) tty->print(" pre" ); if (cl->is_main_loop()) tty->print(" main"); if (cl->is_post_loop()) tty->print(" post"); @@ -2764,6 +2781,10 @@ // if the allocation is not eliminated for some reason. innermost->_allow_optimizations = false; innermost->_has_call = 1; // = true + } else if (n->Opcode() == Op_SafePoint) { + // Record all safepoints in this loop. + if (innermost->_safepts == NULL) innermost->_safepts = new Node_List(); + innermost->_safepts->push(n); } } } @@ -2814,6 +2835,9 @@ is_deleteable_safept(n)) { Node *in = n->in(TypeFunc::Control); lazy_replace(n,in); // Pull safepoint now + if (ilt->_safepts != NULL) { + ilt->_safepts->yank(n); + } // Carry on with the recursion "as if" we are walking // only the control input if( !visited.test_set( in->_idx ) ) {
--- a/src/share/vm/opto/loopnode.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/loopnode.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -336,6 +336,7 @@ _has_sfpt:1, // True if has non-call safepoint _rce_candidate:1; // True if candidate for range check elimination + Node_List* _safepts; // List of safepoints in this loop Node_List* _required_safept; // A inner loop cannot delete these safepts; bool _allow_optimizations; // Allow loop optimizations @@ -343,6 +344,7 @@ : _parent(0), _next(0), _child(0), _head(head), _tail(tail), _phase(phase), + _safepts(NULL), _required_safept(NULL), _allow_optimizations(true), _nest(0), _irreducible(0), _has_call(0), _has_sfpt(0), _rce_candidate(0)
--- a/src/share/vm/opto/output.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/output.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -1874,6 +1874,8 @@ if (!do_scheduling()) return; + assert(MaxVectorSize <= 8, "scheduling code works only with pairs"); + NOT_PRODUCT( TracePhase t2("isched", &_t_instrSched, TimeCompiler); ) // Create a data structure for all the scheduling information
--- a/src/share/vm/opto/reg_split.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/reg_split.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -449,9 +449,12 @@ // USES: If USE is in HRP, split at use to leave main LRG on stack. // Else, hoist LRG back up to register only (ie - split is also DEF) // We will compute a new maxlrg as we go -uint PhaseChaitin::Split( uint maxlrg ) { +uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { NOT_PRODUCT( Compile::TracePhase t3("regAllocSplit", &_t_regAllocSplit, TimeCompiler); ) + // Free thread local resources used by this method on exit. + ResourceMark rm(split_arena); + uint bidx, pidx, slidx, insidx, inpidx, twoidx; uint non_phi = 1, spill_cnt = 0; Node **Reachblock; @@ -461,14 +464,17 @@ bool u1, u2, u3; Block *b, *pred; PhiNode *phi; - GrowableArray<uint> lidxs; + GrowableArray<uint> lidxs(split_arena, _maxlrg, 0, 0); // Array of counters to count splits per live range - GrowableArray<uint> splits; + GrowableArray<uint> splits(split_arena, _maxlrg, 0, 0); + +#define NEW_SPLIT_ARRAY(type, size)\ + (type*) split_arena->allocate_bytes((size) * sizeof(type)) //----------Setup Code---------- // Create a convenient mapping from lrg numbers to reaches/leaves indices - uint *lrg2reach = NEW_RESOURCE_ARRAY( uint, _maxlrg ); + uint *lrg2reach = NEW_SPLIT_ARRAY( uint, _maxlrg ); // Keep track of DEFS & Phis for later passes defs = new Node_List(); phis = new Node_List(); @@ -500,15 +506,15 @@ // a Def is UP or DOWN. UP means that it should get a register (ie - // it is always in LRP regions), and DOWN means that it is probably // on the stack (ie - it crosses HRP regions). - Node ***Reaches = NEW_RESOURCE_ARRAY( Node**, _cfg._num_blocks+1 ); - bool **UP = NEW_RESOURCE_ARRAY( bool*, _cfg._num_blocks+1 ); - Node **debug_defs = NEW_RESOURCE_ARRAY( Node*, spill_cnt ); - VectorSet **UP_entry= NEW_RESOURCE_ARRAY( VectorSet*, spill_cnt ); + Node ***Reaches = NEW_SPLIT_ARRAY( Node**, _cfg._num_blocks+1 ); + bool **UP = NEW_SPLIT_ARRAY( bool*, _cfg._num_blocks+1 ); + Node **debug_defs = NEW_SPLIT_ARRAY( Node*, spill_cnt ); + VectorSet **UP_entry= NEW_SPLIT_ARRAY( VectorSet*, spill_cnt ); // Initialize Reaches & UP for( bidx = 0; bidx < _cfg._num_blocks+1; bidx++ ) { - Reaches[bidx] = NEW_RESOURCE_ARRAY( Node*, spill_cnt ); - UP[bidx] = NEW_RESOURCE_ARRAY( bool, spill_cnt ); + Reaches[bidx] = NEW_SPLIT_ARRAY( Node*, spill_cnt ); + UP[bidx] = NEW_SPLIT_ARRAY( bool, spill_cnt ); Node **Reachblock = Reaches[bidx]; bool *UPblock = UP[bidx]; for( slidx = 0; slidx < spill_cnt; slidx++ ) { @@ -517,9 +523,11 @@ } } +#undef NEW_SPLIT_ARRAY + // Initialize to array of empty vectorsets for( slidx = 0; slidx < spill_cnt; slidx++ ) - UP_entry[slidx] = new VectorSet(Thread::current()->resource_area()); + UP_entry[slidx] = new VectorSet(split_arena); //----------PASS 1---------- //----------Propagation & Node Insertion Code----------
--- a/src/share/vm/opto/runtime.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/runtime.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -880,46 +880,6 @@ } JRT_END -//----------------------------------------------------------------------------- -// implicit exception support. - -static void report_null_exception_in_code_cache(address exception_pc) { - ResourceMark rm; - CodeBlob* n = CodeCache::find_blob(exception_pc); - if (n != NULL) { - tty->print_cr("#"); - tty->print_cr("# HotSpot Runtime Error, null exception in generated code"); - tty->print_cr("#"); - tty->print_cr("# pc where exception happened = " INTPTR_FORMAT, exception_pc); - - if (n->is_nmethod()) { - methodOop method = ((nmethod*)n)->method(); - tty->print_cr("# Method where it happened %s.%s ", Klass::cast(method->method_holder())->name()->as_C_string(), method->name()->as_C_string()); - tty->print_cr("#"); - if (ShowMessageBoxOnError && UpdateHotSpotCompilerFileOnError && - CompilerOracle::has_command_file()) { - const char* title = "HotSpot Runtime Error"; - const char* question = "Do you want to exclude compilation of this method in future runs?"; - if (os::message_box(title, question)) { - CompilerOracle::append_comment_to_file(""); - CompilerOracle::append_comment_to_file("Null exception in compiled code resulted in the following exclude"); - CompilerOracle::append_comment_to_file(""); - CompilerOracle::append_exclude_to_file(method); - tty->print_cr("#"); - tty->print_cr("# %s has been updated to exclude the specified method", CompileCommandFile); - tty->print_cr("#"); - } - } - fatal("Implicit null exception happened in compiled method"); - } else { - n->print(); - fatal("Implicit null exception happened in generated stub"); - } - } - fatal("Implicit null exception at wrong place"); -} - - //------------------------------------------------------------------------------------- // register policy
--- a/src/share/vm/opto/superword.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/superword.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -1058,12 +1058,27 @@ return VectorNode::implemented(p0->Opcode(), p->size(), velt_basic_type(p0)); } +//------------------------------same_inputs-------------------------- +// For pack p, are all idx operands the same? +static bool same_inputs(Node_List* p, int idx) { + Node* p0 = p->at(0); + uint vlen = p->size(); + Node* p0_def = p0->in(idx); + for (uint i = 1; i < vlen; i++) { + Node* pi = p->at(i); + Node* pi_def = pi->in(idx); + if (p0_def != pi_def) + return false; + } + return true; +} + //------------------------------profitable--------------------------- // For pack p, are all operands and all uses (with in the block) vector? bool SuperWord::profitable(Node_List* p) { Node* p0 = p->at(0); uint start, end; - vector_opd_range(p0, &start, &end); + VectorNode::vector_operands(p0, &start, &end); // Return false if some input is not vector and inside block for (uint i = start; i < end; i++) { @@ -1071,15 +1086,20 @@ // For now, return false if not scalar promotion case (inputs are the same.) // Later, implement PackNode and allow differing, non-vector inputs // (maybe just the ones from outside the block.) - Node* p0_def = p0->in(i); - for (uint j = 1; j < p->size(); j++) { - Node* use = p->at(j); - Node* def = use->in(i); - if (p0_def != def) - return false; + if (!same_inputs(p, i)) { + return false; } } } + if (VectorNode::is_shift(p0)) { + // For now, return false if shift count is vector because + // hw does not support it. + if (is_vector_use(p0, 2)) + return false; + // For the same reason return false if different shift counts. + if (!same_inputs(p, 2)) + return false; + } if (!p0->is_Store()) { // For now, return false if not all uses are vector. // Later, implement ExtractNode and allow non-vector uses (maybe @@ -1357,6 +1377,12 @@ // Promote operands to vector Node* in1 = vector_opd(p, 1); Node* in2 = vector_opd(p, 2); + if (VectorNode::is_invariant_vector(in1) && (n->is_Add() || n->is_Mul())) { + // Move invariant vector input into second position to avoid register spilling. + Node* tmp = in1; + in1 = in2; + in2 = tmp; + } vn = VectorNode::make(_phase->C, opc, in1, in2, vlen, velt_basic_type(n)); } else { ShouldNotReachHere(); @@ -1386,19 +1412,40 @@ uint vlen = p->size(); Node* opd = p0->in(opd_idx); - bool same_opd = true; - for (uint i = 1; i < vlen; i++) { - Node* pi = p->at(i); - Node* in = pi->in(opd_idx); - if (opd != in) { - same_opd = false; - break; + if (same_inputs(p, opd_idx)) { + if (opd->is_Vector() || opd->is_LoadVector()) { + assert(((opd_idx != 2) || !VectorNode::is_shift(p0)), "shift's count can't be vector"); + return opd; // input is matching vector } - } - - if (same_opd) { - if (opd->is_Vector() || opd->is_LoadVector()) { - return opd; // input is matching vector + if ((opd_idx == 2) && VectorNode::is_shift(p0)) { + // No vector is needed for shift count. + // Vector instructions do not mask shift count, do it here. + Compile* C = _phase->C; + Node* cnt = opd; + juint mask = (p0->bottom_type() == TypeInt::INT) ? (BitsPerInt - 1) : (BitsPerLong - 1); + const TypeInt* t = opd->find_int_type(); + if (t != NULL && t->is_con()) { + juint shift = t->get_con(); + if (shift > mask) { // Unsigned cmp + cnt = ConNode::make(C, TypeInt::make(shift & mask)); + } + } else { + if (t == NULL || t->_lo < 0 || t->_hi > (int)mask) { + cnt = ConNode::make(C, TypeInt::make(mask)); + _phase->_igvn.register_new_node_with_optimizer(cnt); + cnt = new (C, 3) AndINode(opd, cnt); + _phase->_igvn.register_new_node_with_optimizer(cnt); + _phase->set_ctrl(cnt, _phase->get_ctrl(opd)); + } + assert(opd->bottom_type()->isa_int(), "int type only"); + // Move non constant shift count into XMM register. + cnt = new (_phase->C, 2) MoveI2FNode(cnt); + } + if (cnt != opd) { + _phase->_igvn.register_new_node_with_optimizer(cnt); + _phase->set_ctrl(cnt, _phase->get_ctrl(opd)); + } + return cnt; } assert(!opd->is_StoreVector(), "such vector is not expected here"); // Convert scalar input to vector with the same number of elements as @@ -1428,7 +1475,7 @@ Node* in = pi->in(opd_idx); assert(my_pack(in) == NULL, "Should already have been unpacked"); assert(opd_bt == in->bottom_type()->basic_type(), "all same type"); - pk->add_opd(i, in); + pk->add_opd(in); } _phase->_igvn.register_new_node_with_optimizer(pk); _phase->set_ctrl(pk, _phase->get_ctrl(opd)); @@ -1718,37 +1765,27 @@ for (int i = _block.length() - 1; i >= 0; i--) { Node* n = _block.at(i); // Only integer types need be examined - if (n->bottom_type()->isa_int()) { + const Type* vt = velt_type(n); + if (vt->basic_type() == T_INT) { uint start, end; - vector_opd_range(n, &start, &end); + VectorNode::vector_operands(n, &start, &end); const Type* vt = velt_type(n); for (uint j = start; j < end; j++) { Node* in = n->in(j); - // Don't propagate through a type conversion - if (n->bottom_type() != in->bottom_type()) - continue; - switch(in->Opcode()) { - case Op_AddI: case Op_AddL: - case Op_SubI: case Op_SubL: - case Op_MulI: case Op_MulL: - case Op_AndI: case Op_AndL: - case Op_OrI: case Op_OrL: - case Op_XorI: case Op_XorL: - case Op_LShiftI: case Op_LShiftL: - case Op_CMoveI: case Op_CMoveL: - if (in_bb(in)) { - bool same_type = true; - for (DUIterator_Fast kmax, k = in->fast_outs(kmax); k < kmax; k++) { - Node *use = in->fast_out(k); - if (!in_bb(use) || !same_velt_type(use, n)) { - same_type = false; - break; - } + // Don't propagate through a memory + if (!in->is_Mem() && in_bb(in) && velt_type(in)->basic_type() == T_INT && + data_size(n) < data_size(in)) { + bool same_type = true; + for (DUIterator_Fast kmax, k = in->fast_outs(kmax); k < kmax; k++) { + Node *use = in->fast_out(k); + if (!in_bb(use) || !same_velt_type(use, n)) { + same_type = false; + break; } - if (same_type) { - set_velt_type(in, vt); - } + } + if (same_type) { + set_velt_type(in, vt); } } } @@ -1792,10 +1829,8 @@ } const Type* t = _igvn.type(n); if (t->basic_type() == T_INT) { - if (t->higher_equal(TypeInt::BOOL)) return TypeInt::BOOL; - if (t->higher_equal(TypeInt::BYTE)) return TypeInt::BYTE; - if (t->higher_equal(TypeInt::CHAR)) return TypeInt::CHAR; - if (t->higher_equal(TypeInt::SHORT)) return TypeInt::SHORT; + // A narrow type of arithmetic operations will be determined by + // propagating the type of memory operations. return TypeInt::INT; } return t; @@ -1811,38 +1846,6 @@ return vt1 == vt2; } -//-------------------------vector_opd_range----------------------- -// (Start, end] half-open range defining which operands are vector -void SuperWord::vector_opd_range(Node* n, uint* start, uint* end) { - switch (n->Opcode()) { - case Op_LoadB: case Op_LoadUB: - case Op_LoadS: case Op_LoadUS: - case Op_LoadI: case Op_LoadL: - case Op_LoadF: case Op_LoadD: - case Op_LoadP: - *start = 0; - *end = 0; - return; - case Op_StoreB: case Op_StoreC: - case Op_StoreI: case Op_StoreL: - case Op_StoreF: case Op_StoreD: - case Op_StoreP: - *start = MemNode::ValueIn; - *end = *start + 1; - return; - case Op_LShiftI: case Op_LShiftL: - *start = 1; - *end = 2; - return; - case Op_CMoveI: case Op_CMoveL: case Op_CMoveF: case Op_CMoveD: - *start = 2; - *end = n->req(); - return; - } - *start = 1; - *end = n->req(); // default is all operands -} - //------------------------------in_packset--------------------------- // Are s1 and s2 in a pack pair and ordered as s1,s2? bool SuperWord::in_packset(Node* s1, Node* s2) { @@ -1940,7 +1943,7 @@ // lim0 == original pre loop limit // V == v_align (power of 2) // invar == extra invariant piece of the address expression - // e == k [ +/- invar ] + // e == offset [ +/- invar ] // // When reassociating expressions involving '%' the basic rules are: // (a - b) % k == 0 => a % k == b % k @@ -1993,13 +1996,12 @@ int elt_size = align_to_ref_p.memory_size(); int v_align = vw / elt_size; assert(v_align > 1, "sanity"); - int k = align_to_ref_p.offset_in_bytes() / elt_size; - - Node *kn = _igvn.intcon(k); + int offset = align_to_ref_p.offset_in_bytes() / elt_size; + Node *offsn = _igvn.intcon(offset); - Node *e = kn; + Node *e = offsn; if (align_to_ref_p.invar() != NULL) { - // incorporate any extra invariant piece producing k +/- invar >>> log2(elt) + // incorporate any extra invariant piece producing (offset +/- invar) >>> log2(elt) Node* log2_elt = _igvn.intcon(exact_log2(elt_size)); Node* aref = new (_phase->C, 3) URShiftINode(align_to_ref_p.invar(), log2_elt); _phase->_igvn.register_new_node_with_optimizer(aref); @@ -2014,15 +2016,15 @@ } if (vw > ObjectAlignmentInBytes) { // incorporate base e +/- base && Mask >>> log2(elt) - Node* mask = _igvn.MakeConX(~(-1 << exact_log2(vw))); Node* xbase = new(_phase->C, 2) CastP2XNode(NULL, align_to_ref_p.base()); _phase->_igvn.register_new_node_with_optimizer(xbase); - Node* masked_xbase = new (_phase->C, 3) AndXNode(xbase, mask); +#ifdef _LP64 + xbase = new (_phase->C, 2) ConvL2INode(xbase); + _phase->_igvn.register_new_node_with_optimizer(xbase); +#endif + Node* mask = _igvn.intcon(vw-1); + Node* masked_xbase = new (_phase->C, 3) AndINode(xbase, mask); _phase->_igvn.register_new_node_with_optimizer(masked_xbase); -#ifdef _LP64 - masked_xbase = new (_phase->C, 2) ConvL2INode(masked_xbase); - _phase->_igvn.register_new_node_with_optimizer(masked_xbase); -#endif Node* log2_elt = _igvn.intcon(exact_log2(elt_size)); Node* bref = new (_phase->C, 3) URShiftINode(masked_xbase, log2_elt); _phase->_igvn.register_new_node_with_optimizer(bref);
--- a/src/share/vm/opto/vectornode.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/vectornode.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -31,7 +31,7 @@ // Return the vector operator for the specified scalar operation // and vector length. Also used to check if the code generator // supports the vector operation. -int VectorNode::opcode(int sopc, uint vlen, BasicType bt) { +int VectorNode::opcode(int sopc, BasicType bt) { switch (sopc) { case Op_AddI: switch (bt) { @@ -69,6 +69,15 @@ case Op_SubD: assert(bt == T_DOUBLE, "must be"); return Op_SubVD; + case Op_MulI: + switch (bt) { + case T_BOOLEAN: + case T_BYTE: return 0; // Unimplemented + case T_CHAR: + case T_SHORT: return Op_MulVS; + case T_INT: return Matcher::match_rule_supported(Op_MulVI) ? Op_MulVI : 0; // SSE4_1 + } + ShouldNotReachHere(); case Op_MulF: assert(bt == T_FLOAT, "must be"); return Op_MulVF; @@ -90,6 +99,9 @@ case T_INT: return Op_LShiftVI; } ShouldNotReachHere(); + case Op_LShiftL: + assert(bt == T_LONG, "must be"); + return Op_LShiftVL; case Op_RShiftI: switch (bt) { case T_BOOLEAN: @@ -99,6 +111,21 @@ case T_INT: return Op_RShiftVI; } ShouldNotReachHere(); + case Op_RShiftL: + assert(bt == T_LONG, "must be"); + return Op_RShiftVL; + case Op_URShiftI: + switch (bt) { + case T_BOOLEAN: + case T_BYTE: return Op_URShiftVB; + case T_CHAR: + case T_SHORT: return Op_URShiftVS; + case T_INT: return Op_URShiftVI; + } + ShouldNotReachHere(); + case Op_URShiftL: + assert(bt == T_LONG, "must be"); + return Op_URShiftVL; case Op_AndI: case Op_AndL: return Op_AndV; @@ -134,16 +161,88 @@ if (is_java_primitive(bt) && (vlen > 1) && is_power_of_2(vlen) && Matcher::vector_size_supported(bt, vlen)) { - int vopc = VectorNode::opcode(opc, vlen, bt); + int vopc = VectorNode::opcode(opc, bt); return vopc > 0 && Matcher::has_match_rule(vopc); } return false; } +bool VectorNode::is_shift(Node* n) { + switch (n->Opcode()) { + case Op_LShiftI: + case Op_LShiftL: + case Op_RShiftI: + case Op_RShiftL: + case Op_URShiftI: + case Op_URShiftL: + return true; + } + return false; +} + +// Check if input is loop invariant vector. +bool VectorNode::is_invariant_vector(Node* n) { + // Only Replicate vector nodes are loop invariant for now. + switch (n->Opcode()) { + case Op_ReplicateB: + case Op_ReplicateS: + case Op_ReplicateI: + case Op_ReplicateL: + case Op_ReplicateF: + case Op_ReplicateD: + return true; + } + return false; +} + +// [Start, end) half-open range defining which operands are vectors +void VectorNode::vector_operands(Node* n, uint* start, uint* end) { + switch (n->Opcode()) { + case Op_LoadB: case Op_LoadUB: + case Op_LoadS: case Op_LoadUS: + case Op_LoadI: case Op_LoadL: + case Op_LoadF: case Op_LoadD: + case Op_LoadP: case Op_LoadN: + *start = 0; + *end = 0; // no vector operands + break; + case Op_StoreB: case Op_StoreC: + case Op_StoreI: case Op_StoreL: + case Op_StoreF: case Op_StoreD: + case Op_StoreP: case Op_StoreN: + *start = MemNode::ValueIn; + *end = MemNode::ValueIn + 1; // 1 vector operand + break; + case Op_LShiftI: case Op_LShiftL: + case Op_RShiftI: case Op_RShiftL: + case Op_URShiftI: case Op_URShiftL: + *start = 1; + *end = 2; // 1 vector operand + break; + case Op_AddI: case Op_AddL: case Op_AddF: case Op_AddD: + case Op_SubI: case Op_SubL: case Op_SubF: case Op_SubD: + case Op_MulI: case Op_MulL: case Op_MulF: case Op_MulD: + case Op_DivF: case Op_DivD: + case Op_AndI: case Op_AndL: + case Op_OrI: case Op_OrL: + case Op_XorI: case Op_XorL: + *start = 1; + *end = 3; // 2 vector operands + break; + case Op_CMoveI: case Op_CMoveL: case Op_CMoveF: case Op_CMoveD: + *start = 2; + *end = n->req(); + break; + default: + *start = 1; + *end = n->req(); // default is all operands + } +} + // Return the vector version of a scalar operation node. VectorNode* VectorNode::make(Compile* C, int opc, Node* n1, Node* n2, uint vlen, BasicType bt) { const TypeVect* vt = TypeVect::make(bt, vlen); - int vopc = VectorNode::opcode(opc, vlen, bt); + int vopc = VectorNode::opcode(opc, bt); switch (vopc) { case Op_AddVB: return new (C, 3) AddVBNode(n1, n2, vt); @@ -160,6 +259,8 @@ case Op_SubVF: return new (C, 3) SubVFNode(n1, n2, vt); case Op_SubVD: return new (C, 3) SubVDNode(n1, n2, vt); + case Op_MulVS: return new (C, 3) MulVSNode(n1, n2, vt); + case Op_MulVI: return new (C, 3) MulVINode(n1, n2, vt); case Op_MulVF: return new (C, 3) MulVFNode(n1, n2, vt); case Op_MulVD: return new (C, 3) MulVDNode(n1, n2, vt); @@ -169,10 +270,17 @@ case Op_LShiftVB: return new (C, 3) LShiftVBNode(n1, n2, vt); case Op_LShiftVS: return new (C, 3) LShiftVSNode(n1, n2, vt); case Op_LShiftVI: return new (C, 3) LShiftVINode(n1, n2, vt); + case Op_LShiftVL: return new (C, 3) LShiftVLNode(n1, n2, vt); case Op_RShiftVB: return new (C, 3) RShiftVBNode(n1, n2, vt); case Op_RShiftVS: return new (C, 3) RShiftVSNode(n1, n2, vt); case Op_RShiftVI: return new (C, 3) RShiftVINode(n1, n2, vt); + case Op_RShiftVL: return new (C, 3) RShiftVLNode(n1, n2, vt); + + case Op_URShiftVB: return new (C, 3) URShiftVBNode(n1, n2, vt); + case Op_URShiftVS: return new (C, 3) URShiftVSNode(n1, n2, vt); + case Op_URShiftVI: return new (C, 3) URShiftVINode(n1, n2, vt); + case Op_URShiftVL: return new (C, 3) URShiftVLNode(n1, n2, vt); case Op_AndV: return new (C, 3) AndVNode(n1, n2, vt); case Op_OrV: return new (C, 3) OrVNode (n1, n2, vt); @@ -214,38 +322,39 @@ switch (bt) { case T_BOOLEAN: case T_BYTE: - return new (C, vlen+1) PackBNode(s, vt); + return new (C, 2) PackBNode(s, vt); case T_CHAR: case T_SHORT: - return new (C, vlen+1) PackSNode(s, vt); + return new (C, 2) PackSNode(s, vt); case T_INT: - return new (C, vlen+1) PackINode(s, vt); + return new (C, 2) PackINode(s, vt); case T_LONG: - return new (C, vlen+1) PackLNode(s, vt); + return new (C, 2) PackLNode(s, vt); case T_FLOAT: - return new (C, vlen+1) PackFNode(s, vt); + return new (C, 2) PackFNode(s, vt); case T_DOUBLE: - return new (C, vlen+1) PackDNode(s, vt); + return new (C, 2) PackDNode(s, vt); } ShouldNotReachHere(); return NULL; } // Create a binary tree form for Packs. [lo, hi) (half-open) range -Node* PackNode::binaryTreePack(Compile* C, int lo, int hi) { +PackNode* PackNode::binary_tree_pack(Compile* C, int lo, int hi) { int ct = hi - lo; assert(is_power_of_2(ct), "power of 2"); if (ct == 2) { PackNode* pk = PackNode::make(C, in(lo), 2, vect_type()->element_basic_type()); - pk->add_opd(1, in(lo+1)); + pk->add_opd(in(lo+1)); return pk; } else { int mid = lo + ct/2; - Node* n1 = binaryTreePack(C, lo, mid); - Node* n2 = binaryTreePack(C, mid, hi ); + PackNode* n1 = binary_tree_pack(C, lo, mid); + PackNode* n2 = binary_tree_pack(C, mid, hi ); - BasicType bt = vect_type()->element_basic_type(); + BasicType bt = n1->vect_type()->element_basic_type(); + assert(bt == n2->vect_type()->element_basic_type(), "should be the same"); switch (bt) { case T_BOOLEAN: case T_BYTE:
--- a/src/share/vm/opto/vectornode.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/opto/vectornode.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -46,6 +46,7 @@ const TypeVect* vect_type() const { return type()->is_vect(); } uint length() const { return vect_type()->length(); } // Vector length + uint length_in_bytes() const { return vect_type()->length_in_bytes(); } virtual int Opcode() const; @@ -55,9 +56,12 @@ static VectorNode* make(Compile* C, int opc, Node* n1, Node* n2, uint vlen, BasicType bt); - static int opcode(int opc, uint vlen, BasicType bt); + static int opcode(int opc, BasicType bt); static bool implemented(int opc, uint vlen, BasicType bt); - + static bool is_shift(Node* n); + static bool is_invariant_vector(Node* n); + // [Start, end) half-open range defining which operands are vectors + static void vector_operands(Node* n, uint* start, uint* end); }; //===========================Vector=ALU=Operations==================================== @@ -158,6 +162,22 @@ virtual int Opcode() const; }; +//------------------------------MulVSNode--------------------------------------- +// Vector multiply short +class MulVSNode : public VectorNode { + public: + MulVSNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} + virtual int Opcode() const; +}; + +//------------------------------MulVINode--------------------------------------- +// Vector multiply int +class MulVINode : public VectorNode { + public: + MulVINode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} + virtual int Opcode() const; +}; + //------------------------------MulVFNode--------------------------------------- // Vector multiply float class MulVFNode : public VectorNode { @@ -191,7 +211,7 @@ }; //------------------------------LShiftVBNode--------------------------------------- -// Vector lshift byte +// Vector left shift bytes class LShiftVBNode : public VectorNode { public: LShiftVBNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} @@ -199,7 +219,7 @@ }; //------------------------------LShiftVSNode--------------------------------------- -// Vector lshift shorts +// Vector left shift shorts class LShiftVSNode : public VectorNode { public: LShiftVSNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} @@ -207,39 +227,88 @@ }; //------------------------------LShiftVINode--------------------------------------- -// Vector lshift ints +// Vector left shift ints class LShiftVINode : public VectorNode { public: LShiftVINode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; }; -//------------------------------URShiftVBNode--------------------------------------- -// Vector urshift bytes +//------------------------------LShiftVLNode--------------------------------------- +// Vector left shift longs +class LShiftVLNode : public VectorNode { + public: + LShiftVLNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} + virtual int Opcode() const; +}; + +//------------------------------RShiftVBNode--------------------------------------- +// Vector right arithmetic (signed) shift bytes class RShiftVBNode : public VectorNode { public: RShiftVBNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; }; -//------------------------------URShiftVSNode--------------------------------------- -// Vector urshift shorts +//------------------------------RShiftVSNode--------------------------------------- +// Vector right arithmetic (signed) shift shorts class RShiftVSNode : public VectorNode { public: RShiftVSNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; }; -//------------------------------URShiftVINode--------------------------------------- -// Vector urshift ints +//------------------------------RShiftVINode--------------------------------------- +// Vector right arithmetic (signed) shift ints class RShiftVINode : public VectorNode { public: RShiftVINode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} virtual int Opcode() const; }; +//------------------------------RShiftVLNode--------------------------------------- +// Vector right arithmetic (signed) shift longs +class RShiftVLNode : public VectorNode { + public: + RShiftVLNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} + virtual int Opcode() const; +}; + +//------------------------------URShiftVBNode--------------------------------------- +// Vector right logical (unsigned) shift bytes +class URShiftVBNode : public VectorNode { + public: + URShiftVBNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} + virtual int Opcode() const; +}; + +//------------------------------URShiftVSNode--------------------------------------- +// Vector right logical (unsigned) shift shorts +class URShiftVSNode : public VectorNode { + public: + URShiftVSNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} + virtual int Opcode() const; +}; + +//------------------------------URShiftVINode--------------------------------------- +// Vector right logical (unsigned) shift ints +class URShiftVINode : public VectorNode { + public: + URShiftVINode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} + virtual int Opcode() const; +}; + +//------------------------------URShiftVLNode--------------------------------------- +// Vector right logical (unsigned) shift longs +class URShiftVLNode : public VectorNode { + public: + URShiftVLNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} + virtual int Opcode() const; +}; + + //------------------------------AndVNode--------------------------------------- -// Vector and +// Vector and integer class AndVNode : public VectorNode { public: AndVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} @@ -247,7 +316,7 @@ }; //------------------------------OrVNode--------------------------------------- -// Vector or +// Vector or integer class OrVNode : public VectorNode { public: OrVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} @@ -255,7 +324,7 @@ }; //------------------------------XorVNode--------------------------------------- -// Vector xor +// Vector xor integer class XorVNode : public VectorNode { public: XorVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {} @@ -373,12 +442,12 @@ PackNode(Node* in1, Node* n2, const TypeVect* vt) : VectorNode(in1, n2, vt) {} virtual int Opcode() const; - void add_opd(uint i, Node* n) { - init_req(i+1, n); + void add_opd(Node* n) { + add_req(n); } // Create a binary tree form for Packs. [lo, hi) (half-open) range - Node* binaryTreePack(Compile* C, int lo, int hi); + PackNode* binary_tree_pack(Compile* C, int lo, int hi); static PackNode* make(Compile* C, Node* s, uint vlen, BasicType bt); };
--- a/src/share/vm/precompiled/precompiled.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/precompiled/precompiled.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -306,7 +306,6 @@ # include "gc_implementation/g1/g1_specialized_oop_closures.hpp" # include "gc_implementation/g1/ptrQueue.hpp" # include "gc_implementation/g1/satbQueue.hpp" -# include "gc_implementation/parNew/parGCAllocBuffer.hpp" # include "gc_implementation/parNew/parOopClosures.hpp" # include "gc_implementation/parallelScavenge/objectStartArray.hpp" # include "gc_implementation/parallelScavenge/parMarkBitMap.hpp" @@ -322,6 +321,7 @@ # include "gc_implementation/parallelScavenge/psYoungGen.hpp" # include "gc_implementation/shared/gcAdaptivePolicyCounters.hpp" # include "gc_implementation/shared/gcPolicyCounters.hpp" +# include "gc_implementation/shared/parGCAllocBuffer.hpp" #endif // SERIALGC #endif // !DONT_USE_PRECOMPILED_HEADER
--- a/src/share/vm/runtime/arguments.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/runtime/arguments.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -1934,7 +1934,7 @@ (ExplicitGCInvokesConcurrent || ExplicitGCInvokesConcurrentAndUnloadsClasses)) { jio_fprintf(defaultStream::error_stream(), - "error: +ExplictGCInvokesConcurrent[AndUnloadsClasses] conflicts" + "error: +ExplicitGCInvokesConcurrent[AndUnloadsClasses] conflicts" " with -UseAsyncConcMarkSweepGC"); status = false; } @@ -2148,6 +2148,7 @@ // modify its entries, not its name or shape const char* graal_projects[] = { #ifdef AMD64 + "com.oracle.graal.amd64", "com.oracle.graal.asm.amd64", "com.oracle.graal.lir.amd64", "com.oracle.graal.compiler.amd64",
--- a/src/share/vm/runtime/compilationPolicy.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/runtime/compilationPolicy.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -208,7 +208,7 @@ } void NonTieredCompPolicy::reset_counter_for_back_branch_event(methodHandle m) { - GRAAL_ONLY(assert(false, "unexpected")); +// GRAAL_ONLY(assert(false, "unexpected")); // Delay next back-branch event but pump up invocation counter to triger // whole method compilation. InvocationCounter* i = m->invocation_counter();
--- a/src/share/vm/runtime/globals.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/runtime/globals.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -43,7 +43,6 @@ #include "shark/shark_globals.hpp" #endif - RUNTIME_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \ MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, \ MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_EXPERIMENTAL_FLAG, \ @@ -55,6 +54,10 @@ MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, \ MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG) +ARCH_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, \ + MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_EXPERIMENTAL_FLAG, \ + MATERIALIZE_NOTPRODUCT_FLAG) + MATERIALIZE_FLAGS_EXT @@ -212,7 +215,6 @@ #define C1_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, doc, "{C1 notproduct}", DEFAULT }, #endif - #define C2_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{C2 product}", DEFAULT }, #define C2_PD_PRODUCT_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{C2 pd product}", DEFAULT }, #define C2_DIAGNOSTIC_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{C2 diagnostic}", DEFAULT }, @@ -227,6 +229,17 @@ #define C2_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, doc, "{C2 notproduct}", DEFAULT }, #endif +#define ARCH_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{ARCH product}", DEFAULT }, +#define ARCH_DIAGNOSTIC_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{ARCH diagnostic}", DEFAULT }, +#define ARCH_EXPERIMENTAL_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{ARCH experimental}", DEFAULT }, +#ifdef PRODUCT + #define ARCH_DEVELOP_FLAG_STRUCT(type, name, value, doc) /* flag is constant */ + #define ARCH_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) +#else + #define ARCH_DEVELOP_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, doc, "{ARCH}", DEFAULT }, + #define ARCH_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, doc, "{ARCH notproduct}", DEFAULT }, +#endif + #define SHARK_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{Shark product}", DEFAULT }, #define SHARK_PD_PRODUCT_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{Shark pd product}", DEFAULT }, #define SHARK_DIAGNOSTIC_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{Shark diagnostic}", DEFAULT }, @@ -255,6 +268,7 @@ #ifdef SHARK SHARK_FLAGS(SHARK_DEVELOP_FLAG_STRUCT, SHARK_PD_DEVELOP_FLAG_STRUCT, SHARK_PRODUCT_FLAG_STRUCT, SHARK_PD_PRODUCT_FLAG_STRUCT, SHARK_DIAGNOSTIC_FLAG_STRUCT, SHARK_NOTPRODUCT_FLAG_STRUCT) #endif + ARCH_FLAGS(ARCH_DEVELOP_FLAG_STRUCT, ARCH_PRODUCT_FLAG_STRUCT, ARCH_DIAGNOSTIC_FLAG_STRUCT, ARCH_EXPERIMENTAL_FLAG_STRUCT, ARCH_NOTPRODUCT_FLAG_STRUCT) FLAGTABLE_EXT {0, NULL, NULL} };
--- a/src/share/vm/runtime/globals.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/runtime/globals.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -530,12 +530,6 @@ product(intx, UseSSE, 99, \ "Highest supported SSE instructions set on x86/x64") \ \ - product(intx, UseAVX, 99, \ - "Highest supported AVX instructions set on x86/x64") \ - \ - product(intx, UseVIS, 99, \ - "Highest supported VIS instructions set on Sparc") \ - \ product(uintx, LargePageSizeInBytes, 0, \ "Large page size (0 to let VM choose the page size") \ \ @@ -572,10 +566,6 @@ product(bool, PrintVMQWaitTime, false, \ "Prints out the waiting time in VM operation queue") \ \ - develop(bool, BailoutToInterpreterForThrows, false, \ - "Compiled methods which throws/catches exceptions will be " \ - "deopt and intp.") \ - \ develop(bool, NoYieldsInMicrolock, false, \ "Disable yields in microlock") \ \ @@ -618,9 +608,6 @@ "inline Object::hashCode() native that is known to be part " \ "of base library DLL") \ \ - develop(bool, InlineObjectCopy, true, \ - "inline Object.clone and Arrays.copyOf[Range] intrinsics") \ - \ develop(bool, InlineNatives, true, \ "inline natives that are known to be part of base library DLL") \ \ @@ -642,31 +629,9 @@ develop(bool, InlineThreadNatives, true, \ "inline Thread.currentThread, etc") \ \ - develop(bool, InlineReflectionGetCallerClass, true, \ - "inline sun.reflect.Reflection.getCallerClass(), known to be part "\ - "of base library DLL") \ - \ develop(bool, InlineUnsafeOps, true, \ "inline memory ops (native methods) from sun.misc.Unsafe") \ \ - develop(bool, ConvertCmpD2CmpF, true, \ - "Convert cmpD to cmpF when one input is constant in float range") \ - \ - develop(bool, ConvertFloat2IntClipping, true, \ - "Convert float2int clipping idiom to integer clipping") \ - \ - develop(bool, SpecialStringCompareTo, true, \ - "special version of string compareTo") \ - \ - develop(bool, SpecialStringIndexOf, true, \ - "special version of string indexOf") \ - \ - develop(bool, SpecialStringEquals, true, \ - "special version of string equals") \ - \ - develop(bool, SpecialArraysEquals, true, \ - "special version of Arrays.equals(char[],char[])") \ - \ product(bool, CriticalJNINatives, true, \ "check for critical JNI entry points") \ \ @@ -676,9 +641,6 @@ product(bool, UseSSE42Intrinsics, false, \ "SSE4.2 versions of intrinsics") \ \ - product(bool, UseCondCardMark, false, \ - "Check for already marked card before updating card table") \ - \ develop(bool, TraceCallFixup, false, \ "traces all call fixups") \ \ @@ -765,9 +727,6 @@ develop(bool, ForceFloatExceptions, trueInDebug, \ "Force exceptions on FP stack under/overflow") \ \ - develop(bool, SoftMatchFailure, trueInProduct, \ - "If the DFA fails to match a node, print a message and bail out") \ - \ develop(bool, VerifyStackAtCalls, false, \ "Verify that the stack pointer is unchanged after calls") \ \ @@ -838,6 +797,9 @@ product(bool, PrintGCApplicationStoppedTime, false, \ "Print the time the application has been stopped") \ \ + diagnostic(bool, VerboseVerification, false, \ + "Display detailed verification details") \ + \ notproduct(uintx, ErrorHandlerTest, 0, \ "If > 0, provokes an error after VM initialization; the value" \ "determines which error to provoke. See test_error_handler()" \ @@ -921,15 +883,6 @@ "1: allow scavenging from the code cache; " \ "2: emit as many constants as the compiler can see") \ \ - diagnostic(bool, TraceOSRBreakpoint, false, \ - "Trace OSR Breakpoint ") \ - \ - diagnostic(bool, TraceCompileTriggered, false, \ - "Trace compile triggered") \ - \ - diagnostic(bool, TraceTriggers, false, \ - "Trace triggers") \ - \ product(bool, AlwaysRestoreFPU, false, \ "Restore the FPU control word after every JNI call (expensive)") \ \ @@ -1046,9 +999,6 @@ develop(bool, UsePrivilegedStack, true, \ "Enable the security JVM functions") \ \ - develop(bool, IEEEPrecision, true, \ - "Enables IEEE precision (for INTEL only)") \ - \ develop(bool, ProtectionDomainVerification, true, \ "Verifies protection domain before resolution in system " \ "dictionary") \ @@ -1118,8 +1068,6 @@ "(Unsafe,Unstable) " \ " Controls emission of inline sync fast-path code") \ \ - product(intx, AlwaysInflate, 0, "(Unstable) Force inflation") \ - \ product(intx, MonitorBound, 0, "Bound Monitor population") \ \ product(bool, MonitorInUseLists, false, "Track Monitors for Deflation") \ @@ -1127,9 +1075,6 @@ product(intx, Atomics, 0, \ "(Unsafe,Unstable) Diagnostic - Controls emission of atomics") \ \ - product(intx, FenceInstruction, 0, \ - "(Unsafe,Unstable) Experimental") \ - \ product(intx, SyncFlags, 0, "(Unsafe,Unstable) Experimental Sync flags" ) \ \ product(intx, SyncVerbose, 0, "(Unstable)" ) \ @@ -1159,10 +1104,6 @@ "call thr_setconcurrency at thread create time to avoid " \ "LWP starvation on MP systems (For Solaris Only)") \ \ - develop(bool, UpdateHotSpotCompilerFileOnError, true, \ - "Should the system attempt to update the compiler file when " \ - "an error occurs?") \ - \ product(bool, ReduceSignalUsage, false, \ "Reduce the use of OS signals in Java and/or the VM") \ \ @@ -1197,15 +1138,6 @@ "Use alternate signals instead of SIGUSR1 & SIGUSR2 for VM " \ "internal signals (Solaris only)") \ \ - product(bool, UseSpinning, false, \ - "Use spinning in monitor inflation and before entry") \ - \ - product(bool, PreSpinYield, false, \ - "Yield before inner spinning loop") \ - \ - product(bool, PostSpinYield, true, \ - "Yield after inner spinning loop") \ - \ product(bool, AllowJNIEnvProxy, false, \ "Allow JNIEnv proxies for jdbx") \ \ @@ -1234,39 +1166,9 @@ product(bool, LazyBootClassLoader, true, \ "Enable/disable lazy opening of boot class path entries") \ \ - diagnostic(bool, UseIncDec, true, \ - "Use INC, DEC instructions on x86") \ - \ - product(bool, UseNewLongLShift, false, \ - "Use optimized bitwise shift left") \ - \ - product(bool, UseStoreImmI16, true, \ - "Use store immediate 16-bits value instruction on x86") \ - \ - product(bool, UseAddressNop, false, \ - "Use '0F 1F [addr]' NOP instructions on x86 cpus") \ - \ - product(bool, UseXmmLoadAndClearUpper, true, \ - "Load low part of XMM register and clear upper part") \ - \ - product(bool, UseXmmRegToRegMoveAll, false, \ - "Copy all XMM register bits when moving value between registers") \ - \ - product(bool, UseXmmI2D, false, \ - "Use SSE2 CVTDQ2PD instruction to convert Integer to Double") \ - \ - product(bool, UseXmmI2F, false, \ - "Use SSE2 CVTDQ2PS instruction to convert Integer to Float") \ - \ product(bool, UseXMMForArrayCopy, false, \ "Use SSE2 MOVQ instruction for Arraycopy") \ \ - product(bool, UseUnalignedLoadStores, false, \ - "Use SSE2 MOVDQU instruction for Arraycopy") \ - \ - product(bool, UseCBCond, false, \ - "Use compare and branch instruction on SPARC") \ - \ product(intx, FieldsAllocationStyle, 1, \ "0 - type based with oops first, 1 - with oops last, " \ "2 - oops in super and sub classes are together") \ @@ -1396,9 +1298,6 @@ develop(bool, TraceStartupTime, false, \ "Trace setup time") \ \ - product(ccstr, HPILibPath, NULL, \ - "Specify alternate path to HPI library") \ - \ develop(bool, TraceProtectionDomainVerification, false, \ "Trace protection domain verifcation") \ \ @@ -1414,10 +1313,6 @@ product(bool, TraceMonitorInflation, false, \ "Trace monitor inflation in JVM") \ \ - /* assembler */ \ - product(bool, Use486InstrsOnly, false, \ - "Use 80486 Compliant instruction subset") \ - \ /* gc */ \ \ product(bool, UseSerialGC, false, \ @@ -1476,9 +1371,6 @@ develop(uintx, ParallelOldGCSplitInterval, 3, \ "How often to provoke splitting a young gen space") \ \ - develop(bool, TraceRegionTasksQueuing, false, \ - "Trace the queuing of the region tasks") \ - \ product(uintx, ConcGCThreads, 0, \ "Number of threads concurrent gc will use") \ \ @@ -1630,10 +1522,6 @@ "The gain in the feedback loop for on-the-fly PLAB resizing" \ " during a scavenge") \ \ - product(uintx, CMSOldPLABReactivityCeiling, 10, \ - "The clamping of the gain in the feedback loop for on-the-fly" \ - " PLAB resizing during a scavenge") \ - \ product(bool, AlwaysPreTouch, false, \ "It forces all freshly committed pages to be pre-touched.") \ \ @@ -1641,12 +1529,6 @@ "The maximum size of young gen chosen by default per GC worker " \ "thread available") \ \ - product(bool, GCOverheadReporting, false, \ - "Enables the GC overhead reporting facility") \ - \ - product(intx, GCOverheadReportingPeriodMS, 100, \ - "Reporting period for conc GC overhead reporting, in ms ") \ - \ product(bool, CMSIncrementalMode, false, \ "Whether CMS GC should operate in \"incremental\" mode") \ \ @@ -2026,9 +1908,6 @@ experimental(uintx, WorkStealingSpinToYieldRatio, 10, \ "Ratio of hard spins to calls to yield") \ \ - product(uintx, PreserveMarkStackSize, 1024, \ - "Size for stack used in promotion failure handling") \ - \ develop(uintx, ObjArrayMarkingStride, 512, \ "Number of ObjArray elements to push onto the marking stack" \ "before pushing a continuation entry") \ @@ -2053,18 +1932,6 @@ product(bool, TLABStats, true, \ "Print various TLAB related information") \ \ - product(bool, UseBlockZeroing, false, \ - "Use special cpu instructions for block zeroing") \ - \ - product(intx, BlockZeroingLowLimit, 2048, \ - "Minimum size in bytes when block zeroing will be used") \ - \ - product(bool, UseBlockCopy, false, \ - "Use special cpu instructions for block copy") \ - \ - product(intx, BlockCopyLowLimit, 2048, \ - "Minimum size in bytes when block copy will be used") \ - \ product(bool, PrintRevisitStats, false, \ "Print revisit (klass and MDO) stack related information") \ \ @@ -2257,9 +2124,6 @@ product(intx, PrefetchFieldsAhead, -1, \ "How many fields ahead to prefetch in oop scan (<= 0 means off)") \ \ - develop(bool, UsePrefetchQueue, true, \ - "Use the prefetch queue during PS promotion") \ - \ diagnostic(bool, VerifyBeforeExit, trueInDebug, \ "Verify system before exiting") \ \ @@ -2495,27 +2359,9 @@ develop(bool, CITraceTypeFlow, false, \ "detailed per-bytecode tracing of ciTypeFlow analysis") \ \ - develop(intx, CICloneLoopTestLimit, 100, \ - "size limit for blocks heuristically cloned in ciTypeFlow") \ - \ develop(intx, OSROnlyBCI, -1, \ "OSR only at this bci. Negative values mean exclude that bci") \ \ - /* temp diagnostics */ \ - \ - diagnostic(bool, TraceRedundantCompiles, false, \ - "Have compile broker print when a request already in the queue is"\ - " requested again") \ - \ - diagnostic(bool, InitialCompileFast, false, \ - "Initial compile at CompLevel_fast_compile") \ - \ - diagnostic(bool, InitialCompileReallyFast, false, \ - "Initial compile at CompLevel_really_fast_compile (no profile)") \ - \ - diagnostic(bool, FullProfileOnReInterpret, true, \ - "On re-interpret unc-trap compile next at CompLevel_fast_compile")\ - \ /* compiler */ \ \ product(intx, CICompilerCount, CI_COMPILER_COUNT, \ @@ -2529,12 +2375,6 @@ "proper StackOverflow handling; disable only to measure cost " \ "of stackbanging)") \ \ - develop(bool, Use24BitFPMode, true, \ - "Set 24-bit FPU mode on a per-compile basis ") \ - \ - develop(bool, Use24BitFP, true, \ - "use FP instructions that produce 24-bit precise results") \ - \ develop(bool, UseStrictFP, true, \ "use strict fp if modifier strictfp is set") \ \ @@ -2566,9 +2406,6 @@ "print the break down of clean up tasks performed during" \ " safepoint") \ \ - develop(bool, InlineAccessors, true, \ - "inline accessor methods (get/set)") \ - \ product(bool, Inline, true, \ "enable inlining") \ \ @@ -2581,33 +2418,15 @@ product(bool, UseTypeProfile, true, \ "Check interpreter profile for historically monomorphic calls") \ \ - product(intx, TypeProfileMajorReceiverPercent, 90, \ - "% of major receiver type to all profiled receivers") \ - \ notproduct(bool, TimeCompiler, false, \ "time the compiler") \ \ - notproduct(bool, TimeCompiler2, false, \ - "detailed time the compiler (requires +TimeCompiler)") \ - \ diagnostic(bool, PrintInlining, false, \ "prints inlining optimizations") \ \ - diagnostic(bool, PrintIntrinsics, false, \ - "prints attempted and successful inlining of intrinsics") \ - \ - product(bool, UseCountLeadingZerosInstruction, false, \ - "Use count leading zeros instruction") \ - \ product(bool, UsePopCountInstruction, false, \ "Use population count instruction") \ \ - diagnostic(ccstrlist, DisableIntrinsic, "", \ - "do not expand intrinsics whose (internal) names appear here") \ - \ - develop(bool, StressReflectiveCode, false, \ - "Use inexact types at allocations, etc., to test reflection") \ - \ develop(bool, EagerInitialization, false, \ "Eagerly initialize classes if possible") \ \ @@ -2617,10 +2436,6 @@ develop(bool, PrintMethodFlushing, false, \ "print the nmethods being flushed") \ \ - notproduct(bool, LogMultipleMutexLocking, false, \ - "log locking and unlocking of mutexes (only if multiple locks " \ - "are held)") \ - \ develop(bool, UseRelocIndex, false, \ "use an index to speed random access to relocations") \ \ @@ -2630,9 +2445,6 @@ diagnostic(bool, DebugNonSafepoints, trueInDebug, \ "Generate extra debugging info for non-safepoints in nmethods") \ \ - diagnostic(bool, DebugInlinedCalls, true, \ - "If false, restricts profiled locations to the root method only") \ - \ product(bool, PrintVMOptions, false, \ "Print flags that appeared on the command line") \ \ @@ -2709,9 +2521,6 @@ notproduct(bool, IgnoreLockingAssertions, false, \ "disable locking assertions (for speed)") \ \ - notproduct(bool, VerifyLoopOptimizations, false, \ - "verify major loop optimizations") \ - \ product(bool, RangeCheckElimination, true, \ "Split loop iterations to eliminate range checks") \ \ @@ -2721,12 +2530,6 @@ develop(bool, TypeProfileCasts, true, \ "treat casts like calls for purposes of type profiling") \ \ - develop(bool, MonomorphicArrayCheck, true, \ - "Uncommon-trap array store checks that require full type check") \ - \ - diagnostic(bool, ProfileDynamicTypes, true, \ - "do extra type profiling and use it more aggressively") \ - \ develop(bool, DelayCompilationDuringStartup, true, \ "Delay invoking the compiler until main application class is " \ "loaded") \ @@ -2741,19 +2544,9 @@ notproduct(intx, CompileTheWorldSafepointInterval, 100, \ "Force a safepoint every n compiles so sweeper can keep up") \ \ - develop(bool, TraceIterativeGVN, false, \ - "Print progress during Iterative Global Value Numbering") \ - \ develop(bool, FillDelaySlots, true, \ "Fill delay slots (on SPARC only)") \ \ - develop(bool, VerifyIterativeGVN, false, \ - "Verify Def-Use modifications during sparse Iterative Global " \ - "Value Numbering") \ - \ - notproduct(bool, TracePhaseCCP, false, \ - "Print progress during Conditional Constant Propagation") \ - \ develop(bool, TimeLivenessAnalysis, false, \ "Time computation of bytecode liveness analysis") \ \ @@ -2766,22 +2559,9 @@ notproduct(bool, CollectIndexSetStatistics, false, \ "Collect information about IndexSets") \ \ - develop(bool, PrintDominators, false, \ - "Print out dominator trees for GVN") \ - \ develop(bool, UseLoopSafepoints, true, \ "Generate Safepoint nodes in every loop") \ \ - notproduct(bool, TraceCISCSpill, false, \ - "Trace allocators use of cisc spillable instructions") \ - \ - notproduct(bool, TraceSpilling, false, \ - "Trace spilling") \ - \ - product(bool, SplitIfBlocks, true, \ - "Clone compares and control flow through merge points to fold " \ - "some branches") \ - \ develop(intx, FastAllocateSizeLimit, 128*K, \ /* Note: This value is zero mod 1<<13 for a cheap sparc set. */ \ "Inline allocations larger than this in doublewords must go slow")\ @@ -2838,15 +2618,6 @@ develop(bool, UseFastSignatureHandlers, true, \ "Use fast signature handlers for native calls") \ \ - develop(bool, UseV8InstrsOnly, false, \ - "Use SPARC-V8 Compliant instruction subset") \ - \ - product(bool, UseNiagaraInstrs, false, \ - "Use Niagara-efficient instruction subset") \ - \ - develop(bool, UseCASForSwap, false, \ - "Do not use swap instructions, but only CAS (in a loop) on SPARC")\ - \ product(bool, UseLoopCounter, true, \ "Increment invocation counter on backward branch") \ \ @@ -2863,9 +2634,6 @@ notproduct(bool, TraceOnStackReplacement, false, \ "Trace on stack replacement") \ \ - develop(bool, PoisonOSREntry, true, \ - "Detect abnormal calls to OSR code") \ - \ product_pd(bool, PreferInterpreterNativeStubs, \ "Use always interpreter stubs for native methods invoked via " \ "interpreter") \ @@ -2908,9 +2676,6 @@ develop(bool, TraceFrequencyInlining, false, \ "Trace frequency based inlining") \ \ - notproduct(bool, TraceTypeProfile, false, \ - "Trace type profile") \ - \ develop_pd(bool, InlineIntrinsics, \ "Inline intrinsics that can be statically resolved") \ \ @@ -2998,15 +2763,6 @@ product(intx, AllocatePrefetchInstr, 0, \ "Prefetch instruction to prefetch ahead of allocation pointer") \ \ - product(intx, ReadPrefetchInstr, 0, \ - "Prefetch instruction to prefetch ahead") \ - \ - product(uintx, ArraycopySrcPrefetchDistance, 0, \ - "Distance to prefetch source array in arracopy") \ - \ - product(uintx, ArraycopyDstPrefetchDistance, 0, \ - "Distance to prefetch destination array in arracopy") \ - \ /* deoptimization */ \ product(bool, TraceDeoptimization, false, \ "Trace deoptimization") \ @@ -3100,9 +2856,6 @@ product(intx, MinInliningThreshold, 250, \ "min. invocation count a method needs to have to be inlined") \ \ - develop(intx, AlignEntryCode, 4, \ - "aligns entry code to specified value (in bytes)") \ - \ develop(intx, MethodHistogramCutoff, 100, \ "cutoff value for method invoc. histogram (+CountCalls)") \ \ @@ -3142,9 +2895,6 @@ "Minimum sleep() interval (milliseconds) when " \ "ConvertSleepToYield is off (used for SOLARIS)") \ \ - product(intx, EventLogLength, 2000, \ - "maximum nof events in event log") \ - \ develop(intx, ProfilerPCTickThreshold, 15, \ "Number of ticks in a PC buckets to be a hotspot") \ \ @@ -3183,9 +2933,6 @@ product(intx, PerBytecodeTrapLimit, 4, \ "Limit on traps (of one kind) at a particular BCI") \ \ - develop(intx, FreqCountInvocations, 1, \ - "Scaling factor for branch frequencies (deprecated)") \ - \ develop(intx, InlineFrequencyRatio, 20, \ "Ratio of call site execution to caller method invocation") \ \ @@ -3199,29 +2946,12 @@ develop(intx, InlineThrowMaxSize, 200, \ "Force inlining of throwing methods smaller than this") \ \ - product(intx, AliasLevel, 3, \ - "0 for no aliasing, 1 for oop/field/static/array split, " \ - "2 for class split, 3 for unique instances") \ - \ - develop(bool, VerifyAliases, false, \ - "perform extra checks on the results of alias analysis") \ - \ develop(intx, ProfilerNodeSize, 1024, \ "Size in K to allocate for the Profile Nodes of each thread") \ \ - develop(intx, V8AtomicOperationUnderLockSpinCount, 50, \ - "Number of times to spin wait on a v8 atomic operation lock") \ - \ - product(intx, ReadSpinIterations, 100, \ - "Number of read attempts before a yield (spin inner loop)") \ - \ product_pd(intx, PreInflateSpin, \ "Number of times to spin wait before inflation") \ \ - product(intx, PreBlockSpin, 10, \ - "Number of times to spin in an inflated lock before going to " \ - "an OS lock") \ - \ /* gc parameters */ \ product(uintx, InitialHeapSize, 0, \ "Initial heap size (in bytes); zero means OldSize + NewSize") \ @@ -3478,10 +3208,6 @@ "(non-negative value throws OOM after this many CI accesses " \ "in each compile)") \ \ - develop(intx, CIFireOOMAtDelay, -1, \ - "Wait for this many CI accesses to occur in all compiles before " \ - "beginning to throw OutOfMemoryErrors in each compile") \ - \ notproduct(bool, CIObjectFactoryVerify, false, \ "enable potentially expensive verification in ciObjectFactory") \ \ @@ -3675,9 +3401,6 @@ product(bool, PrintTieredEvents, false, \ "Print tiered events notifications") \ \ - product(bool, StressTieredRuntime, false, \ - "Alternate client and server compiler on compile requests") \ - \ product_pd(intx, OnStackReplacePercentage, \ "NON_TIERED number of method invocations/branches (expressed as %"\ "of CompileThreshold) before (re-)compiling OSR code") \ @@ -3847,9 +3570,6 @@ "support JSR 292 (method handles, invokedynamic, " \ "anonymous classes") \ \ - product(bool, AnonymousClasses, false, \ - "support sun.misc.Unsafe.defineAnonymousClass (deprecated)") \ - \ diagnostic(bool, PrintMethodHandleStubs, false, \ "Print generated stub code for method handles") \ \ @@ -3964,6 +3684,8 @@ RUNTIME_OS_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG) +ARCH_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG) + // Extensions #include "runtime/globals_ext.hpp"
--- a/src/share/vm/runtime/globals_extension.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/runtime/globals_extension.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,7 +66,6 @@ #define C1_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), #endif - #define C2_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), #define C2_PD_PRODUCT_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), #define C2_DIAGNOSTIC_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), @@ -81,6 +80,17 @@ #define C2_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), #endif +#define ARCH_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), +#define ARCH_DIAGNOSTIC_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), +#define ARCH_EXPERIMENTAL_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), +#ifdef PRODUCT + #define ARCH_DEVELOP_FLAG_MEMBER(type, name, value, doc) /* flag is constant */ + #define ARCH_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) +#else + #define ARCH_DEVELOP_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), + #define ARCH_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), +#endif + typedef enum { RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_EXPERIMENTAL_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER, RUNTIME_LP64_PRODUCT_FLAG_MEMBER) RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER) @@ -93,6 +103,7 @@ #ifdef COMPILER2 C2_FLAGS(C2_DEVELOP_FLAG_MEMBER, C2_PD_DEVELOP_FLAG_MEMBER, C2_PRODUCT_FLAG_MEMBER, C2_PD_PRODUCT_FLAG_MEMBER, C2_DIAGNOSTIC_FLAG_MEMBER, C2_EXPERIMENTAL_FLAG_MEMBER, C2_NOTPRODUCT_FLAG_MEMBER) #endif + ARCH_FLAGS(ARCH_DEVELOP_FLAG_MEMBER, ARCH_PRODUCT_FLAG_MEMBER, ARCH_DIAGNOSTIC_FLAG_MEMBER, ARCH_EXPERIMENTAL_FLAG_MEMBER, ARCH_NOTPRODUCT_FLAG_MEMBER) COMMANDLINEFLAG_EXT NUM_CommandLineFlag } CommandLineFlag; @@ -134,7 +145,6 @@ #define RUNTIME_LP64_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) /* flag is constant */ #endif // _LP64 - #define C2_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), #define C2_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type), #define C2_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), @@ -149,6 +159,17 @@ #define C2_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), #endif +#define ARCH_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), +#define ARCH_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), +#define ARCH_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), +#ifdef PRODUCT + #define ARCH_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) /* flag is constant */ + #define ARCH_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) +#else + #define ARCH_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), + #define ARCH_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), +#endif + typedef enum { RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE, RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE, @@ -193,6 +214,11 @@ C2_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE, C2_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE) #endif + ARCH_FLAGS(ARCH_DEVELOP_FLAG_MEMBER_WITH_TYPE, + ARCH_PRODUCT_FLAG_MEMBER_WITH_TYPE, + ARCH_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE, + ARCH_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE, + ARCH_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE) COMMANDLINEFLAGWITHTYPE_EXT NUM_CommandLineFlagWithType } CommandLineFlagWithType;
--- a/src/share/vm/runtime/relocator.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/runtime/relocator.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -465,13 +465,12 @@ void Relocator::adjust_stack_map_table(int bci, int delta) { if (method()->has_stackmap_table()) { typeArrayOop data = method()->stackmap_data(); - // The data in the array is a classfile representation of the stackmap - // table attribute, less the initial u2 tag and u4 attribute_length fields. - stack_map_table_attribute* attr = stack_map_table_attribute::at( - (address)data->byte_at_addr(0) - (sizeof(u2) + sizeof(u4))); + // The data in the array is a classfile representation of the stackmap table + stack_map_table* sm_table = + stack_map_table::at((address)data->byte_at_addr(0)); - int count = attr->number_of_entries(); - stack_map_frame* frame = attr->entries(); + int count = sm_table->number_of_entries(); + stack_map_frame* frame = sm_table->entries(); int bci_iter = -1; bool offset_adjusted = false; // only need to adjust one offset @@ -486,7 +485,7 @@ frame->set_offset_delta(new_offset_delta); } else { assert(frame->is_same_frame() || - frame->is_same_frame_1_stack_item_frame(), + frame->is_same_locals_1_stack_item_frame(), "Frame must be one of the compressed forms"); // The new delta exceeds the capacity of the 'same_frame' or // 'same_frame_1_stack_item_frame' frame types. We need to @@ -513,7 +512,7 @@ if (frame->is_same_frame()) { same_frame_extended::create_at(frame_addr, new_offset_delta); } else { - same_frame_1_stack_item_extended::create_at( + same_locals_1_stack_item_extended::create_at( frame_addr, new_offset_delta, NULL); // the verification_info_type should already be at the right spot }
--- a/src/share/vm/runtime/vmStructs.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/runtime/vmStructs.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -2135,6 +2135,7 @@ /******************/ \ \ declare_constant(UseTLAB) \ + declare_constant(EnableInvokeDynamic) \ \ /**************/ \ /* Stack bias */ \
--- a/src/share/vm/services/memPtr.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/services/memPtr.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -27,7 +27,7 @@ #include "services/memTracker.hpp" volatile jint SequenceGenerator::_seq_number = 1; -DEBUG_ONLY(jint SequenceGenerator::_max_seq_number = 1;) +NOT_PRODUCT(jint SequenceGenerator::_max_seq_number = 1;) DEBUG_ONLY(volatile unsigned long SequenceGenerator::_generation = 0;) jint SequenceGenerator::next() { @@ -36,7 +36,7 @@ MemTracker::shutdown(MemTracker::NMT_sequence_overflow); } assert(seq > 0, "counter overflow"); - DEBUG_ONLY(_max_seq_number = (seq > _max_seq_number) ? seq : _max_seq_number;) + NOT_PRODUCT(_max_seq_number = (seq > _max_seq_number) ? seq : _max_seq_number;) return seq; }
--- a/src/share/vm/services/memPtr.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/services/memPtr.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -51,11 +51,11 @@ }; DEBUG_ONLY(static unsigned long current_generation() { return (unsigned long)_generation; }) - DEBUG_ONLY(static jint max_seq_num() { return _max_seq_number; }) + NOT_PRODUCT(static jint max_seq_num() { return _max_seq_number; }) private: static volatile jint _seq_number; - DEBUG_ONLY(static jint _max_seq_number; ) + NOT_PRODUCT(static jint _max_seq_number; ) DEBUG_ONLY(static volatile unsigned long _generation; ) };
--- a/src/share/vm/services/memPtrArray.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/services/memPtrArray.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -59,7 +59,7 @@ virtual size_t instance_size() const = 0; virtual bool shrink() = 0; - debug_only(virtual int capacity() const = 0;) + NOT_PRODUCT(virtual int capacity() const = 0;) }; // Iterator interface @@ -205,7 +205,7 @@ return _size; } - debug_only(int capacity() const { return _max_size; }) + NOT_PRODUCT(int capacity() const { return _max_size; }) void clear() { assert(_data != NULL, "Just check");
--- a/src/share/vm/services/memRecorder.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/services/memRecorder.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -73,7 +73,7 @@ return sizeof(FixedSizeMemPointerArray<E, SIZE>); } - debug_only(int capacity() const { return SIZE; }) + NOT_PRODUCT(int capacity() const { return SIZE; }) public: // implementation of public interface
--- a/src/share/vm/services/memSnapshot.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/services/memSnapshot.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -338,15 +338,13 @@ vm_itr.insert_after(cur_vm); } } else { -#ifdef ASSERT // In theory, we should assert without conditions. However, in case of native // thread stack, NMT explicitly releases the thread stack in Thread's destructor, // due to platform dependent behaviors. On some platforms, we see uncommit/release // native thread stack, but some, we don't. - if (!cur_vm->is_uncommit_record() && !cur_vm->is_deallocation_record()) { - ShouldNotReachHere(); - } -#endif + assert(cur_vm->is_uncommit_record() || cur_vm->is_deallocation_record(), + err_msg("Should not reach here, pointer addr = [" INTPTR_FORMAT "], flags = [%x]", + cur_vm->addr(), cur_vm->flags())); } } } else { @@ -406,7 +404,7 @@ } -#ifdef ASSERT +#ifndef PRODUCT void MemSnapshot::print_snapshot_stats(outputStream* st) { st->print_cr("Snapshot:"); st->print_cr("\tMalloced: %d/%d [%5.2f%%] %dKB", _alloc_ptrs->length(), _alloc_ptrs->capacity(), @@ -434,6 +432,20 @@ } } +bool MemSnapshot::has_allocation_record(address addr) { + MemPointerArrayIteratorImpl itr(_staging_area); + MemPointerRecord* cur = (MemPointerRecord*)itr.current(); + while (cur != NULL) { + if (cur->addr() == addr && cur->is_allocation_record()) { + return true; + } + cur = (MemPointerRecord*)itr.next(); + } + return false; +} +#endif // PRODUCT + +#ifdef ASSERT void MemSnapshot::check_staging_data() { MemPointerArrayIteratorImpl itr(_staging_area); MemPointerRecord* cur = (MemPointerRecord*)itr.current(); @@ -447,17 +459,5 @@ next = (MemPointerRecord*)itr.next(); } } +#endif // ASSERT -bool MemSnapshot::has_allocation_record(address addr) { - MemPointerArrayIteratorImpl itr(_staging_area); - MemPointerRecord* cur = (MemPointerRecord*)itr.current(); - while (cur != NULL) { - if (cur->addr() == addr && cur->is_allocation_record()) { - return true; - } - cur = (MemPointerRecord*)itr.next(); - } - return false; -} - -#endif
--- a/src/share/vm/services/memSnapshot.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/services/memSnapshot.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -63,13 +63,13 @@ MemPointer* p1 = (MemPointer*)ptr; MemPointer* p2 = (MemPointer*)_array->at(_pos - 1); assert(!is_dup_pointer(p1, p2), - "dup pointer"); + err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags())); } if (_pos < _array->length() -1) { MemPointer* p1 = (MemPointer*)ptr; MemPointer* p2 = (MemPointer*)_array->at(_pos + 1); assert(!is_dup_pointer(p1, p2), - "dup pointer"); + err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags())); } return _array->insert_at(ptr, _pos); } @@ -79,14 +79,14 @@ MemPointer* p1 = (MemPointer*)ptr; MemPointer* p2 = (MemPointer*)_array->at(_pos - 1); assert(!is_dup_pointer(p1, p2), - "dup pointer"); + err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags())); } if (_pos < _array->length() - 1) { MemPointer* p1 = (MemPointer*)ptr; MemPointer* p2 = (MemPointer*)_array->at(_pos + 1); assert(!is_dup_pointer(p1, p2), - "dup pointer"); + err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags())); } if (_array->insert_at(ptr, _pos + 1)) { _pos ++;
--- a/src/share/vm/services/memTrackWorker.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/services/memTrackWorker.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -99,9 +99,11 @@ } if (rec != NULL) { // merge the recorder into staging area - bool result = snapshot->merge(rec); - assert(result, "merge failed"); - debug_only(_merge_count ++;) + if (!snapshot->merge(rec)) { + MemTracker::shutdown(MemTracker::NMT_out_of_memory); + } else { + NOT_PRODUCT(_merge_count ++;) + } MemTracker::release_thread_recorder(rec); } else { // no more recorder to merge, promote staging area @@ -129,7 +131,7 @@ } assert(MemTracker::shutdown_in_progress(), "just check"); - // transites to final shutdown + // transits to final shutdown MemTracker::final_shutdown(); }
--- a/src/share/vm/services/memTracker.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/services/memTracker.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -65,7 +65,7 @@ int MemTracker::_thread_count = 255; volatile jint MemTracker::_pooled_recorder_count = 0; debug_only(intx MemTracker::_main_thread_tid = 0;) -debug_only(volatile jint MemTracker::_pending_recorder_count = 0;) +NOT_PRODUCT(volatile jint MemTracker::_pending_recorder_count = 0;) void MemTracker::init_tracking_options(const char* option_line) { _tracking_level = NMT_off; @@ -291,7 +291,7 @@ (void*)cur_head)) { cur_head = const_cast<MemRecorder*>(_merge_pending_queue); } - debug_only(Atomic::store(0, &_pending_recorder_count)); + NOT_PRODUCT(Atomic::store(0, &_pending_recorder_count)); return cur_head; } @@ -420,7 +420,7 @@ cur_head = const_cast<MemRecorder*>(_merge_pending_queue); rec->set_next(cur_head); } - debug_only(Atomic::inc(&_pending_recorder_count);) + NOT_PRODUCT(Atomic::inc(&_pending_recorder_count);) } /*
--- a/src/share/vm/services/memTracker.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/services/memTracker.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -184,7 +184,6 @@ // record a 'malloc' call static inline void record_malloc(address addr, size_t size, MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { - assert(is_on(), "check by caller"); if (NMT_CAN_TRACK(flags)) { create_memory_record(addr, (flags|MemPointerRecord::malloc_tag()), size, pc, thread); } @@ -285,7 +284,6 @@ // retrieve global snapshot static MemSnapshot* get_snapshot() { - assert(is_on(), "native memory tracking is off"); if (shutdown_in_progress()) { return NULL; }
--- a/src/share/vm/utilities/ostream.cpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/utilities/ostream.cpp Fri Nov 09 13:35:26 2012 +0100 @@ -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 @@ -238,8 +238,9 @@ return; } -void outputStream::indent() { +outputStream& outputStream::indent() { while (_position < _indentation) sp(); + return *this; } void outputStream::print_jlong(jlong value) { @@ -252,6 +253,47 @@ print(os::julong_format_specifier(), value); } +/** + * This prints out hex data in a 'windbg' or 'xxd' form, where each line is: + * <hex-address>: 8 * <hex-halfword> <ascii translation (optional)> + * example: + * 0000000: 7f44 4f46 0102 0102 0000 0000 0000 0000 .DOF............ + * 0000010: 0000 0000 0000 0040 0000 0020 0000 0005 .......@... .... + * 0000020: 0000 0000 0000 0040 0000 0000 0000 015d .......@.......] + * ... + * + * indent is applied to each line. Ends with a CR. + */ +void outputStream::print_data(void* data, size_t len, bool with_ascii) { + size_t limit = (len + 16) / 16 * 16; + for (size_t i = 0; i < limit; ++i) { + if (i % 16 == 0) { + indent().print("%07x:", i); + } + if (i % 2 == 0) { + print(" "); + } + if (i < len) { + print("%02x", ((unsigned char*)data)[i]); + } else { + print(" "); + } + if ((i + 1) % 16 == 0) { + if (with_ascii) { + print(" "); + for (size_t j = 0; j < 16; ++j) { + size_t idx = i + j - 15; + if (idx < len) { + char c = ((char*)data)[idx]; + print("%c", c >= 32 && c <= 126 ? c : '.'); + } + } + } + print_cr(""); + } + } +} + stringStream::stringStream(size_t initial_size) : outputStream() { buffer_length = initial_size; buffer = NEW_RESOURCE_ARRAY(char, buffer_length);
--- a/src/share/vm/utilities/ostream.hpp Fri Nov 09 13:32:53 2012 +0100 +++ b/src/share/vm/utilities/ostream.hpp Fri Nov 09 13:35:26 2012 +0100 @@ -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 @@ -59,9 +59,11 @@ outputStream(int width, bool has_time_stamps); // indentation - void indent(); + outputStream& indent(); void inc() { _indentation++; }; void dec() { _indentation--; }; + void inc(int n) { _indentation += n; }; + void dec(int n) { _indentation -= n; }; int indentation() const { return _indentation; } void set_indentation(int i) { _indentation = i; } void fill_to(int col); @@ -84,6 +86,7 @@ void print_raw(const char* str, int len) { write(str, len); } void print_raw_cr(const char* str) { write(str, strlen(str)); cr(); } void print_raw_cr(const char* str, int len){ write(str, len); cr(); } + void print_data(void* data, size_t len, bool with_ascii); void put(char ch); void sp(int count = 1); void cr(); @@ -122,6 +125,19 @@ extern outputStream* tty; // tty output extern outputStream* gclog_or_tty; // stream for gc log if -Xloggc:<f>, or tty +class streamIndentor : public StackObj { + private: + outputStream* _str; + int _amount; + + public: + streamIndentor(outputStream* str, int amt = 2) : _str(str), _amount(amt) { + _str->inc(_amount); + } + ~streamIndentor() { _str->dec(_amount); } +}; + + // advisory locking for the shared tty stream: class ttyLocker: StackObj { friend class ttyUnlocker;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6340864/TestByteVect.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,1274 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 6340864 + * @summary Implement vectorization optimizations in hotspot-server + * + * @run main/othervm/timeout=400 -Xbatch -Xmx64m TestByteVect + */ + +public class TestByteVect { + private static final int ARRLEN = 997; + private static final int ITERS = 11000; + private static final int ADD_INIT = 0; + private static final int BIT_MASK = 0xB7; + private static final int VALUE = 3; + private static final int SHIFT = 8; + + public static void main(String args[]) { + System.out.println("Testing Byte vectors"); + int errn = test(); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test() { + byte[] a0 = new byte[ARRLEN]; + byte[] a1 = new byte[ARRLEN]; + byte[] a2 = new byte[ARRLEN]; + byte[] a3 = new byte[ARRLEN]; + byte[] a4 = new byte[ARRLEN]; + short[] p2 = new short[ARRLEN/2]; + int[] p4 = new int[ARRLEN/4]; + long[] p8 = new long[ARRLEN/8]; + // Initialize + int gold_sum = 0; + for (int i=0; i<ARRLEN; i++) { + byte val = (byte)(ADD_INIT+i); + gold_sum += val; + a1[i] = val; + a2[i] = (byte)VALUE; + a3[i] = (byte)-VALUE; + a4[i] = (byte)BIT_MASK; + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_sum(a1); + test_addc(a0, a1); + test_addv(a0, a1, (byte)VALUE); + test_adda(a0, a1, a2); + test_subc(a0, a1); + test_subv(a0, a1, (byte)VALUE); + test_suba(a0, a1, a2); + test_mulc(a0, a1); + test_mulv(a0, a1, (byte)VALUE); + test_mula(a0, a1, a2); + test_divc(a0, a1); + test_divv(a0, a1, (byte)VALUE); + test_diva(a0, a1, a2); + test_mulc_n(a0, a1); + test_mulv(a0, a1, (byte)-VALUE); + test_mula(a0, a1, a3); + test_divc_n(a0, a1); + test_divv(a0, a1, (byte)-VALUE); + test_diva(a0, a1, a3); + test_andc(a0, a1); + test_andv(a0, a1, (byte)BIT_MASK); + test_anda(a0, a1, a4); + test_orc(a0, a1); + test_orv(a0, a1, (byte)BIT_MASK); + test_ora(a0, a1, a4); + test_xorc(a0, a1); + test_xorv(a0, a1, (byte)BIT_MASK); + test_xora(a0, a1, a4); + test_sllc(a0, a1); + test_sllv(a0, a1, VALUE); + test_srlc(a0, a1); + test_srlv(a0, a1, VALUE); + test_srac(a0, a1); + test_srav(a0, a1, VALUE); + test_sllc_n(a0, a1); + test_sllv(a0, a1, -VALUE); + test_srlc_n(a0, a1); + test_srlv(a0, a1, -VALUE); + test_srac_n(a0, a1); + test_srav(a0, a1, -VALUE); + test_sllc_o(a0, a1); + test_sllv(a0, a1, SHIFT); + test_srlc_o(a0, a1); + test_srlv(a0, a1, SHIFT); + test_srac_o(a0, a1); + test_srav(a0, a1, SHIFT); + test_sllc_on(a0, a1); + test_sllv(a0, a1, -SHIFT); + test_srlc_on(a0, a1); + test_srlv(a0, a1, -SHIFT); + test_srac_on(a0, a1); + test_srav(a0, a1, -SHIFT); + test_pack2(p2, a1); + test_unpack2(a0, p2); + test_pack2_swap(p2, a1); + test_unpack2_swap(a0, p2); + test_pack4(p4, a1); + test_unpack4(a0, p4); + test_pack4_swap(p4, a1); + test_unpack4_swap(a0, p4); + test_pack8(p8, a1); + test_unpack8(a0, p8); + test_pack8_swap(p8, a1); + test_unpack8_swap(a0, p8); + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + int sum = test_sum(a1); + if (sum != gold_sum) { + System.err.println("test_sum: " + sum + " != " + gold_sum); + errn++; + } + + test_addc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_addc: ", i, a0[i], (byte)((byte)(ADD_INIT+i)+VALUE)); + } + test_addv(a0, a1, (byte)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_addv: ", i, a0[i], (byte)((byte)(ADD_INIT+i)+VALUE)); + } + test_adda(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_adda: ", i, a0[i], (byte)((byte)(ADD_INIT+i)+VALUE)); + } + + test_subc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_subc: ", i, a0[i], (byte)((byte)(ADD_INIT+i)-VALUE)); + } + test_subv(a0, a1, (byte)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_subv: ", i, a0[i], (byte)((byte)(ADD_INIT+i)-VALUE)); + } + test_suba(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_suba: ", i, a0[i], (byte)((byte)(ADD_INIT+i)-VALUE)); + } + + test_mulc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulc: ", i, a0[i], (byte)((byte)(ADD_INIT+i)*VALUE)); + } + test_mulv(a0, a1, (byte)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulv: ", i, a0[i], (byte)((byte)(ADD_INIT+i)*VALUE)); + } + test_mula(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mula: ", i, a0[i], (byte)((byte)(ADD_INIT+i)*VALUE)); + } + + test_divc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divc: ", i, a0[i], (byte)((byte)(ADD_INIT+i)/VALUE)); + } + test_divv(a0, a1, (byte)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divv: ", i, a0[i], (byte)((byte)(ADD_INIT+i)/VALUE)); + } + test_diva(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_diva: ", i, a0[i], (byte)((byte)(ADD_INIT+i)/VALUE)); + } + + test_mulc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulc_n: ", i, a0[i], (byte)((byte)(ADD_INIT+i)*(-VALUE))); + } + test_mulv(a0, a1, (byte)-VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulv_n: ", i, a0[i], (byte)((byte)(ADD_INIT+i)*(-VALUE))); + } + test_mula(a0, a1, a3); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mula_n: ", i, a0[i], (byte)((byte)(ADD_INIT+i)*(-VALUE))); + } + + test_divc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divc_n: ", i, a0[i], (byte)((byte)(ADD_INIT+i)/(-VALUE))); + } + test_divv(a0, a1, (byte)-VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divv_n: ", i, a0[i], (byte)((byte)(ADD_INIT+i)/(-VALUE))); + } + test_diva(a0, a1, a3); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_diva_n: ", i, a0[i], (byte)((byte)(ADD_INIT+i)/(-VALUE))); + } + + test_andc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_andc: ", i, a0[i], (byte)((byte)(ADD_INIT+i)&BIT_MASK)); + } + test_andv(a0, a1, (byte)BIT_MASK); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_andv: ", i, a0[i], (byte)((byte)(ADD_INIT+i)&BIT_MASK)); + } + test_anda(a0, a1, a4); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_anda: ", i, a0[i], (byte)((byte)(ADD_INIT+i)&BIT_MASK)); + } + + test_orc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_orc: ", i, a0[i], (byte)((byte)(ADD_INIT+i)|BIT_MASK)); + } + test_orv(a0, a1, (byte)BIT_MASK); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_orv: ", i, a0[i], (byte)((byte)(ADD_INIT+i)|BIT_MASK)); + } + test_ora(a0, a1, a4); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ora: ", i, a0[i], (byte)((byte)(ADD_INIT+i)|BIT_MASK)); + } + + test_xorc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_xorc: ", i, a0[i], (byte)((byte)(ADD_INIT+i)^BIT_MASK)); + } + test_xorv(a0, a1, (byte)BIT_MASK); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_xorv: ", i, a0[i], (byte)((byte)(ADD_INIT+i)^BIT_MASK)); + } + test_xora(a0, a1, a4); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_xora: ", i, a0[i], (byte)((byte)(ADD_INIT+i)^BIT_MASK)); + } + + test_sllc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc: ", i, a0[i], (byte)((byte)(ADD_INIT+i)<<VALUE)); + } + test_sllv(a0, a1, VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv: ", i, a0[i], (byte)((byte)(ADD_INIT+i)<<VALUE)); + } + + test_srlc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>>VALUE)); + } + test_srlv(a0, a1, VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>>VALUE)); + } + + test_srac(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>VALUE)); + } + test_srav(a0, a1, VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>VALUE)); + } + + test_sllc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc_n: ", i, a0[i], (byte)((byte)(ADD_INIT+i)<<(-VALUE))); + } + test_sllv(a0, a1, -VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv_n: ", i, a0[i], (byte)((byte)(ADD_INIT+i)<<(-VALUE))); + } + + test_srlc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc_n: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>>(-VALUE))); + } + test_srlv(a0, a1, -VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv_n: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>>(-VALUE))); + } + + test_srac_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac_n: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>(-VALUE))); + } + test_srav(a0, a1, -VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav_n: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>(-VALUE))); + } + + test_sllc_o(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc_o: ", i, a0[i], (byte)((byte)(ADD_INIT+i)<<SHIFT)); + } + test_sllv(a0, a1, SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv_o: ", i, a0[i], (byte)((byte)(ADD_INIT+i)<<SHIFT)); + } + + test_srlc_o(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc_o: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>>SHIFT)); + } + test_srlv(a0, a1, SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv_o: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>>SHIFT)); + } + + test_srac_o(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac_o: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>SHIFT)); + } + test_srav(a0, a1, SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav_o: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>SHIFT)); + } + + test_sllc_on(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc_on: ", i, a0[i], (byte)((byte)(ADD_INIT+i)<<(-SHIFT))); + } + test_sllv(a0, a1, -SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv_on: ", i, a0[i], (byte)((byte)(ADD_INIT+i)<<(-SHIFT))); + } + + test_srlc_on(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc_on: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>>(-SHIFT))); + } + test_srlv(a0, a1, -SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv_on: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>>(-SHIFT))); + } + + test_srac_on(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac_on: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>(-SHIFT))); + } + test_srav(a0, a1, -SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav_on: ", i, a0[i], (byte)((byte)(ADD_INIT+i)>>(-SHIFT))); + } + + test_pack2(p2, a1); + for (int i=0; i<ARRLEN/2; i++) { + errn += verify("test_pack2: ", i, p2[i], (short)(((short)(ADD_INIT+2*i) & 0xFF) | ((short)(ADD_INIT+2*i+1) << 8))); + } + for (int i=0; i<ARRLEN; i++) { + a0[i] = -1; + } + test_unpack2(a0, p2); + for (int i=0; i<(ARRLEN&(-2)); i++) { + errn += verify("test_unpack2: ", i, a0[i], (byte)(ADD_INIT+i)); + } + + test_pack2_swap(p2, a1); + for (int i=0; i<ARRLEN/2; i++) { + errn += verify("test_pack2_swap: ", i, p2[i], (short)(((short)(ADD_INIT+2*i+1) & 0xFF) | ((short)(ADD_INIT+2*i) << 8))); + } + for (int i=0; i<ARRLEN; i++) { + a0[i] = -1; + } + test_unpack2_swap(a0, p2); + for (int i=0; i<(ARRLEN&(-2)); i++) { + errn += verify("test_unpack2_swap: ", i, a0[i], (byte)(ADD_INIT+i)); + } + + test_pack4(p4, a1); + for (int i=0; i<ARRLEN/4; i++) { + errn += verify("test_pack4: ", i, p4[i], ((int)(ADD_INIT+4*i+0) & 0xFF) | + (((int)(ADD_INIT+4*i+1) & 0xFF) << 8) | + (((int)(ADD_INIT+4*i+2) & 0xFF) << 16) | + (((int)(ADD_INIT+4*i+3) & 0xFF) << 24)); + } + for (int i=0; i<ARRLEN; i++) { + a0[i] = -1; + } + test_unpack4(a0, p4); + for (int i=0; i<(ARRLEN&(-4)); i++) { + errn += verify("test_unpack4: ", i, a0[i], (byte)(ADD_INIT+i)); + } + + test_pack4_swap(p4, a1); + for (int i=0; i<ARRLEN/4; i++) { + errn += verify("test_pack4_swap: ", i, p4[i], ((int)(ADD_INIT+4*i+3) & 0xFF) | + (((int)(ADD_INIT+4*i+2) & 0xFF) << 8) | + (((int)(ADD_INIT+4*i+1) & 0xFF) << 16) | + (((int)(ADD_INIT+4*i+0) & 0xFF) << 24)); + } + for (int i=0; i<ARRLEN; i++) { + a0[i] = -1; + } + test_unpack4_swap(a0, p4); + for (int i=0; i<(ARRLEN&(-4)); i++) { + errn += verify("test_unpack4_swap: ", i, a0[i], (byte)(ADD_INIT+i)); + } + + test_pack8(p8, a1); + for (int i=0; i<ARRLEN/8; i++) { + errn += verify("test_pack8: ", i, p8[i], ((long)(ADD_INIT+8*i+0) & 0xFFl) | + (((long)(ADD_INIT+8*i+1) & 0xFFl) << 8) | + (((long)(ADD_INIT+8*i+2) & 0xFFl) << 16) | + (((long)(ADD_INIT+8*i+3) & 0xFFl) << 24) | + (((long)(ADD_INIT+8*i+4) & 0xFFl) << 32) | + (((long)(ADD_INIT+8*i+5) & 0xFFl) << 40) | + (((long)(ADD_INIT+8*i+6) & 0xFFl) << 48) | + (((long)(ADD_INIT+8*i+7) & 0xFFl) << 56)); + } + for (int i=0; i<ARRLEN; i++) { + a0[i] = -1; + } + test_unpack8(a0, p8); + for (int i=0; i<(ARRLEN&(-8)); i++) { + errn += verify("test_unpack8: ", i, a0[i], (byte)(ADD_INIT+i)); + } + + test_pack8_swap(p8, a1); + for (int i=0; i<ARRLEN/8; i++) { + errn += verify("test_pack8_swap: ", i, p8[i], ((long)(ADD_INIT+8*i+7) & 0xFFl) | + (((long)(ADD_INIT+8*i+6) & 0xFFl) << 8) | + (((long)(ADD_INIT+8*i+5) & 0xFFl) << 16) | + (((long)(ADD_INIT+8*i+4) & 0xFFl) << 24) | + (((long)(ADD_INIT+8*i+3) & 0xFFl) << 32) | + (((long)(ADD_INIT+8*i+2) & 0xFFl) << 40) | + (((long)(ADD_INIT+8*i+1) & 0xFFl) << 48) | + (((long)(ADD_INIT+8*i+0) & 0xFFl) << 56)); + } + for (int i=0; i<ARRLEN; i++) { + a0[i] = -1; + } + test_unpack8_swap(a0, p8); + for (int i=0; i<(ARRLEN&(-8)); i++) { + errn += verify("test_unpack8_swap: ", i, a0[i], (byte)(ADD_INIT+i)); + } + + } + + if (errn > 0) + return errn; + + System.out.println("Time"); + long start, end; + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sum(a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sum: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_addc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addv(a0, a1, (byte)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_addv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_adda(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_adda: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_subc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_subc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_subv(a0, a1, (byte)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_subv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_suba(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_suba: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_mulc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulv(a0, a1, (byte)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_mulv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mula(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_mula: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_divc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divv(a0, a1, (byte)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_divv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_diva(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_diva: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_mulc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulv(a0, a1, (byte)-VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_mulv_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mula(a0, a1, a3); + } + end = System.currentTimeMillis(); + System.out.println("test_mula_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_divc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divv(a0, a1, (byte)-VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_divv_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_diva(a0, a1, a3); + } + end = System.currentTimeMillis(); + System.out.println("test_diva_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_andc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_andc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_andv(a0, a1, (byte)BIT_MASK); + } + end = System.currentTimeMillis(); + System.out.println("test_andv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_anda(a0, a1, a4); + } + end = System.currentTimeMillis(); + System.out.println("test_anda: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_orc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_orc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_orv(a0, a1, (byte)BIT_MASK); + } + end = System.currentTimeMillis(); + System.out.println("test_orv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ora(a0, a1, a4); + } + end = System.currentTimeMillis(); + System.out.println("test_ora: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_xorc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_xorc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_xorv(a0, a1, (byte)BIT_MASK); + } + end = System.currentTimeMillis(); + System.out.println("test_xorv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_xora(a0, a1, a4); + } + end = System.currentTimeMillis(); + System.out.println("test_xora: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srav: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srav_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc_o(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc_o: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv_o: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc_o(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc_o: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv_o: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac_o(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac_o: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srav_o: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc_on(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc_on: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, -SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv_on: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc_on(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc_on: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, -SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv_on: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac_on(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac_on: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, -SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srav_on: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_pack2(p2, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_pack2: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unpack2(a0, p2); + } + end = System.currentTimeMillis(); + System.out.println("test_unpack2: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_pack2_swap(p2, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_pack2_swap: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unpack2_swap(a0, p2); + } + end = System.currentTimeMillis(); + System.out.println("test_unpack2_swap: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_pack4(p4, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_pack4: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unpack4(a0, p4); + } + end = System.currentTimeMillis(); + System.out.println("test_unpack4: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_pack4_swap(p4, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_pack4_swap: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unpack4_swap(a0, p4); + } + end = System.currentTimeMillis(); + System.out.println("test_unpack4_swap: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_pack8(p8, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_pack8: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unpack8(a0, p8); + } + end = System.currentTimeMillis(); + System.out.println("test_unpack8: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_pack8_swap(p8, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_pack8_swap: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unpack8_swap(a0, p8); + } + end = System.currentTimeMillis(); + System.out.println("test_unpack8_swap: " + (end - start)); + + return errn; + } + + static int test_sum(byte[] a1) { + int sum = 0; + for (int i = 0; i < a1.length; i+=1) { + sum += a1[i]; + } + return sum; + } + + static void test_addc(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]+VALUE); + } + } + static void test_addv(byte[] a0, byte[] a1, byte b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]+b); + } + } + static void test_adda(byte[] a0, byte[] a1, byte[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]+a2[i]); + } + } + + static void test_subc(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]-VALUE); + } + } + static void test_subv(byte[] a0, byte[] a1, byte b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]-b); + } + } + static void test_suba(byte[] a0, byte[] a1, byte[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]-a2[i]); + } + } + + static void test_mulc(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]*VALUE); + } + } + static void test_mulc_n(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]*(-VALUE)); + } + } + static void test_mulv(byte[] a0, byte[] a1, byte b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]*b); + } + } + static void test_mula(byte[] a0, byte[] a1, byte[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]*a2[i]); + } + } + + static void test_divc(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]/VALUE); + } + } + static void test_divc_n(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]/(-VALUE)); + } + } + static void test_divv(byte[] a0, byte[] a1, byte b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]/b); + } + } + static void test_diva(byte[] a0, byte[] a1, byte[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]/a2[i]); + } + } + + static void test_andc(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]&BIT_MASK); + } + } + static void test_andv(byte[] a0, byte[] a1, byte b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]&b); + } + } + static void test_anda(byte[] a0, byte[] a1, byte[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]&a2[i]); + } + } + + static void test_orc(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]|BIT_MASK); + } + } + static void test_orv(byte[] a0, byte[] a1, byte b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]|b); + } + } + static void test_ora(byte[] a0, byte[] a1, byte[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]|a2[i]); + } + } + + static void test_xorc(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]^BIT_MASK); + } + } + static void test_xorv(byte[] a0, byte[] a1, byte b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]^b); + } + } + static void test_xora(byte[] a0, byte[] a1, byte[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]^a2[i]); + } + } + + static void test_sllc(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]<<VALUE); + } + } + static void test_sllc_n(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]<<(-VALUE)); + } + } + static void test_sllc_o(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]<<SHIFT); + } + } + static void test_sllc_on(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]<<(-SHIFT)); + } + } + static void test_sllv(byte[] a0, byte[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]<<b); + } + } + + static void test_srlc(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]>>>VALUE); + } + } + static void test_srlc_n(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]>>>(-VALUE)); + } + } + static void test_srlc_o(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]>>>SHIFT); + } + } + static void test_srlc_on(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]>>>(-SHIFT)); + } + } + static void test_srlv(byte[] a0, byte[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]>>>b); + } + } + + static void test_srac(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]>>VALUE); + } + } + static void test_srac_n(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]>>(-VALUE)); + } + } + static void test_srac_o(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]>>SHIFT); + } + } + static void test_srac_on(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]>>(-SHIFT)); + } + } + static void test_srav(byte[] a0, byte[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]>>b); + } + } + + static void test_pack2(short[] p2, byte[] a1) { + if (p2.length*2 > a1.length) return; + for (int i = 0; i < p2.length; i+=1) { + short l0 = (short)a1[i*2+0]; + short l1 = (short)a1[i*2+1]; + p2[i] = (short)((l1 << 8) | (l0 & 0xFF)); + } + } + static void test_unpack2(byte[] a0, short[] p2) { + if (p2.length*2 > a0.length) return; + for (int i = 0; i < p2.length; i+=1) { + short l = p2[i]; + a0[i*2+0] = (byte)(l & 0xFF); + a0[i*2+1] = (byte)(l >> 8); + } + } + static void test_pack2_swap(short[] p2, byte[] a1) { + if (p2.length*2 > a1.length) return; + for (int i = 0; i < p2.length; i+=1) { + short l0 = (short)a1[i*2+0]; + short l1 = (short)a1[i*2+1]; + p2[i] = (short)((l0 << 8) | (l1 & 0xFF)); + } + } + static void test_unpack2_swap(byte[] a0, short[] p2) { + if (p2.length*2 > a0.length) return; + for (int i = 0; i < p2.length; i+=1) { + short l = p2[i]; + a0[i*2+0] = (byte)(l >> 8); + a0[i*2+1] = (byte)(l & 0xFF); + } + } + + static void test_pack4(int[] p4, byte[] a1) { + if (p4.length*4 > a1.length) return; + for (int i = 0; i < p4.length; i+=1) { + int l0 = (int)a1[i*4+0]; + int l1 = (int)a1[i*4+1]; + int l2 = (int)a1[i*4+2]; + int l3 = (int)a1[i*4+3]; + p4[i] = (l0 & 0xFF) | + ((l1 & 0xFF) << 8) | + ((l2 & 0xFF) << 16) | + ((l3 & 0xFF) << 24); + } + } + static void test_unpack4(byte[] a0, int[] p4) { + if (p4.length*4 > a0.length) return; + for (int i = 0; i < p4.length; i+=1) { + int l = p4[i]; + a0[i*4+0] = (byte)(l & 0xFF); + a0[i*4+1] = (byte)(l >> 8); + a0[i*4+2] = (byte)(l >> 16); + a0[i*4+3] = (byte)(l >> 24); + } + } + static void test_pack4_swap(int[] p4, byte[] a1) { + if (p4.length*4 > a1.length) return; + for (int i = 0; i < p4.length; i+=1) { + int l0 = (int)a1[i*4+0]; + int l1 = (int)a1[i*4+1]; + int l2 = (int)a1[i*4+2]; + int l3 = (int)a1[i*4+3]; + p4[i] = (l3 & 0xFF) | + ((l2 & 0xFF) << 8) | + ((l1 & 0xFF) << 16) | + ((l0 & 0xFF) << 24); + } + } + static void test_unpack4_swap(byte[] a0, int[] p4) { + if (p4.length*4 > a0.length) return; + for (int i = 0; i < p4.length; i+=1) { + int l = p4[i]; + a0[i*4+0] = (byte)(l >> 24); + a0[i*4+1] = (byte)(l >> 16); + a0[i*4+2] = (byte)(l >> 8); + a0[i*4+3] = (byte)(l & 0xFF); + } + } + + static void test_pack8(long[] p8, byte[] a1) { + if (p8.length*8 > a1.length) return; + for (int i = 0; i < p8.length; i+=1) { + long l0 = (long)a1[i*8+0]; + long l1 = (long)a1[i*8+1]; + long l2 = (long)a1[i*8+2]; + long l3 = (long)a1[i*8+3]; + long l4 = (long)a1[i*8+4]; + long l5 = (long)a1[i*8+5]; + long l6 = (long)a1[i*8+6]; + long l7 = (long)a1[i*8+7]; + p8[i] = (l0 & 0xFFl) | + ((l1 & 0xFFl) << 8) | + ((l2 & 0xFFl) << 16) | + ((l3 & 0xFFl) << 24) | + ((l4 & 0xFFl) << 32) | + ((l5 & 0xFFl) << 40) | + ((l6 & 0xFFl) << 48) | + ((l7 & 0xFFl) << 56); + } + } + static void test_unpack8(byte[] a0, long[] p8) { + if (p8.length*8 > a0.length) return; + for (int i = 0; i < p8.length; i+=1) { + long l = p8[i]; + a0[i*8+0] = (byte)(l & 0xFFl); + a0[i*8+1] = (byte)(l >> 8); + a0[i*8+2] = (byte)(l >> 16); + a0[i*8+3] = (byte)(l >> 24); + a0[i*8+4] = (byte)(l >> 32); + a0[i*8+5] = (byte)(l >> 40); + a0[i*8+6] = (byte)(l >> 48); + a0[i*8+7] = (byte)(l >> 56); + } + } + static void test_pack8_swap(long[] p8, byte[] a1) { + if (p8.length*8 > a1.length) return; + for (int i = 0; i < p8.length; i+=1) { + long l0 = (long)a1[i*8+0]; + long l1 = (long)a1[i*8+1]; + long l2 = (long)a1[i*8+2]; + long l3 = (long)a1[i*8+3]; + long l4 = (long)a1[i*8+4]; + long l5 = (long)a1[i*8+5]; + long l6 = (long)a1[i*8+6]; + long l7 = (long)a1[i*8+7]; + p8[i] = (l7 & 0xFFl) | + ((l6 & 0xFFl) << 8) | + ((l5 & 0xFFl) << 16) | + ((l4 & 0xFFl) << 24) | + ((l3 & 0xFFl) << 32) | + ((l2 & 0xFFl) << 40) | + ((l1 & 0xFFl) << 48) | + ((l0 & 0xFFl) << 56); + } + } + static void test_unpack8_swap(byte[] a0, long[] p8) { + if (p8.length*8 > a0.length) return; + for (int i = 0; i < p8.length; i+=1) { + long l = p8[i]; + a0[i*8+0] = (byte)(l >> 56); + a0[i*8+1] = (byte)(l >> 48); + a0[i*8+2] = (byte)(l >> 40); + a0[i*8+3] = (byte)(l >> 32); + a0[i*8+4] = (byte)(l >> 24); + a0[i*8+5] = (byte)(l >> 16); + a0[i*8+6] = (byte)(l >> 8); + a0[i*8+7] = (byte)(l & 0xFFl); + } + } + + static int verify(String text, int i, byte elem, byte val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } + + static int verify(String text, int i, short elem, short val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } + + static int verify(String text, int i, int elem, int val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + Integer.toHexString(elem) + " != " + Integer.toHexString(val)); + return 1; + } + return 0; + } + + static int verify(String text, int i, long elem, long val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + Long.toHexString(elem) + " != " + Long.toHexString(val)); + return 1; + } + return 0; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6340864/TestDoubleVect.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,560 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 6340864 + * @summary Implement vectorization optimizations in hotspot-server + * + * @run main/othervm/timeout=400 -Xbatch -Xmx64m TestDoubleVect + */ + +public class TestDoubleVect { + private static final int ARRLEN = 997; + private static final int ITERS = 11000; + private static final double ADD_INIT = -7500.; + private static final double VALUE = 15.; + + public static void main(String args[]) { + System.out.println("Testing Double vectors"); + int errn = test(); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test() { + double[] a0 = new double[ARRLEN]; + double[] a1 = new double[ARRLEN]; + double[] a2 = new double[ARRLEN]; + double[] a3 = new double[ARRLEN]; + // Initialize + double gold_sum = 0; + for (int i=0; i<ARRLEN; i++) { + double val = ADD_INIT+(double)i; + gold_sum += val; + a1[i] = val; + a2[i] = VALUE; + a3[i] = -VALUE; + } + + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_sum(a1); + test_addc(a0, a1); + test_addv(a0, a1, VALUE); + test_adda(a0, a1, a2); + test_subc(a0, a1); + test_subv(a0, a1, VALUE); + test_suba(a0, a1, a2); + test_mulc(a0, a1); + test_mulv(a0, a1, VALUE); + test_mula(a0, a1, a2); + test_divc(a0, a1); + test_divv(a0, a1, VALUE); + test_diva(a0, a1, a2); + test_mulc_n(a0, a1); + test_mulv(a0, a1, -VALUE); + test_mula(a0, a1, a3); + test_divc_n(a0, a1); + test_divv(a0, a1, -VALUE); + test_diva(a0, a1, a3); + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + double sum = test_sum(a1); + if (sum != gold_sum) { + System.err.println("test_sum: " + sum + " != " + gold_sum); + errn++; + } + // Overwrite with NaN values + a1[0] = Double.NaN; + a1[1] = Double.POSITIVE_INFINITY; + a1[2] = Double.NEGATIVE_INFINITY; + a1[3] = Double.MAX_VALUE; + a1[4] = Double.MIN_VALUE; + a1[5] = Double.MIN_NORMAL; + + a2[6] = a1[0]; + a2[7] = a1[1]; + a2[8] = a1[2]; + a2[9] = a1[3]; + a2[10] = a1[4]; + a2[11] = a1[5]; + + a3[6] = -a2[6]; + a3[7] = -a2[7]; + a3[8] = -a2[8]; + a3[9] = -a2[9]; + a3[10] = -a2[10]; + a3[11] = -a2[11]; + + test_addc(a0, a1); + errn += verify("test_addc: ", 0, a0[0], (Double.NaN+VALUE)); + errn += verify("test_addc: ", 1, a0[1], (Double.POSITIVE_INFINITY+VALUE)); + errn += verify("test_addc: ", 2, a0[2], (Double.NEGATIVE_INFINITY+VALUE)); + errn += verify("test_addc: ", 3, a0[3], (Double.MAX_VALUE+VALUE)); + errn += verify("test_addc: ", 4, a0[4], (Double.MIN_VALUE+VALUE)); + errn += verify("test_addc: ", 5, a0[5], (Double.MIN_NORMAL+VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_addc: ", i, a0[i], ((ADD_INIT+i)+VALUE)); + } + test_addv(a0, a1, VALUE); + errn += verify("test_addv: ", 0, a0[0], (Double.NaN+VALUE)); + errn += verify("test_addv: ", 1, a0[1], (Double.POSITIVE_INFINITY+VALUE)); + errn += verify("test_addv: ", 2, a0[2], (Double.NEGATIVE_INFINITY+VALUE)); + errn += verify("test_addv: ", 3, a0[3], (Double.MAX_VALUE+VALUE)); + errn += verify("test_addv: ", 4, a0[4], (Double.MIN_VALUE+VALUE)); + errn += verify("test_addv: ", 5, a0[5], (Double.MIN_NORMAL+VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_addv: ", i, a0[i], ((ADD_INIT+i)+VALUE)); + } + test_adda(a0, a1, a2); + errn += verify("test_adda: ", 0, a0[0], (Double.NaN+VALUE)); + errn += verify("test_adda: ", 1, a0[1], (Double.POSITIVE_INFINITY+VALUE)); + errn += verify("test_adda: ", 2, a0[2], (Double.NEGATIVE_INFINITY+VALUE)); + errn += verify("test_adda: ", 3, a0[3], (Double.MAX_VALUE+VALUE)); + errn += verify("test_adda: ", 4, a0[4], (Double.MIN_VALUE+VALUE)); + errn += verify("test_adda: ", 5, a0[5], (Double.MIN_NORMAL+VALUE)); + errn += verify("test_adda: ", 6, a0[6], ((ADD_INIT+6)+Double.NaN)); + errn += verify("test_adda: ", 7, a0[7], ((ADD_INIT+7)+Double.POSITIVE_INFINITY)); + errn += verify("test_adda: ", 8, a0[8], ((ADD_INIT+8)+Double.NEGATIVE_INFINITY)); + errn += verify("test_adda: ", 9, a0[9], ((ADD_INIT+9)+Double.MAX_VALUE)); + errn += verify("test_adda: ", 10, a0[10], ((ADD_INIT+10)+Double.MIN_VALUE)); + errn += verify("test_adda: ", 11, a0[11], ((ADD_INIT+11)+Double.MIN_NORMAL)); + for (int i=12; i<ARRLEN; i++) { + errn += verify("test_adda: ", i, a0[i], ((ADD_INIT+i)+VALUE)); + } + + test_subc(a0, a1); + errn += verify("test_subc: ", 0, a0[0], (Double.NaN-VALUE)); + errn += verify("test_subc: ", 1, a0[1], (Double.POSITIVE_INFINITY-VALUE)); + errn += verify("test_subc: ", 2, a0[2], (Double.NEGATIVE_INFINITY-VALUE)); + errn += verify("test_subc: ", 3, a0[3], (Double.MAX_VALUE-VALUE)); + errn += verify("test_subc: ", 4, a0[4], (Double.MIN_VALUE-VALUE)); + errn += verify("test_subc: ", 5, a0[5], (Double.MIN_NORMAL-VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_subc: ", i, a0[i], ((ADD_INIT+i)-VALUE)); + } + test_subv(a0, a1, VALUE); + errn += verify("test_subv: ", 0, a0[0], (Double.NaN-VALUE)); + errn += verify("test_subv: ", 1, a0[1], (Double.POSITIVE_INFINITY-VALUE)); + errn += verify("test_subv: ", 2, a0[2], (Double.NEGATIVE_INFINITY-VALUE)); + errn += verify("test_subv: ", 3, a0[3], (Double.MAX_VALUE-VALUE)); + errn += verify("test_subv: ", 4, a0[4], (Double.MIN_VALUE-VALUE)); + errn += verify("test_subv: ", 5, a0[5], (Double.MIN_NORMAL-VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_subv: ", i, a0[i], ((ADD_INIT+i)-VALUE)); + } + test_suba(a0, a1, a2); + errn += verify("test_suba: ", 0, a0[0], (Double.NaN-VALUE)); + errn += verify("test_suba: ", 1, a0[1], (Double.POSITIVE_INFINITY-VALUE)); + errn += verify("test_suba: ", 2, a0[2], (Double.NEGATIVE_INFINITY-VALUE)); + errn += verify("test_suba: ", 3, a0[3], (Double.MAX_VALUE-VALUE)); + errn += verify("test_suba: ", 4, a0[4], (Double.MIN_VALUE-VALUE)); + errn += verify("test_suba: ", 5, a0[5], (Double.MIN_NORMAL-VALUE)); + errn += verify("test_suba: ", 6, a0[6], ((ADD_INIT+6)-Double.NaN)); + errn += verify("test_suba: ", 7, a0[7], ((ADD_INIT+7)-Double.POSITIVE_INFINITY)); + errn += verify("test_suba: ", 8, a0[8], ((ADD_INIT+8)-Double.NEGATIVE_INFINITY)); + errn += verify("test_suba: ", 9, a0[9], ((ADD_INIT+9)-Double.MAX_VALUE)); + errn += verify("test_suba: ", 10, a0[10], ((ADD_INIT+10)-Double.MIN_VALUE)); + errn += verify("test_suba: ", 11, a0[11], ((ADD_INIT+11)-Double.MIN_NORMAL)); + for (int i=12; i<ARRLEN; i++) { + errn += verify("test_suba: ", i, a0[i], ((ADD_INIT+i)-VALUE)); + } + + test_mulc(a0, a1); + errn += verify("test_mulc: ", 0, a0[0], (Double.NaN*VALUE)); + errn += verify("test_mulc: ", 1, a0[1], (Double.POSITIVE_INFINITY*VALUE)); + errn += verify("test_mulc: ", 2, a0[2], (Double.NEGATIVE_INFINITY*VALUE)); + errn += verify("test_mulc: ", 3, a0[3], (Double.MAX_VALUE*VALUE)); + errn += verify("test_mulc: ", 4, a0[4], (Double.MIN_VALUE*VALUE)); + errn += verify("test_mulc: ", 5, a0[5], (Double.MIN_NORMAL*VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_mulc: ", i, a0[i], ((ADD_INIT+i)*VALUE)); + } + test_mulv(a0, a1, VALUE); + errn += verify("test_mulv: ", 0, a0[0], (Double.NaN*VALUE)); + errn += verify("test_mulv: ", 1, a0[1], (Double.POSITIVE_INFINITY*VALUE)); + errn += verify("test_mulv: ", 2, a0[2], (Double.NEGATIVE_INFINITY*VALUE)); + errn += verify("test_mulv: ", 3, a0[3], (Double.MAX_VALUE*VALUE)); + errn += verify("test_mulv: ", 4, a0[4], (Double.MIN_VALUE*VALUE)); + errn += verify("test_mulv: ", 5, a0[5], (Double.MIN_NORMAL*VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_mulv: ", i, a0[i], ((ADD_INIT+i)*VALUE)); + } + test_mula(a0, a1, a2); + errn += verify("test_mula: ", 0, a0[0], (Double.NaN*VALUE)); + errn += verify("test_mula: ", 1, a0[1], (Double.POSITIVE_INFINITY*VALUE)); + errn += verify("test_mula: ", 2, a0[2], (Double.NEGATIVE_INFINITY*VALUE)); + errn += verify("test_mula: ", 3, a0[3], (Double.MAX_VALUE*VALUE)); + errn += verify("test_mula: ", 4, a0[4], (Double.MIN_VALUE*VALUE)); + errn += verify("test_mula: ", 5, a0[5], (Double.MIN_NORMAL*VALUE)); + errn += verify("test_mula: ", 6, a0[6], ((ADD_INIT+6)*Double.NaN)); + errn += verify("test_mula: ", 7, a0[7], ((ADD_INIT+7)*Double.POSITIVE_INFINITY)); + errn += verify("test_mula: ", 8, a0[8], ((ADD_INIT+8)*Double.NEGATIVE_INFINITY)); + errn += verify("test_mula: ", 9, a0[9], ((ADD_INIT+9)*Double.MAX_VALUE)); + errn += verify("test_mula: ", 10, a0[10], ((ADD_INIT+10)*Double.MIN_VALUE)); + errn += verify("test_mula: ", 11, a0[11], ((ADD_INIT+11)*Double.MIN_NORMAL)); + for (int i=12; i<ARRLEN; i++) { + errn += verify("test_mula: ", i, a0[i], ((ADD_INIT+i)*VALUE)); + } + + test_divc(a0, a1); + errn += verify("test_divc: ", 0, a0[0], (Double.NaN/VALUE)); + errn += verify("test_divc: ", 1, a0[1], (Double.POSITIVE_INFINITY/VALUE)); + errn += verify("test_divc: ", 2, a0[2], (Double.NEGATIVE_INFINITY/VALUE)); + errn += verify("test_divc: ", 3, a0[3], (Double.MAX_VALUE/VALUE)); + errn += verify("test_divc: ", 4, a0[4], (Double.MIN_VALUE/VALUE)); + errn += verify("test_divc: ", 5, a0[5], (Double.MIN_NORMAL/VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_divc: ", i, a0[i], ((ADD_INIT+i)/VALUE)); + } + test_divv(a0, a1, VALUE); + errn += verify("test_divv: ", 0, a0[0], (Double.NaN/VALUE)); + errn += verify("test_divv: ", 1, a0[1], (Double.POSITIVE_INFINITY/VALUE)); + errn += verify("test_divv: ", 2, a0[2], (Double.NEGATIVE_INFINITY/VALUE)); + errn += verify("test_divv: ", 3, a0[3], (Double.MAX_VALUE/VALUE)); + errn += verify("test_divv: ", 4, a0[4], (Double.MIN_VALUE/VALUE)); + errn += verify("test_divv: ", 5, a0[5], (Double.MIN_NORMAL/VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_divv: ", i, a0[i], ((ADD_INIT+i)/VALUE)); + } + test_diva(a0, a1, a2); + errn += verify("test_diva: ", 0, a0[0], (Double.NaN/VALUE)); + errn += verify("test_diva: ", 1, a0[1], (Double.POSITIVE_INFINITY/VALUE)); + errn += verify("test_diva: ", 2, a0[2], (Double.NEGATIVE_INFINITY/VALUE)); + errn += verify("test_diva: ", 3, a0[3], (Double.MAX_VALUE/VALUE)); + errn += verify("test_diva: ", 4, a0[4], (Double.MIN_VALUE/VALUE)); + errn += verify("test_diva: ", 5, a0[5], (Double.MIN_NORMAL/VALUE)); + errn += verify("test_diva: ", 6, a0[6], ((ADD_INIT+6)/Double.NaN)); + errn += verify("test_diva: ", 7, a0[7], ((ADD_INIT+7)/Double.POSITIVE_INFINITY)); + errn += verify("test_diva: ", 8, a0[8], ((ADD_INIT+8)/Double.NEGATIVE_INFINITY)); + errn += verify("test_diva: ", 9, a0[9], ((ADD_INIT+9)/Double.MAX_VALUE)); + errn += verify("test_diva: ", 10, a0[10], ((ADD_INIT+10)/Double.MIN_VALUE)); + errn += verify("test_diva: ", 11, a0[11], ((ADD_INIT+11)/Double.MIN_NORMAL)); + for (int i=12; i<ARRLEN; i++) { + errn += verify("test_diva: ", i, a0[i], ((ADD_INIT+i)/VALUE)); + } + + test_mulc_n(a0, a1); + errn += verify("test_mulc_n: ", 0, a0[0], (Double.NaN*(-VALUE))); + errn += verify("test_mulc_n: ", 1, a0[1], (Double.POSITIVE_INFINITY*(-VALUE))); + errn += verify("test_mulc_n: ", 2, a0[2], (Double.NEGATIVE_INFINITY*(-VALUE))); + errn += verify("test_mulc_n: ", 3, a0[3], (Double.MAX_VALUE*(-VALUE))); + errn += verify("test_mulc_n: ", 4, a0[4], (Double.MIN_VALUE*(-VALUE))); + errn += verify("test_mulc_n: ", 5, a0[5], (Double.MIN_NORMAL*(-VALUE))); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_mulc_n: ", i, a0[i], ((ADD_INIT+i)*(-VALUE))); + } + test_mulv(a0, a1, -VALUE); + errn += verify("test_mulv_n: ", 0, a0[0], (Double.NaN*(-VALUE))); + errn += verify("test_mulv_n: ", 1, a0[1], (Double.POSITIVE_INFINITY*(-VALUE))); + errn += verify("test_mulv_n: ", 2, a0[2], (Double.NEGATIVE_INFINITY*(-VALUE))); + errn += verify("test_mulv_n: ", 3, a0[3], (Double.MAX_VALUE*(-VALUE))); + errn += verify("test_mulv_n: ", 4, a0[4], (Double.MIN_VALUE*(-VALUE))); + errn += verify("test_mulv_n: ", 5, a0[5], (Double.MIN_NORMAL*(-VALUE))); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_mulv_n: ", i, a0[i], ((ADD_INIT+i)*(-VALUE))); + } + test_mula(a0, a1, a3); + errn += verify("test_mula_n: ", 0, a0[0], (Double.NaN*(-VALUE))); + errn += verify("test_mula_n: ", 1, a0[1], (Double.POSITIVE_INFINITY*(-VALUE))); + errn += verify("test_mula_n: ", 2, a0[2], (Double.NEGATIVE_INFINITY*(-VALUE))); + errn += verify("test_mula_n: ", 3, a0[3], (Double.MAX_VALUE*(-VALUE))); + errn += verify("test_mula_n: ", 4, a0[4], (Double.MIN_VALUE*(-VALUE))); + errn += verify("test_mula_n: ", 5, a0[5], (Double.MIN_NORMAL*(-VALUE))); + errn += verify("test_mula_n: ", 6, a0[6], ((ADD_INIT+6)*(-Double.NaN))); + errn += verify("test_mula_n: ", 7, a0[7], ((ADD_INIT+7)*(-Double.POSITIVE_INFINITY))); + errn += verify("test_mula_n: ", 8, a0[8], ((ADD_INIT+8)*(-Double.NEGATIVE_INFINITY))); + errn += verify("test_mula_n: ", 9, a0[9], ((ADD_INIT+9)*(-Double.MAX_VALUE))); + errn += verify("test_mula_n: ", 10, a0[10], ((ADD_INIT+10)*(-Double.MIN_VALUE))); + errn += verify("test_mula_n: ", 11, a0[11], ((ADD_INIT+11)*(-Double.MIN_NORMAL))); + for (int i=12; i<ARRLEN; i++) { + errn += verify("test_mula_n: ", i, a0[i], ((ADD_INIT+i)*(-VALUE))); + } + + test_divc_n(a0, a1); + errn += verify("test_divc_n: ", 0, a0[0], (Double.NaN/(-VALUE))); + errn += verify("test_divc_n: ", 1, a0[1], (Double.POSITIVE_INFINITY/(-VALUE))); + errn += verify("test_divc_n: ", 2, a0[2], (Double.NEGATIVE_INFINITY/(-VALUE))); + errn += verify("test_divc_n: ", 3, a0[3], (Double.MAX_VALUE/(-VALUE))); + errn += verify("test_divc_n: ", 4, a0[4], (Double.MIN_VALUE/(-VALUE))); + errn += verify("test_divc_n: ", 5, a0[5], (Double.MIN_NORMAL/(-VALUE))); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_divc_n: ", i, a0[i], ((ADD_INIT+i)/(-VALUE))); + } + test_divv(a0, a1, -VALUE); + errn += verify("test_divv_n: ", 0, a0[0], (Double.NaN/(-VALUE))); + errn += verify("test_divv_n: ", 1, a0[1], (Double.POSITIVE_INFINITY/(-VALUE))); + errn += verify("test_divv_n: ", 2, a0[2], (Double.NEGATIVE_INFINITY/(-VALUE))); + errn += verify("test_divv_n: ", 3, a0[3], (Double.MAX_VALUE/(-VALUE))); + errn += verify("test_divv_n: ", 4, a0[4], (Double.MIN_VALUE/(-VALUE))); + errn += verify("test_divv_n: ", 5, a0[5], (Double.MIN_NORMAL/(-VALUE))); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_divv_n: ", i, a0[i], ((ADD_INIT+i)/(-VALUE))); + } + test_diva(a0, a1, a3); + errn += verify("test_diva_n: ", 0, a0[0], (Double.NaN/(-VALUE))); + errn += verify("test_diva_n: ", 1, a0[1], (Double.POSITIVE_INFINITY/(-VALUE))); + errn += verify("test_diva_n: ", 2, a0[2], (Double.NEGATIVE_INFINITY/(-VALUE))); + errn += verify("test_diva_n: ", 3, a0[3], (Double.MAX_VALUE/(-VALUE))); + errn += verify("test_diva_n: ", 4, a0[4], (Double.MIN_VALUE/(-VALUE))); + errn += verify("test_diva_n: ", 5, a0[5], (Double.MIN_NORMAL/(-VALUE))); + errn += verify("test_diva_n: ", 6, a0[6], ((ADD_INIT+6)/(-Double.NaN))); + errn += verify("test_diva_n: ", 7, a0[7], ((ADD_INIT+7)/(-Double.POSITIVE_INFINITY))); + errn += verify("test_diva_n: ", 8, a0[8], ((ADD_INIT+8)/(-Double.NEGATIVE_INFINITY))); + errn += verify("test_diva_n: ", 9, a0[9], ((ADD_INIT+9)/(-Double.MAX_VALUE))); + errn += verify("test_diva_n: ", 10, a0[10], ((ADD_INIT+10)/(-Double.MIN_VALUE))); + errn += verify("test_diva_n: ", 11, a0[11], ((ADD_INIT+11)/(-Double.MIN_NORMAL))); + for (int i=12; i<ARRLEN; i++) { + errn += verify("test_diva_n: ", i, a0[i], ((ADD_INIT+i)/(-VALUE))); + } + + } + + if (errn > 0) + return errn; + + System.out.println("Time"); + long start, end; + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sum(a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sum: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_addc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_addv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_adda(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_adda: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_subc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_subc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_subv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_subv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_suba(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_suba: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_mulc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_mulv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mula(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_mula: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_divc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_divv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_diva(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_diva: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_mulc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulv(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_mulv_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mula(a0, a1, a3); + } + end = System.currentTimeMillis(); + System.out.println("test_mula_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_divc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divv(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_divv_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_diva(a0, a1, a3); + } + end = System.currentTimeMillis(); + System.out.println("test_diva_n: " + (end - start)); + + return errn; + } + + static double test_sum(double[] a1) { + double sum = 0; + for (int i = 0; i < a1.length; i+=1) { + sum += a1[i]; + } + return sum; + } + + static void test_addc(double[] a0, double[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]+VALUE); + } + } + static void test_addv(double[] a0, double[] a1, double b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]+b); + } + } + static void test_adda(double[] a0, double[] a1, double[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]+a2[i]); + } + } + + static void test_subc(double[] a0, double[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]-VALUE); + } + } + static void test_subv(double[] a0, double[] a1, double b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]-b); + } + } + static void test_suba(double[] a0, double[] a1, double[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]-a2[i]); + } + } + + static void test_mulc(double[] a0, double[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]*VALUE); + } + } + static void test_mulc_n(double[] a0, double[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]*(-VALUE)); + } + } + static void test_mulv(double[] a0, double[] a1, double b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]*b); + } + } + static void test_mula(double[] a0, double[] a1, double[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]*a2[i]); + } + } + + static void test_divc(double[] a0, double[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]/VALUE); + } + } + static void test_divc_n(double[] a0, double[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]/(-VALUE)); + } + } + static void test_divv(double[] a0, double[] a1, double b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]/b); + } + } + static void test_diva(double[] a0, double[] a1, double[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]/a2[i]); + } + } + + static int verify(String text, int i, double elem, double val) { + if (elem != val && !(Double.isNaN(elem) && Double.isNaN(val))) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6340864/TestFloatVect.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,560 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 6340864 + * @summary Implement vectorization optimizations in hotspot-server + * + * @run main/othervm/timeout=400 -Xbatch -Xmx64m TestFloatVect + */ + +public class TestFloatVect { + private static final int ARRLEN = 997; + private static final int ITERS = 11000; + private static final float ADD_INIT = -7500.f; + private static final float VALUE = 15.f; + + public static void main(String args[]) { + System.out.println("Testing Float vectors"); + int errn = test(); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test() { + float[] a0 = new float[ARRLEN]; + float[] a1 = new float[ARRLEN]; + float[] a2 = new float[ARRLEN]; + float[] a3 = new float[ARRLEN]; + // Initialize + float gold_sum = 0; + for (int i=0; i<ARRLEN; i++) { + float val = ADD_INIT+(float)i; + gold_sum += val; + a1[i] = val; + a2[i] = VALUE; + a3[i] = -VALUE; + } + + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_sum(a1); + test_addc(a0, a1); + test_addv(a0, a1, VALUE); + test_adda(a0, a1, a2); + test_subc(a0, a1); + test_subv(a0, a1, VALUE); + test_suba(a0, a1, a2); + test_mulc(a0, a1); + test_mulv(a0, a1, VALUE); + test_mula(a0, a1, a2); + test_divc(a0, a1); + test_divv(a0, a1, VALUE); + test_diva(a0, a1, a2); + test_mulc_n(a0, a1); + test_mulv(a0, a1, -VALUE); + test_mula(a0, a1, a3); + test_divc_n(a0, a1); + test_divv(a0, a1, -VALUE); + test_diva(a0, a1, a3); + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + float sum = test_sum(a1); + if (sum != gold_sum) { + System.err.println("test_sum: " + sum + " != " + gold_sum); + errn++; + } + // Overwrite with NaN values + a1[0] = Float.NaN; + a1[1] = Float.POSITIVE_INFINITY; + a1[2] = Float.NEGATIVE_INFINITY; + a1[3] = Float.MAX_VALUE; + a1[4] = Float.MIN_VALUE; + a1[5] = Float.MIN_NORMAL; + + a2[6] = a1[0]; + a2[7] = a1[1]; + a2[8] = a1[2]; + a2[9] = a1[3]; + a2[10] = a1[4]; + a2[11] = a1[5]; + + a3[6] = -a2[6]; + a3[7] = -a2[7]; + a3[8] = -a2[8]; + a3[9] = -a2[9]; + a3[10] = -a2[10]; + a3[11] = -a2[11]; + + test_addc(a0, a1); + errn += verify("test_addc: ", 0, a0[0], (Float.NaN+VALUE)); + errn += verify("test_addc: ", 1, a0[1], (Float.POSITIVE_INFINITY+VALUE)); + errn += verify("test_addc: ", 2, a0[2], (Float.NEGATIVE_INFINITY+VALUE)); + errn += verify("test_addc: ", 3, a0[3], (Float.MAX_VALUE+VALUE)); + errn += verify("test_addc: ", 4, a0[4], (Float.MIN_VALUE+VALUE)); + errn += verify("test_addc: ", 5, a0[5], (Float.MIN_NORMAL+VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_addc: ", i, a0[i], ((ADD_INIT+i)+VALUE)); + } + test_addv(a0, a1, VALUE); + errn += verify("test_addv: ", 0, a0[0], (Float.NaN+VALUE)); + errn += verify("test_addv: ", 1, a0[1], (Float.POSITIVE_INFINITY+VALUE)); + errn += verify("test_addv: ", 2, a0[2], (Float.NEGATIVE_INFINITY+VALUE)); + errn += verify("test_addv: ", 3, a0[3], (Float.MAX_VALUE+VALUE)); + errn += verify("test_addv: ", 4, a0[4], (Float.MIN_VALUE+VALUE)); + errn += verify("test_addv: ", 5, a0[5], (Float.MIN_NORMAL+VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_addv: ", i, a0[i], ((ADD_INIT+i)+VALUE)); + } + test_adda(a0, a1, a2); + errn += verify("test_adda: ", 0, a0[0], (Float.NaN+VALUE)); + errn += verify("test_adda: ", 1, a0[1], (Float.POSITIVE_INFINITY+VALUE)); + errn += verify("test_adda: ", 2, a0[2], (Float.NEGATIVE_INFINITY+VALUE)); + errn += verify("test_adda: ", 3, a0[3], (Float.MAX_VALUE+VALUE)); + errn += verify("test_adda: ", 4, a0[4], (Float.MIN_VALUE+VALUE)); + errn += verify("test_adda: ", 5, a0[5], (Float.MIN_NORMAL+VALUE)); + errn += verify("test_adda: ", 6, a0[6], ((ADD_INIT+6)+Float.NaN)); + errn += verify("test_adda: ", 7, a0[7], ((ADD_INIT+7)+Float.POSITIVE_INFINITY)); + errn += verify("test_adda: ", 8, a0[8], ((ADD_INIT+8)+Float.NEGATIVE_INFINITY)); + errn += verify("test_adda: ", 9, a0[9], ((ADD_INIT+9)+Float.MAX_VALUE)); + errn += verify("test_adda: ", 10, a0[10], ((ADD_INIT+10)+Float.MIN_VALUE)); + errn += verify("test_adda: ", 11, a0[11], ((ADD_INIT+11)+Float.MIN_NORMAL)); + for (int i=12; i<ARRLEN; i++) { + errn += verify("test_adda: ", i, a0[i], ((ADD_INIT+i)+VALUE)); + } + + test_subc(a0, a1); + errn += verify("test_subc: ", 0, a0[0], (Float.NaN-VALUE)); + errn += verify("test_subc: ", 1, a0[1], (Float.POSITIVE_INFINITY-VALUE)); + errn += verify("test_subc: ", 2, a0[2], (Float.NEGATIVE_INFINITY-VALUE)); + errn += verify("test_subc: ", 3, a0[3], (Float.MAX_VALUE-VALUE)); + errn += verify("test_subc: ", 4, a0[4], (Float.MIN_VALUE-VALUE)); + errn += verify("test_subc: ", 5, a0[5], (Float.MIN_NORMAL-VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_subc: ", i, a0[i], ((ADD_INIT+i)-VALUE)); + } + test_subv(a0, a1, VALUE); + errn += verify("test_subv: ", 0, a0[0], (Float.NaN-VALUE)); + errn += verify("test_subv: ", 1, a0[1], (Float.POSITIVE_INFINITY-VALUE)); + errn += verify("test_subv: ", 2, a0[2], (Float.NEGATIVE_INFINITY-VALUE)); + errn += verify("test_subv: ", 3, a0[3], (Float.MAX_VALUE-VALUE)); + errn += verify("test_subv: ", 4, a0[4], (Float.MIN_VALUE-VALUE)); + errn += verify("test_subv: ", 5, a0[5], (Float.MIN_NORMAL-VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_subv: ", i, a0[i], ((ADD_INIT+i)-VALUE)); + } + test_suba(a0, a1, a2); + errn += verify("test_suba: ", 0, a0[0], (Float.NaN-VALUE)); + errn += verify("test_suba: ", 1, a0[1], (Float.POSITIVE_INFINITY-VALUE)); + errn += verify("test_suba: ", 2, a0[2], (Float.NEGATIVE_INFINITY-VALUE)); + errn += verify("test_suba: ", 3, a0[3], (Float.MAX_VALUE-VALUE)); + errn += verify("test_suba: ", 4, a0[4], (Float.MIN_VALUE-VALUE)); + errn += verify("test_suba: ", 5, a0[5], (Float.MIN_NORMAL-VALUE)); + errn += verify("test_suba: ", 6, a0[6], ((ADD_INIT+6)-Float.NaN)); + errn += verify("test_suba: ", 7, a0[7], ((ADD_INIT+7)-Float.POSITIVE_INFINITY)); + errn += verify("test_suba: ", 8, a0[8], ((ADD_INIT+8)-Float.NEGATIVE_INFINITY)); + errn += verify("test_suba: ", 9, a0[9], ((ADD_INIT+9)-Float.MAX_VALUE)); + errn += verify("test_suba: ", 10, a0[10], ((ADD_INIT+10)-Float.MIN_VALUE)); + errn += verify("test_suba: ", 11, a0[11], ((ADD_INIT+11)-Float.MIN_NORMAL)); + for (int i=12; i<ARRLEN; i++) { + errn += verify("test_suba: ", i, a0[i], ((ADD_INIT+i)-VALUE)); + } + + test_mulc(a0, a1); + errn += verify("test_mulc: ", 0, a0[0], (Float.NaN*VALUE)); + errn += verify("test_mulc: ", 1, a0[1], (Float.POSITIVE_INFINITY*VALUE)); + errn += verify("test_mulc: ", 2, a0[2], (Float.NEGATIVE_INFINITY*VALUE)); + errn += verify("test_mulc: ", 3, a0[3], (Float.MAX_VALUE*VALUE)); + errn += verify("test_mulc: ", 4, a0[4], (Float.MIN_VALUE*VALUE)); + errn += verify("test_mulc: ", 5, a0[5], (Float.MIN_NORMAL*VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_mulc: ", i, a0[i], ((ADD_INIT+i)*VALUE)); + } + test_mulv(a0, a1, VALUE); + errn += verify("test_mulv: ", 0, a0[0], (Float.NaN*VALUE)); + errn += verify("test_mulv: ", 1, a0[1], (Float.POSITIVE_INFINITY*VALUE)); + errn += verify("test_mulv: ", 2, a0[2], (Float.NEGATIVE_INFINITY*VALUE)); + errn += verify("test_mulv: ", 3, a0[3], (Float.MAX_VALUE*VALUE)); + errn += verify("test_mulv: ", 4, a0[4], (Float.MIN_VALUE*VALUE)); + errn += verify("test_mulv: ", 5, a0[5], (Float.MIN_NORMAL*VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_mulv: ", i, a0[i], ((ADD_INIT+i)*VALUE)); + } + test_mula(a0, a1, a2); + errn += verify("test_mula: ", 0, a0[0], (Float.NaN*VALUE)); + errn += verify("test_mula: ", 1, a0[1], (Float.POSITIVE_INFINITY*VALUE)); + errn += verify("test_mula: ", 2, a0[2], (Float.NEGATIVE_INFINITY*VALUE)); + errn += verify("test_mula: ", 3, a0[3], (Float.MAX_VALUE*VALUE)); + errn += verify("test_mula: ", 4, a0[4], (Float.MIN_VALUE*VALUE)); + errn += verify("test_mula: ", 5, a0[5], (Float.MIN_NORMAL*VALUE)); + errn += verify("test_mula: ", 6, a0[6], ((ADD_INIT+6)*Float.NaN)); + errn += verify("test_mula: ", 7, a0[7], ((ADD_INIT+7)*Float.POSITIVE_INFINITY)); + errn += verify("test_mula: ", 8, a0[8], ((ADD_INIT+8)*Float.NEGATIVE_INFINITY)); + errn += verify("test_mula: ", 9, a0[9], ((ADD_INIT+9)*Float.MAX_VALUE)); + errn += verify("test_mula: ", 10, a0[10], ((ADD_INIT+10)*Float.MIN_VALUE)); + errn += verify("test_mula: ", 11, a0[11], ((ADD_INIT+11)*Float.MIN_NORMAL)); + for (int i=12; i<ARRLEN; i++) { + errn += verify("test_mula: ", i, a0[i], ((ADD_INIT+i)*VALUE)); + } + + test_divc(a0, a1); + errn += verify("test_divc: ", 0, a0[0], (Float.NaN/VALUE)); + errn += verify("test_divc: ", 1, a0[1], (Float.POSITIVE_INFINITY/VALUE)); + errn += verify("test_divc: ", 2, a0[2], (Float.NEGATIVE_INFINITY/VALUE)); + errn += verify("test_divc: ", 3, a0[3], (Float.MAX_VALUE/VALUE)); + errn += verify("test_divc: ", 4, a0[4], (Float.MIN_VALUE/VALUE)); + errn += verify("test_divc: ", 5, a0[5], (Float.MIN_NORMAL/VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_divc: ", i, a0[i], ((ADD_INIT+i)/VALUE)); + } + test_divv(a0, a1, VALUE); + errn += verify("test_divv: ", 0, a0[0], (Float.NaN/VALUE)); + errn += verify("test_divv: ", 1, a0[1], (Float.POSITIVE_INFINITY/VALUE)); + errn += verify("test_divv: ", 2, a0[2], (Float.NEGATIVE_INFINITY/VALUE)); + errn += verify("test_divv: ", 3, a0[3], (Float.MAX_VALUE/VALUE)); + errn += verify("test_divv: ", 4, a0[4], (Float.MIN_VALUE/VALUE)); + errn += verify("test_divv: ", 5, a0[5], (Float.MIN_NORMAL/VALUE)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_divv: ", i, a0[i], ((ADD_INIT+i)/VALUE)); + } + test_diva(a0, a1, a2); + errn += verify("test_diva: ", 0, a0[0], (Float.NaN/VALUE)); + errn += verify("test_diva: ", 1, a0[1], (Float.POSITIVE_INFINITY/VALUE)); + errn += verify("test_diva: ", 2, a0[2], (Float.NEGATIVE_INFINITY/VALUE)); + errn += verify("test_diva: ", 3, a0[3], (Float.MAX_VALUE/VALUE)); + errn += verify("test_diva: ", 4, a0[4], (Float.MIN_VALUE/VALUE)); + errn += verify("test_diva: ", 5, a0[5], (Float.MIN_NORMAL/VALUE)); + errn += verify("test_diva: ", 6, a0[6], ((ADD_INIT+6)/Float.NaN)); + errn += verify("test_diva: ", 7, a0[7], ((ADD_INIT+7)/Float.POSITIVE_INFINITY)); + errn += verify("test_diva: ", 8, a0[8], ((ADD_INIT+8)/Float.NEGATIVE_INFINITY)); + errn += verify("test_diva: ", 9, a0[9], ((ADD_INIT+9)/Float.MAX_VALUE)); + errn += verify("test_diva: ", 10, a0[10], ((ADD_INIT+10)/Float.MIN_VALUE)); + errn += verify("test_diva: ", 11, a0[11], ((ADD_INIT+11)/Float.MIN_NORMAL)); + for (int i=12; i<ARRLEN; i++) { + errn += verify("test_diva: ", i, a0[i], ((ADD_INIT+i)/VALUE)); + } + + test_mulc_n(a0, a1); + errn += verify("test_mulc_n: ", 0, a0[0], (Float.NaN*(-VALUE))); + errn += verify("test_mulc_n: ", 1, a0[1], (Float.POSITIVE_INFINITY*(-VALUE))); + errn += verify("test_mulc_n: ", 2, a0[2], (Float.NEGATIVE_INFINITY*(-VALUE))); + errn += verify("test_mulc_n: ", 3, a0[3], (Float.MAX_VALUE*(-VALUE))); + errn += verify("test_mulc_n: ", 4, a0[4], (Float.MIN_VALUE*(-VALUE))); + errn += verify("test_mulc_n: ", 5, a0[5], (Float.MIN_NORMAL*(-VALUE))); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_mulc_n: ", i, a0[i], ((ADD_INIT+i)*(-VALUE))); + } + test_mulv(a0, a1, -VALUE); + errn += verify("test_mulv_n: ", 0, a0[0], (Float.NaN*(-VALUE))); + errn += verify("test_mulv_n: ", 1, a0[1], (Float.POSITIVE_INFINITY*(-VALUE))); + errn += verify("test_mulv_n: ", 2, a0[2], (Float.NEGATIVE_INFINITY*(-VALUE))); + errn += verify("test_mulv_n: ", 3, a0[3], (Float.MAX_VALUE*(-VALUE))); + errn += verify("test_mulv_n: ", 4, a0[4], (Float.MIN_VALUE*(-VALUE))); + errn += verify("test_mulv_n: ", 5, a0[5], (Float.MIN_NORMAL*(-VALUE))); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_mulv_n: ", i, a0[i], ((ADD_INIT+i)*(-VALUE))); + } + test_mula(a0, a1, a3); + errn += verify("test_mula_n: ", 0, a0[0], (Float.NaN*(-VALUE))); + errn += verify("test_mula_n: ", 1, a0[1], (Float.POSITIVE_INFINITY*(-VALUE))); + errn += verify("test_mula_n: ", 2, a0[2], (Float.NEGATIVE_INFINITY*(-VALUE))); + errn += verify("test_mula_n: ", 3, a0[3], (Float.MAX_VALUE*(-VALUE))); + errn += verify("test_mula_n: ", 4, a0[4], (Float.MIN_VALUE*(-VALUE))); + errn += verify("test_mula_n: ", 5, a0[5], (Float.MIN_NORMAL*(-VALUE))); + errn += verify("test_mula_n: ", 6, a0[6], ((ADD_INIT+6)*(-Float.NaN))); + errn += verify("test_mula_n: ", 7, a0[7], ((ADD_INIT+7)*(-Float.POSITIVE_INFINITY))); + errn += verify("test_mula_n: ", 8, a0[8], ((ADD_INIT+8)*(-Float.NEGATIVE_INFINITY))); + errn += verify("test_mula_n: ", 9, a0[9], ((ADD_INIT+9)*(-Float.MAX_VALUE))); + errn += verify("test_mula_n: ", 10, a0[10], ((ADD_INIT+10)*(-Float.MIN_VALUE))); + errn += verify("test_mula_n: ", 11, a0[11], ((ADD_INIT+11)*(-Float.MIN_NORMAL))); + for (int i=12; i<ARRLEN; i++) { + errn += verify("test_mula_n: ", i, a0[i], ((ADD_INIT+i)*(-VALUE))); + } + + test_divc_n(a0, a1); + errn += verify("test_divc_n: ", 0, a0[0], (Float.NaN/(-VALUE))); + errn += verify("test_divc_n: ", 1, a0[1], (Float.POSITIVE_INFINITY/(-VALUE))); + errn += verify("test_divc_n: ", 2, a0[2], (Float.NEGATIVE_INFINITY/(-VALUE))); + errn += verify("test_divc_n: ", 3, a0[3], (Float.MAX_VALUE/(-VALUE))); + errn += verify("test_divc_n: ", 4, a0[4], (Float.MIN_VALUE/(-VALUE))); + errn += verify("test_divc_n: ", 5, a0[5], (Float.MIN_NORMAL/(-VALUE))); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_divc_n: ", i, a0[i], ((ADD_INIT+i)/(-VALUE))); + } + test_divv(a0, a1, -VALUE); + errn += verify("test_divv_n: ", 0, a0[0], (Float.NaN/(-VALUE))); + errn += verify("test_divv_n: ", 1, a0[1], (Float.POSITIVE_INFINITY/(-VALUE))); + errn += verify("test_divv_n: ", 2, a0[2], (Float.NEGATIVE_INFINITY/(-VALUE))); + errn += verify("test_divv_n: ", 3, a0[3], (Float.MAX_VALUE/(-VALUE))); + errn += verify("test_divv_n: ", 4, a0[4], (Float.MIN_VALUE/(-VALUE))); + errn += verify("test_divv_n: ", 5, a0[5], (Float.MIN_NORMAL/(-VALUE))); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_divv_n: ", i, a0[i], ((ADD_INIT+i)/(-VALUE))); + } + test_diva(a0, a1, a3); + errn += verify("test_diva_n: ", 0, a0[0], (Float.NaN/(-VALUE))); + errn += verify("test_diva_n: ", 1, a0[1], (Float.POSITIVE_INFINITY/(-VALUE))); + errn += verify("test_diva_n: ", 2, a0[2], (Float.NEGATIVE_INFINITY/(-VALUE))); + errn += verify("test_diva_n: ", 3, a0[3], (Float.MAX_VALUE/(-VALUE))); + errn += verify("test_diva_n: ", 4, a0[4], (Float.MIN_VALUE/(-VALUE))); + errn += verify("test_diva_n: ", 5, a0[5], (Float.MIN_NORMAL/(-VALUE))); + errn += verify("test_diva_n: ", 6, a0[6], ((ADD_INIT+6)/(-Float.NaN))); + errn += verify("test_diva_n: ", 7, a0[7], ((ADD_INIT+7)/(-Float.POSITIVE_INFINITY))); + errn += verify("test_diva_n: ", 8, a0[8], ((ADD_INIT+8)/(-Float.NEGATIVE_INFINITY))); + errn += verify("test_diva_n: ", 9, a0[9], ((ADD_INIT+9)/(-Float.MAX_VALUE))); + errn += verify("test_diva_n: ", 10, a0[10], ((ADD_INIT+10)/(-Float.MIN_VALUE))); + errn += verify("test_diva_n: ", 11, a0[11], ((ADD_INIT+11)/(-Float.MIN_NORMAL))); + for (int i=12; i<ARRLEN; i++) { + errn += verify("test_diva_n: ", i, a0[i], ((ADD_INIT+i)/(-VALUE))); + } + + } + + if (errn > 0) + return errn; + + System.out.println("Time"); + long start, end; + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sum(a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sum: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_addc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_addv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_adda(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_adda: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_subc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_subc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_subv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_subv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_suba(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_suba: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_mulc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_mulv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mula(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_mula: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_divc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_divv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_diva(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_diva: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_mulc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulv(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_mulv_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mula(a0, a1, a3); + } + end = System.currentTimeMillis(); + System.out.println("test_mula_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_divc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divv(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_divv_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_diva(a0, a1, a3); + } + end = System.currentTimeMillis(); + System.out.println("test_diva_n: " + (end - start)); + + return errn; + } + + static float test_sum(float[] a1) { + float sum = 0; + for (int i = 0; i < a1.length; i+=1) { + sum += a1[i]; + } + return sum; + } + + static void test_addc(float[] a0, float[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]+VALUE); + } + } + static void test_addv(float[] a0, float[] a1, float b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]+b); + } + } + static void test_adda(float[] a0, float[] a1, float[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]+a2[i]); + } + } + + static void test_subc(float[] a0, float[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]-VALUE); + } + } + static void test_subv(float[] a0, float[] a1, float b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]-b); + } + } + static void test_suba(float[] a0, float[] a1, float[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]-a2[i]); + } + } + + static void test_mulc(float[] a0, float[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]*VALUE); + } + } + static void test_mulc_n(float[] a0, float[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]*(-VALUE)); + } + } + static void test_mulv(float[] a0, float[] a1, float b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]*b); + } + } + static void test_mula(float[] a0, float[] a1, float[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]*a2[i]); + } + } + + static void test_divc(float[] a0, float[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]/VALUE); + } + } + static void test_divc_n(float[] a0, float[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]/(-VALUE)); + } + } + static void test_divv(float[] a0, float[] a1, float b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]/b); + } + } + static void test_diva(float[] a0, float[] a1, float[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (a1[i]/a2[i]); + } + } + + static int verify(String text, int i, float elem, float val) { + if (elem != val && !(Float.isNaN(elem) && Float.isNaN(val))) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6340864/TestIntVect.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,1012 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 6340864 + * @summary Implement vectorization optimizations in hotspot-server + * + * @run main/othervm/timeout=400 -Xbatch -Xmx64m TestIntVect + */ + +public class TestIntVect { + private static final int ARRLEN = 997; + private static final int ITERS = 11000; + private static final int ADD_INIT = Integer.MAX_VALUE-500; + private static final int BIT_MASK = 0xEC80F731; + private static final int VALUE = 15; + private static final int SHIFT = 32; + + public static void main(String args[]) { + System.out.println("Testing Integer vectors"); + int errn = test(); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test() { + int[] a0 = new int[ARRLEN]; + int[] a1 = new int[ARRLEN]; + int[] a2 = new int[ARRLEN]; + int[] a3 = new int[ARRLEN]; + int[] a4 = new int[ARRLEN]; + long[] p2 = new long[ARRLEN/2]; + // Initialize + int gold_sum = 0; + for (int i=0; i<ARRLEN; i++) { + int val = (int)(ADD_INIT+i); + gold_sum += val; + a1[i] = val; + a2[i] = (int)VALUE; + a3[i] = (int)-VALUE; + a4[i] = (int)BIT_MASK; + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_sum(a1); + test_addc(a0, a1); + test_addv(a0, a1, (int)VALUE); + test_adda(a0, a1, a2); + test_subc(a0, a1); + test_subv(a0, a1, (int)VALUE); + test_suba(a0, a1, a2); + test_mulc(a0, a1); + test_mulv(a0, a1, (int)VALUE); + test_mula(a0, a1, a2); + test_divc(a0, a1); + test_divv(a0, a1, (int)VALUE); + test_diva(a0, a1, a2); + test_mulc_n(a0, a1); + test_mulv(a0, a1, (int)-VALUE); + test_mula(a0, a1, a3); + test_divc_n(a0, a1); + test_divv(a0, a1, (int)-VALUE); + test_diva(a0, a1, a3); + test_andc(a0, a1); + test_andv(a0, a1, (int)BIT_MASK); + test_anda(a0, a1, a4); + test_orc(a0, a1); + test_orv(a0, a1, (int)BIT_MASK); + test_ora(a0, a1, a4); + test_xorc(a0, a1); + test_xorv(a0, a1, (int)BIT_MASK); + test_xora(a0, a1, a4); + test_sllc(a0, a1); + test_sllv(a0, a1, VALUE); + test_srlc(a0, a1); + test_srlv(a0, a1, VALUE); + test_srac(a0, a1); + test_srav(a0, a1, VALUE); + test_sllc_n(a0, a1); + test_sllv(a0, a1, -VALUE); + test_srlc_n(a0, a1); + test_srlv(a0, a1, -VALUE); + test_srac_n(a0, a1); + test_srav(a0, a1, -VALUE); + test_sllc_o(a0, a1); + test_sllv(a0, a1, SHIFT); + test_srlc_o(a0, a1); + test_srlv(a0, a1, SHIFT); + test_srac_o(a0, a1); + test_srav(a0, a1, SHIFT); + test_sllc_on(a0, a1); + test_sllv(a0, a1, -SHIFT); + test_srlc_on(a0, a1); + test_srlv(a0, a1, -SHIFT); + test_srac_on(a0, a1); + test_srav(a0, a1, -SHIFT); + test_pack2(p2, a1); + test_unpack2(a0, p2); + test_pack2_swap(p2, a1); + test_unpack2_swap(a0, p2); + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + int sum = test_sum(a1); + if (sum != gold_sum) { + System.err.println("test_sum: " + sum + " != " + gold_sum); + errn++; + } + + test_addc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_addc: ", i, a0[i], (int)((int)(ADD_INIT+i)+VALUE)); + } + test_addv(a0, a1, (int)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_addv: ", i, a0[i], (int)((int)(ADD_INIT+i)+VALUE)); + } + test_adda(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_adda: ", i, a0[i], (int)((int)(ADD_INIT+i)+VALUE)); + } + + test_subc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_subc: ", i, a0[i], (int)((int)(ADD_INIT+i)-VALUE)); + } + test_subv(a0, a1, (int)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_subv: ", i, a0[i], (int)((int)(ADD_INIT+i)-VALUE)); + } + test_suba(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_suba: ", i, a0[i], (int)((int)(ADD_INIT+i)-VALUE)); + } + + test_mulc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulc: ", i, a0[i], (int)((int)(ADD_INIT+i)*VALUE)); + } + test_mulv(a0, a1, (int)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulv: ", i, a0[i], (int)((int)(ADD_INIT+i)*VALUE)); + } + test_mula(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mula: ", i, a0[i], (int)((int)(ADD_INIT+i)*VALUE)); + } + + test_divc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divc: ", i, a0[i], (int)((int)(ADD_INIT+i)/VALUE)); + } + test_divv(a0, a1, (int)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divv: ", i, a0[i], (int)((int)(ADD_INIT+i)/VALUE)); + } + test_diva(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_diva: ", i, a0[i], (int)((int)(ADD_INIT+i)/VALUE)); + } + + test_mulc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulc_n: ", i, a0[i], (int)((int)(ADD_INIT+i)*(-VALUE))); + } + test_mulv(a0, a1, (int)-VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulv_n: ", i, a0[i], (int)((int)(ADD_INIT+i)*(-VALUE))); + } + test_mula(a0, a1, a3); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mula_n: ", i, a0[i], (int)((int)(ADD_INIT+i)*(-VALUE))); + } + + test_divc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divc_n: ", i, a0[i], (int)((int)(ADD_INIT+i)/(-VALUE))); + } + test_divv(a0, a1, (int)-VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divv_n: ", i, a0[i], (int)((int)(ADD_INIT+i)/(-VALUE))); + } + test_diva(a0, a1, a3); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_diva_n: ", i, a0[i], (int)((int)(ADD_INIT+i)/(-VALUE))); + } + + test_andc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_andc: ", i, a0[i], (int)((int)(ADD_INIT+i)&BIT_MASK)); + } + test_andv(a0, a1, (int)BIT_MASK); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_andv: ", i, a0[i], (int)((int)(ADD_INIT+i)&BIT_MASK)); + } + test_anda(a0, a1, a4); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_anda: ", i, a0[i], (int)((int)(ADD_INIT+i)&BIT_MASK)); + } + + test_orc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_orc: ", i, a0[i], (int)((int)(ADD_INIT+i)|BIT_MASK)); + } + test_orv(a0, a1, (int)BIT_MASK); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_orv: ", i, a0[i], (int)((int)(ADD_INIT+i)|BIT_MASK)); + } + test_ora(a0, a1, a4); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ora: ", i, a0[i], (int)((int)(ADD_INIT+i)|BIT_MASK)); + } + + test_xorc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_xorc: ", i, a0[i], (int)((int)(ADD_INIT+i)^BIT_MASK)); + } + test_xorv(a0, a1, (int)BIT_MASK); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_xorv: ", i, a0[i], (int)((int)(ADD_INIT+i)^BIT_MASK)); + } + test_xora(a0, a1, a4); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_xora: ", i, a0[i], (int)((int)(ADD_INIT+i)^BIT_MASK)); + } + + test_sllc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc: ", i, a0[i], (int)((int)(ADD_INIT+i)<<VALUE)); + } + test_sllv(a0, a1, VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv: ", i, a0[i], (int)((int)(ADD_INIT+i)<<VALUE)); + } + + test_srlc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc: ", i, a0[i], (int)((int)(ADD_INIT+i)>>>VALUE)); + } + test_srlv(a0, a1, VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv: ", i, a0[i], (int)((int)(ADD_INIT+i)>>>VALUE)); + } + + test_srac(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac: ", i, a0[i], (int)((int)(ADD_INIT+i)>>VALUE)); + } + test_srav(a0, a1, VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav: ", i, a0[i], (int)((int)(ADD_INIT+i)>>VALUE)); + } + + test_sllc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc_n: ", i, a0[i], (int)((int)(ADD_INIT+i)<<(-VALUE))); + } + test_sllv(a0, a1, -VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv_n: ", i, a0[i], (int)((int)(ADD_INIT+i)<<(-VALUE))); + } + + test_srlc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc_n: ", i, a0[i], (int)((int)(ADD_INIT+i)>>>(-VALUE))); + } + test_srlv(a0, a1, -VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv_n: ", i, a0[i], (int)((int)(ADD_INIT+i)>>>(-VALUE))); + } + + test_srac_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac_n: ", i, a0[i], (int)((int)(ADD_INIT+i)>>(-VALUE))); + } + test_srav(a0, a1, -VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav_n: ", i, a0[i], (int)((int)(ADD_INIT+i)>>(-VALUE))); + } + + test_sllc_o(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc_o: ", i, a0[i], (int)((int)(ADD_INIT+i)<<SHIFT)); + } + test_sllv(a0, a1, SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv_o: ", i, a0[i], (int)((int)(ADD_INIT+i)<<SHIFT)); + } + + test_srlc_o(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc_o: ", i, a0[i], (int)((int)(ADD_INIT+i)>>>SHIFT)); + } + test_srlv(a0, a1, SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv_o: ", i, a0[i], (int)((int)(ADD_INIT+i)>>>SHIFT)); + } + + test_srac_o(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac_o: ", i, a0[i], (int)((int)(ADD_INIT+i)>>SHIFT)); + } + test_srav(a0, a1, SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav_o: ", i, a0[i], (int)((int)(ADD_INIT+i)>>SHIFT)); + } + + test_sllc_on(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc_on: ", i, a0[i], (int)((int)(ADD_INIT+i)<<(-SHIFT))); + } + test_sllv(a0, a1, -SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv_on: ", i, a0[i], (int)((int)(ADD_INIT+i)<<(-SHIFT))); + } + + test_srlc_on(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc_on: ", i, a0[i], (int)((int)(ADD_INIT+i)>>>(-SHIFT))); + } + test_srlv(a0, a1, -SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv_on: ", i, a0[i], (int)((int)(ADD_INIT+i)>>>(-SHIFT))); + } + + test_srac_on(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac_on: ", i, a0[i], (int)((int)(ADD_INIT+i)>>(-SHIFT))); + } + test_srav(a0, a1, -SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav_on: ", i, a0[i], (int)((int)(ADD_INIT+i)>>(-SHIFT))); + } + + test_pack2(p2, a1); + for (int i=0; i<ARRLEN/2; i++) { + errn += verify("test_pack2: ", i, p2[i], ((long)(ADD_INIT+2*i) & 0xFFFFFFFFl) | ((long)(ADD_INIT+2*i+1) << 32)); + } + for (int i=0; i<ARRLEN; i++) { + a0[i] = -1; + } + test_unpack2(a0, p2); + for (int i=0; i<(ARRLEN&(-2)); i++) { + errn += verify("test_unpack2: ", i, a0[i], (ADD_INIT+i)); + } + + test_pack2_swap(p2, a1); + for (int i=0; i<ARRLEN/2; i++) { + errn += verify("test_pack2_swap: ", i, p2[i], ((long)(ADD_INIT+2*i+1) & 0xFFFFFFFFl) | ((long)(ADD_INIT+2*i) << 32)); + } + for (int i=0; i<ARRLEN; i++) { + a0[i] = -1; + } + test_unpack2_swap(a0, p2); + for (int i=0; i<(ARRLEN&(-2)); i++) { + errn += verify("test_unpack2_swap: ", i, a0[i], (ADD_INIT+i)); + } + + } + + if (errn > 0) + return errn; + + System.out.println("Time"); + long start, end; + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sum(a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sum: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_addc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addv(a0, a1, (int)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_addv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_adda(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_adda: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_subc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_subc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_subv(a0, a1, (int)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_subv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_suba(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_suba: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_mulc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulv(a0, a1, (int)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_mulv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mula(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_mula: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_divc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divv(a0, a1, (int)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_divv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_diva(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_diva: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_mulc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulv(a0, a1, (int)-VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_mulv_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mula(a0, a1, a3); + } + end = System.currentTimeMillis(); + System.out.println("test_mula_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_divc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divv(a0, a1, (int)-VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_divv_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_diva(a0, a1, a3); + } + end = System.currentTimeMillis(); + System.out.println("test_diva_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_andc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_andc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_andv(a0, a1, (int)BIT_MASK); + } + end = System.currentTimeMillis(); + System.out.println("test_andv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_anda(a0, a1, a4); + } + end = System.currentTimeMillis(); + System.out.println("test_anda: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_orc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_orc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_orv(a0, a1, (int)BIT_MASK); + } + end = System.currentTimeMillis(); + System.out.println("test_orv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ora(a0, a1, a4); + } + end = System.currentTimeMillis(); + System.out.println("test_ora: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_xorc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_xorc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_xorv(a0, a1, (int)BIT_MASK); + } + end = System.currentTimeMillis(); + System.out.println("test_xorv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_xora(a0, a1, a4); + } + end = System.currentTimeMillis(); + System.out.println("test_xora: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srav: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srav_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc_o(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc_o: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv_o: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc_o(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc_o: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv_o: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac_o(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac_o: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srav_o: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc_on(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc_on: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, -SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv_on: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc_on(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc_on: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, -SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv_on: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac_on(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac_on: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, -SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srav_on: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_pack2(p2, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_pack2: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unpack2(a0, p2); + } + end = System.currentTimeMillis(); + System.out.println("test_unpack2: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_pack2_swap(p2, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_pack2_swap: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unpack2_swap(a0, p2); + } + end = System.currentTimeMillis(); + System.out.println("test_unpack2_swap: " + (end - start)); + + return errn; + } + + static int test_sum(int[] a1) { + int sum = 0; + for (int i = 0; i < a1.length; i+=1) { + sum += a1[i]; + } + return sum; + } + + static void test_addc(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]+VALUE); + } + } + static void test_addv(int[] a0, int[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]+b); + } + } + static void test_adda(int[] a0, int[] a1, int[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]+a2[i]); + } + } + + static void test_subc(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]-VALUE); + } + } + static void test_subv(int[] a0, int[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]-b); + } + } + static void test_suba(int[] a0, int[] a1, int[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]-a2[i]); + } + } + + static void test_mulc(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]*VALUE); + } + } + static void test_mulc_n(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]*(-VALUE)); + } + } + static void test_mulv(int[] a0, int[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]*b); + } + } + static void test_mula(int[] a0, int[] a1, int[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]*a2[i]); + } + } + + static void test_divc(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]/VALUE); + } + } + static void test_divc_n(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]/(-VALUE)); + } + } + static void test_divv(int[] a0, int[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]/b); + } + } + static void test_diva(int[] a0, int[] a1, int[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]/a2[i]); + } + } + + static void test_andc(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]&BIT_MASK); + } + } + static void test_andv(int[] a0, int[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]&b); + } + } + static void test_anda(int[] a0, int[] a1, int[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]&a2[i]); + } + } + + static void test_orc(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]|BIT_MASK); + } + } + static void test_orv(int[] a0, int[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]|b); + } + } + static void test_ora(int[] a0, int[] a1, int[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]|a2[i]); + } + } + + static void test_xorc(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]^BIT_MASK); + } + } + static void test_xorv(int[] a0, int[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]^b); + } + } + static void test_xora(int[] a0, int[] a1, int[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]^a2[i]); + } + } + + static void test_sllc(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]<<VALUE); + } + } + static void test_sllc_n(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]<<(-VALUE)); + } + } + static void test_sllc_o(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]<<SHIFT); + } + } + static void test_sllc_on(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]<<(-SHIFT)); + } + } + static void test_sllv(int[] a0, int[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]<<b); + } + } + + static void test_srlc(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]>>>VALUE); + } + } + static void test_srlc_n(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]>>>(-VALUE)); + } + } + static void test_srlc_o(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]>>>SHIFT); + } + } + static void test_srlc_on(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]>>>(-SHIFT)); + } + } + static void test_srlv(int[] a0, int[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]>>>b); + } + } + + static void test_srac(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]>>VALUE); + } + } + static void test_srac_n(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]>>(-VALUE)); + } + } + static void test_srac_o(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]>>SHIFT); + } + } + static void test_srac_on(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]>>(-SHIFT)); + } + } + static void test_srav(int[] a0, int[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(a1[i]>>b); + } + } + + static void test_pack2(long[] p2, int[] a1) { + if (p2.length*2 > a1.length) return; + for (int i = 0; i < p2.length; i+=1) { + long l0 = (long)a1[i*2+0]; + long l1 = (long)a1[i*2+1]; + p2[i] = (l1 << 32) | (l0 & 0xFFFFFFFFl); + } + } + static void test_unpack2(int[] a0, long[] p2) { + if (p2.length*2 > a0.length) return; + for (int i = 0; i < p2.length; i+=1) { + long l = p2[i]; + a0[i*2+0] = (int)(l & 0xFFFFFFFFl); + a0[i*2+1] = (int)(l >> 32); + } + } + static void test_pack2_swap(long[] p2, int[] a1) { + if (p2.length*2 > a1.length) return; + for (int i = 0; i < p2.length; i+=1) { + long l0 = (long)a1[i*2+0]; + long l1 = (long)a1[i*2+1]; + p2[i] = (l0 << 32) | (l1 & 0xFFFFFFFFl); + } + } + static void test_unpack2_swap(int[] a0, long[] p2) { + if (p2.length*2 > a0.length) return; + for (int i = 0; i < p2.length; i+=1) { + long l = p2[i]; + a0[i*2+0] = (int)(l >> 32); + a0[i*2+1] = (int)(l & 0xFFFFFFFFl); + } + } + + static int verify(String text, int i, int elem, int val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } + + static int verify(String text, int i, long elem, long val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + Long.toHexString(elem) + " != " + Long.toHexString(val)); + return 1; + } + return 0; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6340864/TestLongVect.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,917 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 6340864 + * @summary Implement vectorization optimizations in hotspot-server + * + * @run main/othervm/timeout=400 -Xbatch -Xmx64m TestLongVect + */ + +public class TestLongVect { + private static final int ARRLEN = 997; + private static final int ITERS = 11000; + private static final long ADD_INIT = Long.MAX_VALUE-500; + private static final long BIT_MASK = 0xEC80F731EC80F731L; + private static final int VALUE = 31; + private static final int SHIFT = 64; + + public static void main(String args[]) { + System.out.println("Testing Long vectors"); + int errn = test(); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test() { + long[] a0 = new long[ARRLEN]; + long[] a1 = new long[ARRLEN]; + long[] a2 = new long[ARRLEN]; + long[] a3 = new long[ARRLEN]; + long[] a4 = new long[ARRLEN]; + // Initialize + long gold_sum = 0; + for (int i=0; i<ARRLEN; i++) { + long val = (long)(ADD_INIT+i); + gold_sum += val; + a1[i] = val; + a2[i] = (long)VALUE; + a3[i] = (long)-VALUE; + a4[i] = (long)BIT_MASK; + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_sum(a1); + test_addc(a0, a1); + test_addv(a0, a1, (long)VALUE); + test_adda(a0, a1, a2); + test_subc(a0, a1); + test_subv(a0, a1, (long)VALUE); + test_suba(a0, a1, a2); + test_mulc(a0, a1); + test_mulv(a0, a1, (long)VALUE); + test_mula(a0, a1, a2); + test_divc(a0, a1); + test_divv(a0, a1, (long)VALUE); + test_diva(a0, a1, a2); + test_mulc_n(a0, a1); + test_mulv(a0, a1, (long)-VALUE); + test_mula(a0, a1, a3); + test_divc_n(a0, a1); + test_divv(a0, a1, (long)-VALUE); + test_diva(a0, a1, a3); + test_andc(a0, a1); + test_andv(a0, a1, (long)BIT_MASK); + test_anda(a0, a1, a4); + test_orc(a0, a1); + test_orv(a0, a1, (long)BIT_MASK); + test_ora(a0, a1, a4); + test_xorc(a0, a1); + test_xorv(a0, a1, (long)BIT_MASK); + test_xora(a0, a1, a4); + test_sllc(a0, a1); + test_sllv(a0, a1, VALUE); + test_srlc(a0, a1); + test_srlv(a0, a1, VALUE); + test_srac(a0, a1); + test_srav(a0, a1, VALUE); + test_sllc_n(a0, a1); + test_sllv(a0, a1, -VALUE); + test_srlc_n(a0, a1); + test_srlv(a0, a1, -VALUE); + test_srac_n(a0, a1); + test_srav(a0, a1, -VALUE); + test_sllc_o(a0, a1); + test_sllv(a0, a1, SHIFT); + test_srlc_o(a0, a1); + test_srlv(a0, a1, SHIFT); + test_srac_o(a0, a1); + test_srav(a0, a1, SHIFT); + test_sllc_on(a0, a1); + test_sllv(a0, a1, -SHIFT); + test_srlc_on(a0, a1); + test_srlv(a0, a1, -SHIFT); + test_srac_on(a0, a1); + test_srav(a0, a1, -SHIFT); + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + long sum = test_sum(a1); + if (sum != gold_sum) { + System.err.println("test_sum: " + sum + " != " + gold_sum); + errn++; + } + + test_addc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_addc: ", i, a0[i], (long)((long)(ADD_INIT+i)+VALUE)); + } + test_addv(a0, a1, (long)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_addv: ", i, a0[i], (long)((long)(ADD_INIT+i)+VALUE)); + } + test_adda(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_adda: ", i, a0[i], (long)((long)(ADD_INIT+i)+VALUE)); + } + + test_subc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_subc: ", i, a0[i], (long)((long)(ADD_INIT+i)-VALUE)); + } + test_subv(a0, a1, (long)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_subv: ", i, a0[i], (long)((long)(ADD_INIT+i)-VALUE)); + } + test_suba(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_suba: ", i, a0[i], (long)((long)(ADD_INIT+i)-VALUE)); + } + + test_mulc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulc: ", i, a0[i], (long)((long)(ADD_INIT+i)*VALUE)); + } + test_mulv(a0, a1, (long)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulv: ", i, a0[i], (long)((long)(ADD_INIT+i)*VALUE)); + } + test_mula(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mula: ", i, a0[i], (long)((long)(ADD_INIT+i)*VALUE)); + } + + test_divc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divc: ", i, a0[i], (long)((long)(ADD_INIT+i)/VALUE)); + } + test_divv(a0, a1, (long)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divv: ", i, a0[i], (long)((long)(ADD_INIT+i)/VALUE)); + } + test_diva(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_diva: ", i, a0[i], (long)((long)(ADD_INIT+i)/VALUE)); + } + + test_mulc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulc_n: ", i, a0[i], (long)((long)(ADD_INIT+i)*(-VALUE))); + } + test_mulv(a0, a1, (long)-VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulv_n: ", i, a0[i], (long)((long)(ADD_INIT+i)*(-VALUE))); + } + test_mula(a0, a1, a3); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mula_n: ", i, a0[i], (long)((long)(ADD_INIT+i)*(-VALUE))); + } + + test_divc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divc_n: ", i, a0[i], (long)((long)(ADD_INIT+i)/(-VALUE))); + } + test_divv(a0, a1, (long)-VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divv_n: ", i, a0[i], (long)((long)(ADD_INIT+i)/(-VALUE))); + } + test_diva(a0, a1, a3); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_diva_n: ", i, a0[i], (long)((long)(ADD_INIT+i)/(-VALUE))); + } + + test_andc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_andc: ", i, a0[i], (long)((long)(ADD_INIT+i)&BIT_MASK)); + } + test_andv(a0, a1, (long)BIT_MASK); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_andv: ", i, a0[i], (long)((long)(ADD_INIT+i)&BIT_MASK)); + } + test_anda(a0, a1, a4); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_anda: ", i, a0[i], (long)((long)(ADD_INIT+i)&BIT_MASK)); + } + + test_orc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_orc: ", i, a0[i], (long)((long)(ADD_INIT+i)|BIT_MASK)); + } + test_orv(a0, a1, (long)BIT_MASK); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_orv: ", i, a0[i], (long)((long)(ADD_INIT+i)|BIT_MASK)); + } + test_ora(a0, a1, a4); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ora: ", i, a0[i], (long)((long)(ADD_INIT+i)|BIT_MASK)); + } + + test_xorc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_xorc: ", i, a0[i], (long)((long)(ADD_INIT+i)^BIT_MASK)); + } + test_xorv(a0, a1, (long)BIT_MASK); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_xorv: ", i, a0[i], (long)((long)(ADD_INIT+i)^BIT_MASK)); + } + test_xora(a0, a1, a4); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_xora: ", i, a0[i], (long)((long)(ADD_INIT+i)^BIT_MASK)); + } + + test_sllc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc: ", i, a0[i], (long)((long)(ADD_INIT+i)<<VALUE)); + } + test_sllv(a0, a1, VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv: ", i, a0[i], (long)((long)(ADD_INIT+i)<<VALUE)); + } + + test_srlc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc: ", i, a0[i], (long)((long)(ADD_INIT+i)>>>VALUE)); + } + test_srlv(a0, a1, VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv: ", i, a0[i], (long)((long)(ADD_INIT+i)>>>VALUE)); + } + + test_srac(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac: ", i, a0[i], (long)((long)(ADD_INIT+i)>>VALUE)); + } + test_srav(a0, a1, VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav: ", i, a0[i], (long)((long)(ADD_INIT+i)>>VALUE)); + } + + test_sllc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc_n: ", i, a0[i], (long)((long)(ADD_INIT+i)<<(-VALUE))); + } + test_sllv(a0, a1, -VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv_n: ", i, a0[i], (long)((long)(ADD_INIT+i)<<(-VALUE))); + } + + test_srlc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc_n: ", i, a0[i], (long)((long)(ADD_INIT+i)>>>(-VALUE))); + } + test_srlv(a0, a1, -VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv_n: ", i, a0[i], (long)((long)(ADD_INIT+i)>>>(-VALUE))); + } + + test_srac_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac_n: ", i, a0[i], (long)((long)(ADD_INIT+i)>>(-VALUE))); + } + test_srav(a0, a1, -VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav_n: ", i, a0[i], (long)((long)(ADD_INIT+i)>>(-VALUE))); + } + + test_sllc_o(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc_o: ", i, a0[i], (long)((long)(ADD_INIT+i)<<SHIFT)); + } + test_sllv(a0, a1, SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv_o: ", i, a0[i], (long)((long)(ADD_INIT+i)<<SHIFT)); + } + + test_srlc_o(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc_o: ", i, a0[i], (long)((long)(ADD_INIT+i)>>>SHIFT)); + } + test_srlv(a0, a1, SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv_o: ", i, a0[i], (long)((long)(ADD_INIT+i)>>>SHIFT)); + } + + test_srac_o(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac_o: ", i, a0[i], (long)((long)(ADD_INIT+i)>>SHIFT)); + } + test_srav(a0, a1, SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav_o: ", i, a0[i], (long)((long)(ADD_INIT+i)>>SHIFT)); + } + + test_sllc_on(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc_on: ", i, a0[i], (long)((long)(ADD_INIT+i)<<(-SHIFT))); + } + test_sllv(a0, a1, -SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv_on: ", i, a0[i], (long)((long)(ADD_INIT+i)<<(-SHIFT))); + } + + test_srlc_on(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc_on: ", i, a0[i], (long)((long)(ADD_INIT+i)>>>(-SHIFT))); + } + test_srlv(a0, a1, -SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv_on: ", i, a0[i], (long)((long)(ADD_INIT+i)>>>(-SHIFT))); + } + + test_srac_on(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac_on: ", i, a0[i], (long)((long)(ADD_INIT+i)>>(-SHIFT))); + } + test_srav(a0, a1, -SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav_on: ", i, a0[i], (long)((long)(ADD_INIT+i)>>(-SHIFT))); + } + + } + + if (errn > 0) + return errn; + + System.out.println("Time"); + long start, end; + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sum(a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sum: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_addc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addv(a0, a1, (long)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_addv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_adda(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_adda: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_subc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_subc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_subv(a0, a1, (long)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_subv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_suba(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_suba: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_mulc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulv(a0, a1, (long)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_mulv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mula(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_mula: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_divc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divv(a0, a1, (long)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_divv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_diva(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_diva: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_mulc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulv(a0, a1, (long)-VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_mulv_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mula(a0, a1, a3); + } + end = System.currentTimeMillis(); + System.out.println("test_mula_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_divc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divv(a0, a1, (long)-VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_divv_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_diva(a0, a1, a3); + } + end = System.currentTimeMillis(); + System.out.println("test_diva_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_andc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_andc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_andv(a0, a1, (long)BIT_MASK); + } + end = System.currentTimeMillis(); + System.out.println("test_andv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_anda(a0, a1, a4); + } + end = System.currentTimeMillis(); + System.out.println("test_anda: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_orc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_orc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_orv(a0, a1, (long)BIT_MASK); + } + end = System.currentTimeMillis(); + System.out.println("test_orv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ora(a0, a1, a4); + } + end = System.currentTimeMillis(); + System.out.println("test_ora: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_xorc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_xorc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_xorv(a0, a1, (long)BIT_MASK); + } + end = System.currentTimeMillis(); + System.out.println("test_xorv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_xora(a0, a1, a4); + } + end = System.currentTimeMillis(); + System.out.println("test_xora: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srav: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srav_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc_o(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc_o: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv_o: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc_o(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc_o: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv_o: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac_o(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac_o: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srav_o: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc_on(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc_on: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, -SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv_on: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc_on(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc_on: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, -SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv_on: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac_on(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac_on: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, -SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srav_on: " + (end - start)); + + return errn; + } + + static long test_sum(long[] a1) { + long sum = 0; + for (int i = 0; i < a1.length; i+=1) { + sum += a1[i]; + } + return sum; + } + + static void test_addc(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]+VALUE); + } + } + static void test_addv(long[] a0, long[] a1, long b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]+b); + } + } + static void test_adda(long[] a0, long[] a1, long[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]+a2[i]); + } + } + + static void test_subc(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]-VALUE); + } + } + static void test_subv(long[] a0, long[] a1, long b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]-b); + } + } + static void test_suba(long[] a0, long[] a1, long[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]-a2[i]); + } + } + + static void test_mulc(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]*VALUE); + } + } + static void test_mulc_n(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]*(-VALUE)); + } + } + static void test_mulv(long[] a0, long[] a1, long b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]*b); + } + } + static void test_mula(long[] a0, long[] a1, long[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]*a2[i]); + } + } + + static void test_divc(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]/VALUE); + } + } + static void test_divc_n(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]/(-VALUE)); + } + } + static void test_divv(long[] a0, long[] a1, long b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]/b); + } + } + static void test_diva(long[] a0, long[] a1, long[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]/a2[i]); + } + } + + static void test_andc(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]&BIT_MASK); + } + } + static void test_andv(long[] a0, long[] a1, long b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]&b); + } + } + static void test_anda(long[] a0, long[] a1, long[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]&a2[i]); + } + } + + static void test_orc(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]|BIT_MASK); + } + } + static void test_orv(long[] a0, long[] a1, long b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]|b); + } + } + static void test_ora(long[] a0, long[] a1, long[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]|a2[i]); + } + } + + static void test_xorc(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]^BIT_MASK); + } + } + static void test_xorv(long[] a0, long[] a1, long b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]^b); + } + } + static void test_xora(long[] a0, long[] a1, long[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]^a2[i]); + } + } + + static void test_sllc(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]<<VALUE); + } + } + static void test_sllc_n(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]<<(-VALUE)); + } + } + static void test_sllc_o(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]<<SHIFT); + } + } + static void test_sllc_on(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]<<(-SHIFT)); + } + } + static void test_sllv(long[] a0, long[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]<<b); + } + } + + static void test_srlc(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]>>>VALUE); + } + } + static void test_srlc_n(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]>>>(-VALUE)); + } + } + static void test_srlc_o(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]>>>SHIFT); + } + } + static void test_srlc_on(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]>>>(-SHIFT)); + } + } + static void test_srlv(long[] a0, long[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]>>>b); + } + } + + static void test_srac(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]>>VALUE); + } + } + static void test_srac_n(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]>>(-VALUE)); + } + } + static void test_srac_o(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]>>SHIFT); + } + } + static void test_srac_on(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]>>(-SHIFT)); + } + } + static void test_srav(long[] a0, long[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]>>b); + } + } + + static int verify(String text, int i, long elem, long val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6340864/TestShortVect.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,1127 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 6340864 + * @summary Implement vectorization optimizations in hotspot-server + * + * @run main/othervm/timeout=400 -Xbatch -Xmx64m TestShortVect + */ + +public class TestShortVect { + private static final int ARRLEN = 997; + private static final int ITERS = 11000; + private static final int ADD_INIT = Short.MAX_VALUE-500; + private static final int BIT_MASK = 0xB731; + private static final int VALUE = 7; + private static final int SHIFT = 16; + + public static void main(String args[]) { + System.out.println("Testing Short vectors"); + int errn = test(); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test() { + short[] a0 = new short[ARRLEN]; + short[] a1 = new short[ARRLEN]; + short[] a2 = new short[ARRLEN]; + short[] a3 = new short[ARRLEN]; + short[] a4 = new short[ARRLEN]; + int[] p2 = new int[ARRLEN/2]; + long[] p4 = new long[ARRLEN/4]; + // Initialize + int gold_sum = 0; + for (int i=0; i<ARRLEN; i++) { + short val = (short)(ADD_INIT+i); + gold_sum += val; + a1[i] = val; + a2[i] = (short)VALUE; + a3[i] = (short)-VALUE; + a4[i] = (short)BIT_MASK; + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_sum(a1); + test_addc(a0, a1); + test_addv(a0, a1, (short)VALUE); + test_adda(a0, a1, a2); + test_subc(a0, a1); + test_subv(a0, a1, (short)VALUE); + test_suba(a0, a1, a2); + test_mulc(a0, a1); + test_mulv(a0, a1, (short)VALUE); + test_mula(a0, a1, a2); + test_divc(a0, a1); + test_divv(a0, a1, (short)VALUE); + test_diva(a0, a1, a2); + test_mulc_n(a0, a1); + test_mulv(a0, a1, (short)-VALUE); + test_mula(a0, a1, a3); + test_divc_n(a0, a1); + test_divv(a0, a1, (short)-VALUE); + test_diva(a0, a1, a3); + test_andc(a0, a1); + test_andv(a0, a1, (short)BIT_MASK); + test_anda(a0, a1, a4); + test_orc(a0, a1); + test_orv(a0, a1, (short)BIT_MASK); + test_ora(a0, a1, a4); + test_xorc(a0, a1); + test_xorv(a0, a1, (short)BIT_MASK); + test_xora(a0, a1, a4); + test_sllc(a0, a1); + test_sllv(a0, a1, VALUE); + test_srlc(a0, a1); + test_srlv(a0, a1, VALUE); + test_srac(a0, a1); + test_srav(a0, a1, VALUE); + test_sllc_n(a0, a1); + test_sllv(a0, a1, -VALUE); + test_srlc_n(a0, a1); + test_srlv(a0, a1, -VALUE); + test_srac_n(a0, a1); + test_srav(a0, a1, -VALUE); + test_sllc_o(a0, a1); + test_sllv(a0, a1, SHIFT); + test_srlc_o(a0, a1); + test_srlv(a0, a1, SHIFT); + test_srac_o(a0, a1); + test_srav(a0, a1, SHIFT); + test_sllc_on(a0, a1); + test_sllv(a0, a1, -SHIFT); + test_srlc_on(a0, a1); + test_srlv(a0, a1, -SHIFT); + test_srac_on(a0, a1); + test_srav(a0, a1, -SHIFT); + test_pack2(p2, a1); + test_unpack2(a0, p2); + test_pack2_swap(p2, a1); + test_unpack2_swap(a0, p2); + test_pack4(p4, a1); + test_unpack4(a0, p4); + test_pack4_swap(p4, a1); + test_unpack4_swap(a0, p4); + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + int sum = test_sum(a1); + if (sum != gold_sum) { + System.err.println("test_sum: " + sum + " != " + gold_sum); + errn++; + } + + test_addc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_addc: ", i, a0[i], (short)((short)(ADD_INIT+i)+VALUE)); + } + test_addv(a0, a1, (short)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_addv: ", i, a0[i], (short)((short)(ADD_INIT+i)+VALUE)); + } + test_adda(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_adda: ", i, a0[i], (short)((short)(ADD_INIT+i)+VALUE)); + } + + test_subc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_subc: ", i, a0[i], (short)((short)(ADD_INIT+i)-VALUE)); + } + test_subv(a0, a1, (short)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_subv: ", i, a0[i], (short)((short)(ADD_INIT+i)-VALUE)); + } + test_suba(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_suba: ", i, a0[i], (short)((short)(ADD_INIT+i)-VALUE)); + } + + test_mulc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulc: ", i, a0[i], (short)((short)(ADD_INIT+i)*VALUE)); + } + test_mulv(a0, a1, (short)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulv: ", i, a0[i], (short)((short)(ADD_INIT+i)*VALUE)); + } + test_mula(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mula: ", i, a0[i], (short)((short)(ADD_INIT+i)*VALUE)); + } + + test_divc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divc: ", i, a0[i], (short)((short)(ADD_INIT+i)/VALUE)); + } + test_divv(a0, a1, (short)VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divv: ", i, a0[i], (short)((short)(ADD_INIT+i)/VALUE)); + } + test_diva(a0, a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_diva: ", i, a0[i], (short)((short)(ADD_INIT+i)/VALUE)); + } + + test_mulc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulc_n: ", i, a0[i], (short)((short)(ADD_INIT+i)*(-VALUE))); + } + test_mulv(a0, a1, (short)-VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mulv_n: ", i, a0[i], (short)((short)(ADD_INIT+i)*(-VALUE))); + } + test_mula(a0, a1, a3); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_mula_n: ", i, a0[i], (short)((short)(ADD_INIT+i)*(-VALUE))); + } + + test_divc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divc_n: ", i, a0[i], (short)((short)(ADD_INIT+i)/(-VALUE))); + } + test_divv(a0, a1, (short)-VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divv_n: ", i, a0[i], (short)((short)(ADD_INIT+i)/(-VALUE))); + } + test_diva(a0, a1, a3); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_diva_n: ", i, a0[i], (short)((short)(ADD_INIT+i)/(-VALUE))); + } + + test_andc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_andc: ", i, a0[i], (short)((short)(ADD_INIT+i)&BIT_MASK)); + } + test_andv(a0, a1, (short)BIT_MASK); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_andv: ", i, a0[i], (short)((short)(ADD_INIT+i)&BIT_MASK)); + } + test_anda(a0, a1, a4); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_anda: ", i, a0[i], (short)((short)(ADD_INIT+i)&BIT_MASK)); + } + + test_orc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_orc: ", i, a0[i], (short)((short)(ADD_INIT+i)|BIT_MASK)); + } + test_orv(a0, a1, (short)BIT_MASK); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_orv: ", i, a0[i], (short)((short)(ADD_INIT+i)|BIT_MASK)); + } + test_ora(a0, a1, a4); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ora: ", i, a0[i], (short)((short)(ADD_INIT+i)|BIT_MASK)); + } + + test_xorc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_xorc: ", i, a0[i], (short)((short)(ADD_INIT+i)^BIT_MASK)); + } + test_xorv(a0, a1, (short)BIT_MASK); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_xorv: ", i, a0[i], (short)((short)(ADD_INIT+i)^BIT_MASK)); + } + test_xora(a0, a1, a4); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_xora: ", i, a0[i], (short)((short)(ADD_INIT+i)^BIT_MASK)); + } + + test_sllc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc: ", i, a0[i], (short)((short)(ADD_INIT+i)<<VALUE)); + } + test_sllv(a0, a1, VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv: ", i, a0[i], (short)((short)(ADD_INIT+i)<<VALUE)); + } + + test_srlc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc: ", i, a0[i], (short)((short)(ADD_INIT+i)>>>VALUE)); + } + test_srlv(a0, a1, VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv: ", i, a0[i], (short)((short)(ADD_INIT+i)>>>VALUE)); + } + + test_srac(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac: ", i, a0[i], (short)((short)(ADD_INIT+i)>>VALUE)); + } + test_srav(a0, a1, VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav: ", i, a0[i], (short)((short)(ADD_INIT+i)>>VALUE)); + } + + test_sllc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc_n: ", i, a0[i], (short)((short)(ADD_INIT+i)<<(-VALUE))); + } + test_sllv(a0, a1, -VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv_n: ", i, a0[i], (short)((short)(ADD_INIT+i)<<(-VALUE))); + } + + test_srlc_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc_n: ", i, a0[i], (short)((short)(ADD_INIT+i)>>>(-VALUE))); + } + test_srlv(a0, a1, -VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv_n: ", i, a0[i], (short)((short)(ADD_INIT+i)>>>(-VALUE))); + } + + test_srac_n(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac_n: ", i, a0[i], (short)((short)(ADD_INIT+i)>>(-VALUE))); + } + test_srav(a0, a1, -VALUE); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav_n: ", i, a0[i], (short)((short)(ADD_INIT+i)>>(-VALUE))); + } + + test_sllc_o(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc_o: ", i, a0[i], (short)((short)(ADD_INIT+i)<<SHIFT)); + } + test_sllv(a0, a1, SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv_o: ", i, a0[i], (short)((short)(ADD_INIT+i)<<SHIFT)); + } + + test_srlc_o(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc_o: ", i, a0[i], (short)((short)(ADD_INIT+i)>>>SHIFT)); + } + test_srlv(a0, a1, SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv_o: ", i, a0[i], (short)((short)(ADD_INIT+i)>>>SHIFT)); + } + + test_srac_o(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac_o: ", i, a0[i], (short)((short)(ADD_INIT+i)>>SHIFT)); + } + test_srav(a0, a1, SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav_o: ", i, a0[i], (short)((short)(ADD_INIT+i)>>SHIFT)); + } + + test_sllc_on(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllc_on: ", i, a0[i], (short)((short)(ADD_INIT+i)<<(-SHIFT))); + } + test_sllv(a0, a1, -SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_sllv_on: ", i, a0[i], (short)((short)(ADD_INIT+i)<<(-SHIFT))); + } + + test_srlc_on(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlc_on: ", i, a0[i], (short)((short)(ADD_INIT+i)>>>(-SHIFT))); + } + test_srlv(a0, a1, -SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srlv_on: ", i, a0[i], (short)((short)(ADD_INIT+i)>>>(-SHIFT))); + } + + test_srac_on(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srac_on: ", i, a0[i], (short)((short)(ADD_INIT+i)>>(-SHIFT))); + } + test_srav(a0, a1, -SHIFT); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_srav_on: ", i, a0[i], (short)((short)(ADD_INIT+i)>>(-SHIFT))); + } + + test_pack2(p2, a1); + for (int i=0; i<ARRLEN/2; i++) { + errn += verify("test_pack2: ", i, p2[i], ((int)(ADD_INIT+2*i) & 0xFFFF) | ((int)(ADD_INIT+2*i+1) << 16)); + } + for (int i=0; i<ARRLEN; i++) { + a0[i] = -1; + } + test_unpack2(a0, p2); + for (int i=0; i<(ARRLEN&(-2)); i++) { + errn += verify("test_unpack2: ", i, a0[i], (short)(ADD_INIT+i)); + } + + test_pack2_swap(p2, a1); + for (int i=0; i<ARRLEN/2; i++) { + errn += verify("test_pack2_swap: ", i, p2[i], ((int)(ADD_INIT+2*i+1) & 0xFFFF) | ((int)(ADD_INIT+2*i) << 16)); + } + for (int i=0; i<ARRLEN; i++) { + a0[i] = -1; + } + test_unpack2_swap(a0, p2); + for (int i=0; i<(ARRLEN&(-2)); i++) { + errn += verify("test_unpack2_swap: ", i, a0[i], (short)(ADD_INIT+i)); + } + + test_pack4(p4, a1); + for (int i=0; i<ARRLEN/4; i++) { + errn += verify("test_pack4: ", i, p4[i], ((long)(ADD_INIT+4*i+0) & 0xFFFFl) | + (((long)(ADD_INIT+4*i+1) & 0xFFFFl) << 16) | + (((long)(ADD_INIT+4*i+2) & 0xFFFFl) << 32) | + (((long)(ADD_INIT+4*i+3) & 0xFFFFl) << 48)); + } + for (int i=0; i<ARRLEN; i++) { + a0[i] = -1; + } + test_unpack4(a0, p4); + for (int i=0; i<(ARRLEN&(-4)); i++) { + errn += verify("test_unpack4: ", i, a0[i], (short)(ADD_INIT+i)); + } + + test_pack4_swap(p4, a1); + for (int i=0; i<ARRLEN/4; i++) { + errn += verify("test_pack4_swap: ", i, p4[i], ((long)(ADD_INIT+4*i+3) & 0xFFFFl) | + (((long)(ADD_INIT+4*i+2) & 0xFFFFl) << 16) | + (((long)(ADD_INIT+4*i+1) & 0xFFFFl) << 32) | + (((long)(ADD_INIT+4*i+0) & 0xFFFFl) << 48)); + } + for (int i=0; i<ARRLEN; i++) { + a0[i] = -1; + } + test_unpack4_swap(a0, p4); + for (int i=0; i<(ARRLEN&(-4)); i++) { + errn += verify("test_unpack4_swap: ", i, a0[i], (short)(ADD_INIT+i)); + } + + } + + if (errn > 0) + return errn; + + System.out.println("Time"); + long start, end; + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sum(a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sum: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_addc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addv(a0, a1, (short)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_addv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_adda(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_adda: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_subc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_subc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_subv(a0, a1, (short)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_subv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_suba(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_suba: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_mulc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulv(a0, a1, (short)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_mulv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mula(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_mula: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_divc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divv(a0, a1, (short)VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_divv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_diva(a0, a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_diva: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_mulc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mulv(a0, a1, (short)-VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_mulv_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_mula(a0, a1, a3); + } + end = System.currentTimeMillis(); + System.out.println("test_mula_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_divc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divv(a0, a1, (short)-VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_divv_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_diva(a0, a1, a3); + } + end = System.currentTimeMillis(); + System.out.println("test_diva_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_andc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_andc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_andv(a0, a1, (short)BIT_MASK); + } + end = System.currentTimeMillis(); + System.out.println("test_andv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_anda(a0, a1, a4); + } + end = System.currentTimeMillis(); + System.out.println("test_anda: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_orc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_orc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_orv(a0, a1, (short)BIT_MASK); + } + end = System.currentTimeMillis(); + System.out.println("test_orv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ora(a0, a1, a4); + } + end = System.currentTimeMillis(); + System.out.println("test_ora: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_xorc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_xorc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_xorv(a0, a1, (short)BIT_MASK); + } + end = System.currentTimeMillis(); + System.out.println("test_xorv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_xora(a0, a1, a4); + } + end = System.currentTimeMillis(); + System.out.println("test_xora: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srav: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac_n(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, -VALUE); + } + end = System.currentTimeMillis(); + System.out.println("test_srav_n: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc_o(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc_o: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv_o: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc_o(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc_o: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv_o: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac_o(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac_o: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srav_o: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllc_on(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_sllc_on: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_sllv(a0, a1, -SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_sllv_on: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlc_on(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srlc_on: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srlv(a0, a1, -SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srlv_on: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srac_on(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_srac_on: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_srav(a0, a1, -SHIFT); + } + end = System.currentTimeMillis(); + System.out.println("test_srav_on: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_pack2(p2, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_pack2: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unpack2(a0, p2); + } + end = System.currentTimeMillis(); + System.out.println("test_unpack2: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_pack2_swap(p2, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_pack2_swap: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unpack2_swap(a0, p2); + } + end = System.currentTimeMillis(); + System.out.println("test_unpack2_swap: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_pack4(p4, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_pack4: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unpack4(a0, p4); + } + end = System.currentTimeMillis(); + System.out.println("test_unpack4: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_pack4_swap(p4, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_pack4_swap: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unpack4_swap(a0, p4); + } + end = System.currentTimeMillis(); + System.out.println("test_unpack4_swap: " + (end - start)); + + return errn; + } + + static int test_sum(short[] a1) { + int sum = 0; + for (int i = 0; i < a1.length; i+=1) { + sum += a1[i]; + } + return sum; + } + + static void test_addc(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]+VALUE); + } + } + static void test_addv(short[] a0, short[] a1, short b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]+b); + } + } + static void test_adda(short[] a0, short[] a1, short[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]+a2[i]); + } + } + + static void test_subc(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]-VALUE); + } + } + static void test_subv(short[] a0, short[] a1, short b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]-b); + } + } + static void test_suba(short[] a0, short[] a1, short[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]-a2[i]); + } + } + + static void test_mulc(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]*VALUE); + } + } + static void test_mulc_n(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]*(-VALUE)); + } + } + static void test_mulv(short[] a0, short[] a1, short b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]*b); + } + } + static void test_mula(short[] a0, short[] a1, short[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]*a2[i]); + } + } + + static void test_divc(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]/VALUE); + } + } + static void test_divc_n(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]/(-VALUE)); + } + } + static void test_divv(short[] a0, short[] a1, short b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]/b); + } + } + static void test_diva(short[] a0, short[] a1, short[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]/a2[i]); + } + } + + static void test_andc(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]&BIT_MASK); + } + } + static void test_andv(short[] a0, short[] a1, short b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]&b); + } + } + static void test_anda(short[] a0, short[] a1, short[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]&a2[i]); + } + } + + static void test_orc(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]|BIT_MASK); + } + } + static void test_orv(short[] a0, short[] a1, short b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]|b); + } + } + static void test_ora(short[] a0, short[] a1, short[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]|a2[i]); + } + } + + static void test_xorc(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]^BIT_MASK); + } + } + static void test_xorv(short[] a0, short[] a1, short b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]^b); + } + } + static void test_xora(short[] a0, short[] a1, short[] a2) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]^a2[i]); + } + } + + static void test_sllc(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]<<VALUE); + } + } + static void test_sllc_n(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]<<(-VALUE)); + } + } + static void test_sllc_o(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]<<SHIFT); + } + } + static void test_sllc_on(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]<<(-SHIFT)); + } + } + static void test_sllv(short[] a0, short[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]<<b); + } + } + + static void test_srlc(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]>>>VALUE); + } + } + static void test_srlc_n(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]>>>(-VALUE)); + } + } + static void test_srlc_o(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]>>>SHIFT); + } + } + static void test_srlc_on(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]>>>(-SHIFT)); + } + } + static void test_srlv(short[] a0, short[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]>>>b); + } + } + + static void test_srac(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]>>VALUE); + } + } + static void test_srac_n(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]>>(-VALUE)); + } + } + static void test_srac_o(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]>>SHIFT); + } + } + static void test_srac_on(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]>>(-SHIFT)); + } + } + static void test_srav(short[] a0, short[] a1, int b) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]>>b); + } + } + + static void test_pack2(int[] p2, short[] a1) { + if (p2.length*2 > a1.length) return; + for (int i = 0; i < p2.length; i+=1) { + int l0 = (int)a1[i*2+0]; + int l1 = (int)a1[i*2+1]; + p2[i] = (l1 << 16) | (l0 & 0xFFFF); + } + } + static void test_unpack2(short[] a0, int[] p2) { + if (p2.length*2 > a0.length) return; + for (int i = 0; i < p2.length; i+=1) { + int l = p2[i]; + a0[i*2+0] = (short)(l & 0xFFFF); + a0[i*2+1] = (short)(l >> 16); + } + } + static void test_pack2_swap(int[] p2, short[] a1) { + if (p2.length*2 > a1.length) return; + for (int i = 0; i < p2.length; i+=1) { + int l0 = (int)a1[i*2+0]; + int l1 = (int)a1[i*2+1]; + p2[i] = (l0 << 16) | (l1 & 0xFFFF); + } + } + static void test_unpack2_swap(short[] a0, int[] p2) { + if (p2.length*2 > a0.length) return; + for (int i = 0; i < p2.length; i+=1) { + int l = p2[i]; + a0[i*2+0] = (short)(l >> 16); + a0[i*2+1] = (short)(l & 0xFFFF); + } + } + + static void test_pack4(long[] p4, short[] a1) { + if (p4.length*4 > a1.length) return; + for (int i = 0; i < p4.length; i+=1) { + long l0 = (long)a1[i*4+0]; + long l1 = (long)a1[i*4+1]; + long l2 = (long)a1[i*4+2]; + long l3 = (long)a1[i*4+3]; + p4[i] = (l0 & 0xFFFFl) | + ((l1 & 0xFFFFl) << 16) | + ((l2 & 0xFFFFl) << 32) | + ((l3 & 0xFFFFl) << 48); + } + } + static void test_unpack4(short[] a0, long[] p4) { + if (p4.length*4 > a0.length) return; + for (int i = 0; i < p4.length; i+=1) { + long l = p4[i]; + a0[i*4+0] = (short)(l & 0xFFFFl); + a0[i*4+1] = (short)(l >> 16); + a0[i*4+2] = (short)(l >> 32); + a0[i*4+3] = (short)(l >> 48); + } + } + static void test_pack4_swap(long[] p4, short[] a1) { + if (p4.length*4 > a1.length) return; + for (int i = 0; i < p4.length; i+=1) { + long l0 = (long)a1[i*4+0]; + long l1 = (long)a1[i*4+1]; + long l2 = (long)a1[i*4+2]; + long l3 = (long)a1[i*4+3]; + p4[i] = (l3 & 0xFFFFl) | + ((l2 & 0xFFFFl) << 16) | + ((l1 & 0xFFFFl) << 32) | + ((l0 & 0xFFFFl) << 48); + } + } + static void test_unpack4_swap(short[] a0, long[] p4) { + if (p4.length*4 > a0.length) return; + for (int i = 0; i < p4.length; i+=1) { + long l = p4[i]; + a0[i*4+0] = (short)(l >> 48); + a0[i*4+1] = (short)(l >> 32); + a0[i*4+2] = (short)(l >> 16); + a0[i*4+3] = (short)(l & 0xFFFFl); + } + } + + static int verify(String text, int i, short elem, short val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } + + static int verify(String text, int i, int elem, int val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + Integer.toHexString(elem) + " != " + Integer.toHexString(val)); + return 1; + } + return 0; + } + + static int verify(String text, int i, long elem, long val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + Long.toHexString(elem) + " != " + Long.toHexString(val)); + return 1; + } + return 0; + } +}
--- a/test/compiler/6894807/Test6894807.sh Fri Nov 09 13:32:53 2012 +0100 +++ b/test/compiler/6894807/Test6894807.sh Fri Nov 09 13:35:26 2012 +0100 @@ -21,7 +21,7 @@ # set platform-dependent variables OS=`uname -s` case "$OS" in - SunOS | Linux ) + SunOS | Linux | Darwin ) NULL=/dev/null PS=":" FS="/" @@ -31,6 +31,11 @@ PS=";" FS="\\" ;; + CYGWIN_* ) + NULL=/dev/null + PS=";" + FS="/" + ;; * ) echo "Unrecognized system!" exit 1;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/7190310/Test7190310.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,78 @@ +/* + * 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. + * + */ + +/* + * Manual test + */ + +import java.lang.ref.*; + +public class Test7190310 { + private static Object str = new Object() { + public String toString() { + return "The Object"; + } + + protected void finalize() throws Throwable { + System.out.println("The Object is being finalized"); + super.finalize(); + } + }; + private final static ReferenceQueue<Object> rq = + new ReferenceQueue<Object>(); + private final static WeakReference<Object> wr = + new WeakReference<Object>(str, rq); + + public static void main(String[] args) + throws InterruptedException { + Thread reader = new Thread() { + public void run() { + while (wr.get() != null) { + } + System.out.println("wr.get() returned null"); + } + }; + + Thread queueReader = new Thread() { + public void run() { + try { + Reference<? extends Object> ref = rq.remove(); + System.out.println(ref); + System.out.println("queueReader returned, ref==wr is " + + (ref == wr)); + } catch (InterruptedException e) { + System.err.println("Sleep interrupted - exiting"); + } + } + }; + + reader.start(); + queueReader.start(); + + Thread.sleep(1000); + str = null; + System.gc(); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/7190310/Test7190310_unsafe.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 7190310 + * @summary Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops + * @run main/othervm -Xbatch Test7190310_unsafe + */ + +import java.lang.ref.*; +import java.lang.reflect.*; +import sun.misc.Unsafe; + +public class Test7190310_unsafe { + + static class TestObject { + public String toString() { + return "TestObject"; + } + }; + + private static TestObject str = new TestObject(); + private static final WeakReference ref = new WeakReference(str); + + private TestObject obj; + + public static void main(String[] args) throws Exception { + Class c = Test7190310_unsafe.class.getClassLoader().loadClass("sun.misc.Unsafe"); + Field f = c.getDeclaredField("theUnsafe"); + f.setAccessible(true); + Unsafe unsafe = (Unsafe)f.get(c); + + f = Reference.class.getDeclaredField("referent"); + f.setAccessible(true); + long referent_offset = unsafe.objectFieldOffset(f); + + Test7190310_unsafe t = new Test7190310_unsafe(); + TestObject o = new TestObject(); + t.obj = o; + + // Warmup (compile methods) + System.err.println("Warmup"); + Object obj = null; + for (int i = 0; i < 11000; i++) { + obj = getRef0(ref); + } + for (int i = 0; i < 11000; i++) { + obj = getRef1(unsafe, ref, referent_offset); + } + for (int i = 0; i < 11000; i++) { + obj = getRef2(unsafe, ref, referent_offset); + } + for (int i = 0; i < 11000; i++) { + obj = getRef3(unsafe, ref, referent_offset); + } + for (int i = 0; i < 11000; i++) { + obj = getRef4(unsafe, t, referent_offset); + } + + // Access verification + System.err.println("Verification"); + if (!verifyGet(referent_offset, unsafe)) { + System.exit(97); + } + + obj = getRef3(unsafe, t, referent_offset); + if (obj != o) { + System.out.println("FAILED: unsafe.getObject(Object, " + referent_offset + ") " + obj + " != " + o); + System.exit(97); + } + obj = getRef4(unsafe, t, referent_offset); + if (obj != o) { + System.out.println("FAILED: unsafe.getObject(Test7190310, " + referent_offset + ") " + obj + " != " + o); + System.exit(97); + } + } + + static boolean verifyGet(long referent_offset, Unsafe unsafe) throws Exception { + // Access verification + System.out.println("referent: " + str); + Object obj = getRef0(ref); + if (obj != str) { + System.out.println("FAILED: weakRef.get() " + obj + " != " + str); + return false; + } + obj = getRef1(unsafe, ref, referent_offset); + if (obj != str) { + System.out.println("FAILED: unsafe.getObject(weakRef, " + referent_offset + ") " + obj + " != " + str); + return false; + } + obj = getRef2(unsafe, ref, referent_offset); + if (obj != str) { + System.out.println("FAILED: unsafe.getObject(abstRef, " + referent_offset + ") " + obj + " != " + str); + return false; + } + obj = getRef3(unsafe, ref, referent_offset); + if (obj != str) { + System.out.println("FAILED: unsafe.getObject(Object, " + referent_offset + ") " + obj + " != " + str); + return false; + } + return true; + } + + static Object getRef0(WeakReference ref) throws Exception { + return ref.get(); + } + static Object getRef1(Unsafe unsafe, WeakReference ref, long referent_offset) throws Exception { + return unsafe.getObject(ref, referent_offset); + } + static Object getRef2(Unsafe unsafe, Reference ref, long referent_offset) throws Exception { + return unsafe.getObject(ref, referent_offset); + } + static Object getRef3(Unsafe unsafe, Object ref, long referent_offset) throws Exception { + return unsafe.getObject(ref, referent_offset); + } + static Object getRef4(Unsafe unsafe, Test7190310_unsafe ref, long referent_offset) throws Exception { + return unsafe.getObject(ref, referent_offset); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/7192963/TestByteVect.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 7192963 + * @summary assert(_in[req-1] == this) failed: Must pass arg count to 'new' + * + * @run main/othervm/timeout=400 -Xbatch -Xmx64m TestByteVect + */ + +public class TestByteVect { + private static final int ARRLEN = 997; + private static final int ITERS = 11000; + public static void main(String args[]) { + System.out.println("Testing Byte vectors"); + int errn = test(); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test() { + byte[] a0 = new byte[ARRLEN]; + byte[] a1 = new byte[ARRLEN]; + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1[i] = (byte)i; + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_init(a0); + test_addi(a0, a1); + test_lsai(a0, a1); + test_unrl_init(a0); + test_unrl_addi(a0, a1); + test_unrl_lsai(a0, a1); + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + test_init(a0); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_init: ", i, a0[i], (byte)(i&3)); + } + test_addi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_addi: ", i, a0[i], (byte)(i+(i&3))); + } + test_lsai(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_lsai: ", i, a0[i], (byte)(i<<(i&3))); + } + test_unrl_init(a0); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_init: ", i, a0[i], (byte)(i&3)); + } + test_unrl_addi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_addi: ", i, a0[i], (byte)(i+(i&3))); + } + test_unrl_lsai(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_lsai: ", i, a0[i], (byte)(i<<(i&3))); + } + } + + if (errn > 0) + return errn; + + System.out.println("Time"); + long start, end; + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_init(a0); + } + end = System.currentTimeMillis(); + System.out.println("test_init: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_addi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_lsai(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_lsai: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_init(a0); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_init: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_addi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_addi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_lsai(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_lsai: " + (end - start)); + + return errn; + } + + static void test_init(byte[] a0) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(i&3); + } + } + static void test_addi(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]+(i&3)); + } + } + static void test_lsai(byte[] a0, byte[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (byte)(a1[i]<<(i&3)); + } + } + static void test_unrl_init(byte[] a0) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = 0; + a0[i+1] = 1; + a0[i+2] = 2; + a0[i+3] = 3; + } + for (; i < a0.length; i++) { + a0[i] = (byte)(i&3); + } + } + static void test_unrl_addi(byte[] a0, byte[] a1) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = (byte)(a1[i+0]+0); + a0[i+1] = (byte)(a1[i+1]+1); + a0[i+2] = (byte)(a1[i+2]+2); + a0[i+3] = (byte)(a1[i+3]+3); + } + for (; i < a0.length; i++) { + a0[i] = (byte)(a1[i]+(i&3)); + } + } + static void test_unrl_lsai(byte[] a0, byte[] a1) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = (byte)(a1[i+0]<<0); + a0[i+1] = (byte)(a1[i+1]<<1); + a0[i+2] = (byte)(a1[i+2]<<2); + a0[i+3] = (byte)(a1[i+3]<<3); + } + for (; i < a0.length; i++) { + a0[i] = (byte)(a1[i]<<(i&3)); + } + } + + static int verify(String text, int i, byte elem, byte val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/7192963/TestDoubleVect.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 7192963 + * @summary assert(_in[req-1] == this) failed: Must pass arg count to 'new' + * + * @run main/othervm/timeout=400 -Xbatch -Xmx64m TestDoubleVect + */ + +public class TestDoubleVect { + private static final int ARRLEN = 997; + private static final int ITERS = 11000; + public static void main(String args[]) { + System.out.println("Testing Double vectors"); + int errn = test(); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test() { + double[] a0 = new double[ARRLEN]; + double[] a1 = new double[ARRLEN]; + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1[i] = (double)i; + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_init(a0); + test_addi(a0, a1); + test_divi(a0, a1); + test_unrl_init(a0); + test_unrl_addi(a0, a1); + test_unrl_divi(a0, a1); + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + test_init(a0); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_init: ", i, a0[i], (double)(i&3)); + } + test_addi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_addi: ", i, a0[i], (double)(i+(i&3))); + } + test_divi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divi: ", i, a0[i], (double)i/(double)((i&3)+1)); + } + test_unrl_init(a0); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_init: ", i, a0[i], (double)(i&3)); + } + test_unrl_addi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_addi: ", i, a0[i], (double)(i+(i&3))); + } + test_unrl_divi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_divi: ", i, a0[i], (double)i/(double)((i&3)+1)); + } + } + + if (errn > 0) + return errn; + + System.out.println("Time"); + long start, end; + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_init(a0); + } + end = System.currentTimeMillis(); + System.out.println("test_init: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_addi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_divi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_init(a0); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_init: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_addi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_addi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_divi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_divi: " + (end - start)); + + return errn; + } + + static void test_init(double[] a0) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (double)(i&3); + } + } + static void test_addi(double[] a0, double[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = a1[i]+(double)(i&3); + } + } + static void test_divi(double[] a0, double[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = a1[i]/(double)((i&3)+1); + } + } + static void test_unrl_init(double[] a0) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = 0.; + a0[i+1] = 1.; + a0[i+2] = 2.; + a0[i+3] = 3.; + } + for (; i < a0.length; i++) { + a0[i] = (double)(i&3); + } + } + static void test_unrl_addi(double[] a0, double[] a1) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = a1[i+0]+0.; + a0[i+1] = a1[i+1]+1.; + a0[i+2] = a1[i+2]+2.; + a0[i+3] = a1[i+3]+3.; + } + for (; i < a0.length; i++) { + a0[i] = a1[i]+(double)(i&3); + } + } + static void test_unrl_divi(double[] a0, double[] a1) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = a1[i+0]/1.; + a0[i+1] = a1[i+1]/2.; + a0[i+2] = a1[i+2]/3.; + a0[i+3] = a1[i+3]/4.; + } + for (; i < a0.length; i++) { + a0[i] = a1[i]/(double)((i&3)+1); + } + } + + static int verify(String text, int i, double elem, double val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/7192963/TestFloatVect.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 7192963 + * @summary assert(_in[req-1] == this) failed: Must pass arg count to 'new' + * + * @run main/othervm/timeout=400 -Xbatch -Xmx64m TestFloatVect + */ + +public class TestFloatVect { + private static final int ARRLEN = 997; + private static final int ITERS = 11000; + public static void main(String args[]) { + System.out.println("Testing Float vectors"); + int errn = test(); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test() { + float[] a0 = new float[ARRLEN]; + float[] a1 = new float[ARRLEN]; + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1[i] = (float)i; + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_init(a0); + test_addi(a0, a1); + test_divi(a0, a1); + test_unrl_init(a0); + test_unrl_addi(a0, a1); + test_unrl_divi(a0, a1); + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + test_init(a0); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_init: ", i, a0[i], (float)(i&3)); + } + test_addi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_addi: ", i, a0[i], (float)(i+(i&3))); + } + test_divi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_divi: ", i, a0[i], (float)i/(float)((i&3)+1)); + } + test_unrl_init(a0); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_init: ", i, a0[i], (float)(i&3)); + } + test_unrl_addi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_addi: ", i, a0[i], (float)(i+(i&3))); + } + test_unrl_divi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_divi: ", i, a0[i], (float)i/(float)((i&3)+1)); + } + } + + if (errn > 0) + return errn; + + System.out.println("Time"); + long start, end; + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_init(a0); + } + end = System.currentTimeMillis(); + System.out.println("test_init: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_addi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_divi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_divi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_init(a0); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_init: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_addi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_addi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_divi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_divi: " + (end - start)); + + return errn; + } + + static void test_init(float[] a0) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (float)(i&3); + } + } + static void test_addi(float[] a0, float[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = a1[i]+(float)(i&3); + } + } + static void test_divi(float[] a0, float[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = a1[i]/(float)((i&3)+1); + } + } + static void test_unrl_init(float[] a0) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = 0.f; + a0[i+1] = 1.f; + a0[i+2] = 2.f; + a0[i+3] = 3.f; + } + for (; i < a0.length; i++) { + a0[i] = (float)(i&3); + } + } + static void test_unrl_addi(float[] a0, float[] a1) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = a1[i+0]+0.f; + a0[i+1] = a1[i+1]+1.f; + a0[i+2] = a1[i+2]+2.f; + a0[i+3] = a1[i+3]+3.f; + } + for (; i < a0.length; i++) { + a0[i] = a1[i]+(float)(i&3); + } + } + static void test_unrl_divi(float[] a0, float[] a1) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = a1[i+0]/1.f; + a0[i+1] = a1[i+1]/2.f; + a0[i+2] = a1[i+2]/3.f; + a0[i+3] = a1[i+3]/4.f; + } + for (; i < a0.length; i++) { + a0[i] = a1[i]/(float)((i&3)+1); + } + } + + static int verify(String text, int i, float elem, float val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/7192963/TestIntVect.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 7192963 + * @summary assert(_in[req-1] == this) failed: Must pass arg count to 'new' + * + * @run main/othervm/timeout=400 -Xbatch -Xmx64m TestIntVect + */ + +public class TestIntVect { + private static final int ARRLEN = 997; + private static final int ITERS = 11000; + public static void main(String args[]) { + System.out.println("Testing Integer vectors"); + int errn = test(); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test() { + int[] a0 = new int[ARRLEN]; + int[] a1 = new int[ARRLEN]; + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1[i] = i; + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_init(a0); + test_addi(a0, a1); + test_lsai(a0, a1); + test_unrl_init(a0); + test_unrl_addi(a0, a1); + test_unrl_lsai(a0, a1); + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + test_init(a0); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_init: ", i, a0[i], (i&3)); + } + test_addi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_addi: ", i, a0[i], (i+(i&3))); + } + test_lsai(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_lsai: ", i, a0[i], (i<<(i&3))); + } + test_unrl_init(a0); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_init: ", i, a0[i], (i&3)); + } + test_unrl_addi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_addi: ", i, a0[i], (i+(i&3))); + } + test_unrl_lsai(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_lsai: ", i, a0[i], (i<<(i&3))); + } + } + + if (errn > 0) + return errn; + + System.out.println("Time"); + long start, end; + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_init(a0); + } + end = System.currentTimeMillis(); + System.out.println("test_init: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_addi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_lsai(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_lsai: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_init(a0); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_init: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_addi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_addi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_lsai(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_lsai: " + (end - start)); + + return errn; + } + + static void test_init(int[] a0) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (i&3); + } + } + static void test_addi(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = a1[i]+(i&3); + } + } + static void test_lsai(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = a1[i]<<(i&3); + } + } + static void test_unrl_init(int[] a0) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = 0; + a0[i+1] = 1; + a0[i+2] = 2; + a0[i+3] = 3; + } + for (; i < a0.length; i++) { + a0[i] = (i&3); + } + } + static void test_unrl_addi(int[] a0, int[] a1) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = a1[i+0]+0; + a0[i+1] = a1[i+1]+1; + a0[i+2] = a1[i+2]+2; + a0[i+3] = a1[i+3]+3; + } + for (; i < a0.length; i++) { + a0[i] = a1[i]+(i&3); + } + } + static void test_unrl_lsai(int[] a0, int[] a1) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = a1[i+0]<<0; + a0[i+1] = a1[i+1]<<1; + a0[i+2] = a1[i+2]<<2; + a0[i+3] = a1[i+3]<<3; + } + for (; i < a0.length; i++) { + a0[i] = a1[i]<<(i&3); + } + } + + static int verify(String text, int i, int elem, int val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/7192963/TestLongVect.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 7192963 + * @summary assert(_in[req-1] == this) failed: Must pass arg count to 'new' + * + * @run main/othervm/timeout=400 -Xbatch -Xmx64m TestLongVect + */ + +public class TestLongVect { + private static final int ARRLEN = 997; + private static final int ITERS = 11000; + public static void main(String args[]) { + System.out.println("Testing Long vectors"); + int errn = test(); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test() { + long[] a0 = new long[ARRLEN]; + long[] a1 = new long[ARRLEN]; + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1[i] = (long)i; + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_init(a0); + test_addi(a0, a1); + test_lsai(a0, a1); + test_unrl_init(a0); + test_unrl_addi(a0, a1); + test_unrl_lsai(a0, a1); + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + test_init(a0); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_init: ", i, a0[i], (long)(i&3)); + } + test_addi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_addi: ", i, a0[i], (long)(i+(i&3))); + } + test_lsai(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_lsai: ", i, a0[i], (long)(i<<(i&3))); + } + test_unrl_init(a0); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_init: ", i, a0[i], (long)(i&3)); + } + test_unrl_addi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_addi: ", i, a0[i], (long)(i+(i&3))); + } + test_unrl_lsai(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_lsai: ", i, a0[i], (long)(i<<(i&3))); + } + } + + if (errn > 0) + return errn; + + System.out.println("Time"); + long start, end; + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_init(a0); + } + end = System.currentTimeMillis(); + System.out.println("test_init: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_addi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_lsai(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_lsai: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_init(a0); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_init: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_addi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_addi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_lsai(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_lsai: " + (end - start)); + + return errn; + } + + static void test_init(long[] a0) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(i&3); + } + } + static void test_addi(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]+(i&3)); + } + } + static void test_lsai(long[] a0, long[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (long)(a1[i]<<(i&3)); + } + } + static void test_unrl_init(long[] a0) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = 0; + a0[i+1] = 1; + a0[i+2] = 2; + a0[i+3] = 3; + } + for (; i < a0.length; i++) { + a0[i] = (long)(i&3); + } + } + static void test_unrl_addi(long[] a0, long[] a1) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = (long)(a1[i+0]+0); + a0[i+1] = (long)(a1[i+1]+1); + a0[i+2] = (long)(a1[i+2]+2); + a0[i+3] = (long)(a1[i+3]+3); + } + for (; i < a0.length; i++) { + a0[i] = (long)(a1[i]+(i&3)); + } + } + static void test_unrl_lsai(long[] a0, long[] a1) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = (long)(a1[i+0]<<0); + a0[i+1] = (long)(a1[i+1]<<1); + a0[i+2] = (long)(a1[i+2]<<2); + a0[i+3] = (long)(a1[i+3]<<3); + } + for (; i < a0.length; i++) { + a0[i] = (long)(a1[i]<<(i&3)); + } + } + + static int verify(String text, int i, long elem, long val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/7192963/TestShortVect.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 7192963 + * @summary assert(_in[req-1] == this) failed: Must pass arg count to 'new' + * + * @run main/othervm/timeout=400 -Xbatch -Xmx64m TestShortVect + */ + +public class TestShortVect { + private static final int ARRLEN = 997; + private static final int ITERS = 11000; + public static void main(String args[]) { + System.out.println("Testing Short vectors"); + int errn = test(); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test() { + short[] a0 = new short[ARRLEN]; + short[] a1 = new short[ARRLEN]; + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1[i] = (short)i; + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_init(a0); + test_addi(a0, a1); + test_lsai(a0, a1); + test_unrl_init(a0); + test_unrl_addi(a0, a1); + test_unrl_lsai(a0, a1); + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + test_init(a0); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_init: ", i, a0[i], (short)(i&3)); + } + test_addi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_addi: ", i, a0[i], (short)(i+(i&3))); + } + test_lsai(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_lsai: ", i, a0[i], (short)(i<<(i&3))); + } + test_unrl_init(a0); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_init: ", i, a0[i], (short)(i&3)); + } + test_unrl_addi(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_addi: ", i, a0[i], (short)(i+(i&3))); + } + test_unrl_lsai(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_unrl_lsai: ", i, a0[i], (short)(i<<(i&3))); + } + } + + if (errn > 0) + return errn; + + System.out.println("Time"); + long start, end; + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_init(a0); + } + end = System.currentTimeMillis(); + System.out.println("test_init: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_addi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_addi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_lsai(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_lsai: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_init(a0); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_init: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_addi(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_addi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_unrl_lsai(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_unrl_lsai: " + (end - start)); + + return errn; + } + + static void test_init(short[] a0) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(i&3); + } + } + static void test_addi(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]+(i&3)); + } + } + static void test_lsai(short[] a0, short[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (short)(a1[i]<<(i&3)); + } + } + static void test_unrl_init(short[] a0) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = 0; + a0[i+1] = 1; + a0[i+2] = 2; + a0[i+3] = 3; + } + for (; i < a0.length; i++) { + a0[i] = (short)(i&3); + } + } + static void test_unrl_addi(short[] a0, short[] a1) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = (short)(a1[i+0]+0); + a0[i+1] = (short)(a1[i+1]+1); + a0[i+2] = (short)(a1[i+2]+2); + a0[i+3] = (short)(a1[i+3]+3); + } + for (; i < a0.length; i++) { + a0[i] = (short)(a1[i]+(i&3)); + } + } + static void test_unrl_lsai(short[] a0, short[] a1) { + int i = 0; + for (; i < a0.length-4; i+=4) { + a0[i+0] = (short)(a1[i+0]<<0); + a0[i+1] = (short)(a1[i+1]<<1); + a0[i+2] = (short)(a1[i+2]<<2); + a0[i+3] = (short)(a1[i+3]<<3); + } + for (; i < a0.length; i++) { + a0[i] = (short)(a1[i]<<(i&3)); + } + } + + static int verify(String text, int i, short elem, short val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } +} +
--- a/test/gc/6941923/test6941923.sh Fri Nov 09 13:32:53 2012 +0100 +++ b/test/gc/6941923/test6941923.sh Fri Nov 09 13:35:26 2012 +0100 @@ -9,12 +9,12 @@ ## skip on windows OS=`uname -s` case "$OS" in - SunOS | Linux ) + SunOS | Linux | Darwin ) NULL=/dev/null PS=":" FS="/" ;; - Windows_* ) + Windows_* | CYGWIN_* ) echo "Test skipped for Windows" exit 0 ;;
--- a/test/runtime/6626217/Test6626217.sh Fri Nov 09 13:32:53 2012 +0100 +++ b/test/runtime/6626217/Test6626217.sh Fri Nov 09 13:35:26 2012 +0100 @@ -49,7 +49,7 @@ # set platform-dependent variables OS=`uname -s` case "$OS" in - SunOS | Linux ) + SunOS | Linux | Darwin ) NULL=/dev/null PS=":" FS="/" @@ -65,6 +65,14 @@ CP=cp MV=mv ;; + CYGWIN_* ) + NULL=/dev/null + PS=";" + FS="/" + RM=rm + CP=cp + MV=mv + ;; * ) echo "Unrecognized system!" exit 1;
--- a/test/runtime/6878713/Test6878713.sh Fri Nov 09 13:32:53 2012 +0100 +++ b/test/runtime/6878713/Test6878713.sh Fri Nov 09 13:35:26 2012 +0100 @@ -28,7 +28,7 @@ # set platform-dependent variables OS=`uname -s` case "$OS" in - SunOS | Linux ) + SunOS | Linux | Darwin ) NULL=/dev/null PS=":" FS="/" @@ -38,6 +38,11 @@ PS=";" FS="\\" ;; + CYGWIN_* ) + NULL=/dev/null + PS=";" + FS="/" + ;; * ) echo "Unrecognized system!" exit 1;
--- a/test/runtime/6929067/Test6929067.sh Fri Nov 09 13:32:53 2012 +0100 +++ b/test/runtime/6929067/Test6929067.sh Fri Nov 09 13:35:26 2012 +0100 @@ -27,17 +27,10 @@ PS=":" FS="/" ;; - SunOS | Windows_* | *BSD) - NULL=NUL - PS=";" - FS="\\" + * ) echo "Test passed; only valid for Linux" exit 0; ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; esac # Choose arch: i386 or amd64 (test is Linux-specific)
--- a/test/runtime/7020373/Test7020373.sh Fri Nov 09 13:32:53 2012 +0100 +++ b/test/runtime/7020373/Test7020373.sh Fri Nov 09 13:35:26 2012 +0100 @@ -40,6 +40,11 @@ PS=";" FS="\\" ;; + CYGWIN_* ) + NULL=/dev/null + PS=";" + FS="/" + ;; * ) echo "Unrecognized system!" exit 1;
--- a/test/runtime/7051189/Xchecksig.sh Fri Nov 09 13:32:53 2012 +0100 +++ b/test/runtime/7051189/Xchecksig.sh Fri Nov 09 13:35:26 2012 +0100 @@ -43,10 +43,10 @@ OS=`uname -s` case "$OS" in - SunOS | Linux ) + SunOS | Linux | Darwin ) FS="/" ;; - Windows_* ) + Windows_* | CYGWIN_* ) printf "Not testing libjsig.so on Windows. PASSED.\n " exit 0 ;;
--- a/test/runtime/7110720/Test7110720.sh Fri Nov 09 13:32:53 2012 +0100 +++ b/test/runtime/7110720/Test7110720.sh Fri Nov 09 13:35:26 2012 +0100 @@ -37,7 +37,7 @@ # set platform-dependent variables OS=`uname -s` case "$OS" in - SunOS | Linux ) + SunOS | Linux | Darwin ) FS="/" RM=/bin/rm CP=/bin/cp @@ -55,6 +55,12 @@ CP=cp MV=mv ;; + CYGWIN_* ) + FS="/" + RM=rm + CP=cp + MV=mv + ;; * ) echo "Unrecognized system!" exit 1;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/7116786/Test7116786.java Fri Nov 09 13:35:26 2012 +0100 @@ -0,0 +1,486 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test Test7116786 + * @summary verify that VerifyError messages are as expected + * @library testcases.jar + * @run main/othervm -Xverify:all Test7116786 + */ + + +/** + * This class contains information regarding when a VerifyError is thrown + * in the verifier. Most of the data is informational-only, and can be + * used to track down where and why VerifyErrors are thrown. As such it + * is possible the information may go out-of-date. + * + * The only fields used for the purpose of testing is the 'caseName' and + * the 'message'. The 'caseName' corresponds to a classfile which exhibits + * the VerifyError, and the 'message' is a regular expression which we expect + * to match the verify error message. If the 'message' doesn't match what + * we expect, it warrents investigation to see if we are still triggering + * the VerifyError that we expect. It could simply just be that the message + * changed, which is fine. + * + * Some cases are not testable, either because the code is probably unreachable + * or the test classfile would be too onerous to create. These cases are + * marked with 'testable' == false, and the test runner will skip them. + */ +class Case { + private String caseName; // Name of the case + private String file; // Source file where VerifyError is thrown + private String location; // enclosing function or switch case + private String description; // What causes this VerifyError + private String message; // The VerifyError message used. + + private boolean testable; // Whether this case is testable or not. + + public Case(String caseName, String file, boolean testable, + String location, String description, String message) { + this.caseName = caseName; + this.file = file; + this.testable = testable; + this.location = location; + this.description = description; + this.message = message; + } + + String getCaseName() { return this.caseName; } + String getFile() { return this.file; } + String getLocation() { return this.location; } + String getDescription() { return this.description; } + String getMessage() { return this.message; } + + boolean isTestable() { return this.testable; } +} + +/** + * These are the locations in the source code where VerifyErrors are thrown + * as of today, 2012/07/18. These may change as the verification code is + * modified, which is ok. This test is trying to provide coverage for all + * VerifyErrors (just to make sure there are no crashes) and it's probably + * not necessary to update it every time the VM changes. + */ +class VerifyErrorCases { + public static final Case[] cases = { + + new Case("case00", "stackMapFrame.cpp", true, "pop_stack_ex", + "stack underflow", + "Operand stack underflow"), + + new Case("case01", "stackMapFrame.cpp", true, "pop_stack_ex", + "stack pop not assignable to expected", + "Bad type on operand stack"), + + new Case("case02", "stackMapFrame.cpp", true, "get_local", + "local index out-of-bounds", + "Local variable table overflow"), + + new Case("case03", "stackMapFrame.cpp", true, "get_local", + "local not assignable to expected", + "Bad local variable type"), + + new Case("case04", "stackMapFrame.cpp", true, "get_local_2", + "local index out-of-bounds [type2]", + "get long/double overflows locals"), + + new Case("case05", "stackMapFrame.cpp", true, "get_local_2", + "local not assignabled to expected [type2]", + "Bad local variable type"), + + /* Unreachable: Can't split long/double on stack */ + new Case("case06", "stackMapFrame.cpp", false, "get_local_2", + "local second-word not assignabled to expected", + "Bad local variable type"), + + new Case("case07", "stackMapFrame.cpp", true, "set_local", + "local index out-of-bounds", + "Local variable table overflow"), + + new Case("case08", "stackMapFrame.cpp", true, "set_local_2", + "local index out-of-bounds [type2]", + "Local variable table overflow"), + + new Case("case09", "stackMapFrame.hpp", true, "push_stack", + "stack overflow", + "Operand stack overflow"), + + new Case("case10", "stackMapFrame.hpp", true, "push_stack_2", + "stack overflow [type2]", + "Operand stack overflow"), + + new Case("case11", "stackMapFrame.hpp", true, "pop_stack", + "stack underflow", + "Operand stack underflow"), + + new Case("case12", "stackMapTable.cpp", true, "StackMapTable ctor", + "stackmap offset beyond code size", + "StackMapTable error: bad offset"), + + new Case("case13", "stackMapTable.cpp", true, "match_stackmap", + "no stackmap frame at expected location", + "Expecting a stackmap frame at branch target "), + + new Case("case14", "stackMapTable.cpp", true, "check_jump_target", + "no stackmap frame at jump location or bad jump", + "Inconsistent stackmap frames at branch target "), + + new Case("case15", "stackMapTable.cpp", true, "check_new_object", + "backward jump with uninit", + "Uninitialized object exists on backward branch "), + + /* Unreachable: wide instructions verified during bytecode analysis */ + new Case("case16", "verifier.cpp", false, "loop header", + "bad op in wide instruction", + "Bad wide instruction"), + + new Case("case17", "verifier.cpp", true, "case iaload", + "TOS not X array", + "Bad type on operand stack in iaload"), + + new Case("case18", "verifier.cpp", true, "case baload", + "TOS not X array", + "Bad type on operand stack in baload"), + + new Case("case19", "verifier.cpp", true, "case caload", + "TOS not X array", + "Bad type on operand stack in caload"), + + new Case("case20", "verifier.cpp", true, "case saload", + "TOS not X array", + "Bad type on operand stack in saload"), + + new Case("case21", "verifier.cpp", true, "case laload", + "TOS not X array", + "Bad type on operand stack in laload"), + + new Case("case22", "verifier.cpp", true, "case faload", + "TOS not X array", + "Bad type on operand stack in faload"), + + new Case("case23", "verifier.cpp", true, "case daload", + "TOS not X array", + "Bad type on operand stack in daload"), + + new Case("case24", "verifier.cpp", true, "case aaload", + "TOS not X array", + "Bad type on operand stack in aaload"), + + new Case("case25", "verifier.cpp", true, "case iastore", + "TOS not int array", + "Bad type on operand stack in iastore"), + + new Case("case26", "verifier.cpp", true, "case bastore", + "TOS not byte array", + "Bad type on operand stack in bastore"), + + new Case("case27", "verifier.cpp", true, "case castore", + "TOS not char array", + "Bad type on operand stack in castore"), + + new Case("case28", "verifier.cpp", true, "case sastore", + "TOS not short array", + "Bad type on operand stack in sastore"), + + new Case("case29", "verifier.cpp", true, "case lastore", + "TOS not long array", + "Bad type on operand stack in lastore"), + + new Case("case30", "verifier.cpp", true, "case fastore", + "TOS not float array", + "Bad type on operand stack in fastore"), + + new Case("case31", "verifier.cpp", true, "case dastore", + "TOS not double array", + "Bad type on operand stack in dastore"), + + new Case("case32", "verifier.cpp", true, "case aastore", + "TOS not object array", + "Bad type on operand stack in aastore"), + + /* Unreachable: In order to hit this case, we would need a + * category2_1st at TOS which is not possible. */ + new Case("case33", "verifier.cpp", false, "case pop2", + "TOS is category2_1st (would split)", + "Bad type on operand stack in pop2"), + + /* Unreachable: In order to hit this case, we would need a + * category2_1st at stack depth 2 with category_1 on TOS which is not + * possible. */ + new Case("case34", "verifier.cpp", false, "case dup_x2", + "TOS-1 is category2_1st (would split)", + "Bad type on operand stack in dup_x2"), + + /* Unreachable: In order to hit this case, we would need a + * category2_1st at TOS which is not possible. */ + new Case("case35", "verifier.cpp", false, "case dup2", + "TOS-1 is category2_1st (would split)", + "Bad type on operand stack in dup2"), + + /* Unreachable: In order to hit this case, we would need a + * category2_1st at TOS which is not possible. */ + new Case("case36", "verifier.cpp", false, "case dup2_x1", + "TOS-1 is category2_1st (would split)", + "Bad type on operand stack in dup2_x1"), + + /* Unreachable: In order to hit this case, we would need a + * category2_1st at TOS which is not possible. */ + new Case("case37", "verifier.cpp", false, "case dup2_x2", + "TOS-1 is category2_1st (would split)", + "Bad type on operand stack in dup2_x2"), + + /* Unreachable: In order to hit this case, we would need a + * category2_1st at stack depth 3 with either 2 category_1 or 1 + * category_2 on TOS, which is not possible. */ + new Case("case38", "verifier.cpp", false, "case dup2_x2", + "TOS-3 is category2_1st (would split)", + "Bad type on operand stack in dup2_x2"), + + new Case("case39", "verifier.cpp", true, "case return", + "return type of method is not void", + "Method expects a return value"), + + new Case("case40", "verifier.cpp", true, "case return", + "return with uninitialized this ", + "Constructor must call super() or this() before return"), + + new Case("case41", "verifier.cpp", true, "case new", + "cp index not a class type", + "Illegal new instruction"), + + new Case("case42", "verifier.cpp", true, "case arraylength", + "TOS is not an array", + "Bad type on operand stack in arraylength"), + + new Case("case43", "verifier.cpp", true, "case multianewarray", + "CP index does not refer to array type", + "Illegal constant pool index in multianewarray instruction"), + + new Case("case44", "verifier.cpp", true, "case multianewarray", + "Bad dimension (<1) or does not match CP signature", + "Illegal dimension in multianewarray instruction: "), + + new Case("case45", "verifier.cpp", true, "case default", + "Unrecognized bytecode", + "Bad instruction: "), + + new Case("case46", "verifier.cpp", true, "loop end", + "control flow falls off method", + "Control flow falls through code end"), + + new Case("case47", "verifier.cpp", true, "generate_code_data", + "illegal bytecode via RawBytecodeStream (breakpoint)", + "Bad instruction"), + + new Case("case48", "verifier.cpp", true, "generate_code_data", + "illegal bytecode via RawBytecodeStream (other illegal)", + "Bad instruction"), + + new Case("case49", "verifier.cpp", true, + "verify_exception_handler_table", + "catch_type is not throwable", + "Catch type is not a subclass of Throwable in " + + "exception handler "), + + new Case("case50", "verifier.cpp", true, "verify_stackmap_table", + "missing a stack map frame @ target location (mid table)", + "Expecting a stack map frame"), + + new Case("case51", "verifier.cpp", true, "verify_stackmap_table", + "stack map does not match?", + "Instruction type does not match stack map"), + + new Case("case52", "verifier.cpp", true, "verify_stackmap_table", + "missing a stack map frame @ target location (end of table)", + "Expecting a stack map frame"), + + new Case("case53", "verifier.cpp", true, + "verify_exception_handler_targets", + "stackmap mismatch at exception handler", + "Stack map does not match the one at exception handler "), + + new Case("case54", "verifier.cpp", true, "verify_cp_index", + "constant pool index is out-of-bounds", + "Illegal constant pool index "), + + new Case("case55", "verifier.cpp", true, "verify_cp_type", + "constant pool entry is not expected type", + "Illegal type at constant pool entry "), + + new Case("case56", "verifier.cpp", true, "verify_cp_class_type", + "constant pool entry is not an object type", + "Illegal type at constant pool entry "), + + /* Unreachable: verify_cp_type gates this case */ + new Case("case57", "verifier.cpp", false, "verify_ldc", + "invalid constant pool index in ldc", + "Invalid index in ldc"), + + new Case("case58", "verifier.cpp", true, "verify_switch", + "bad switch padding", + "Nonzero padding byte in lookswitch or tableswitch"), + + new Case("case59", "verifier.cpp", true, "verify_switch", + "tableswitch low is greater than high", + "low must be less than or equal to high in tableswitch"), + + /* Unreachable on 64-bit? Only way to get here is to overflow + * the 'keys' variable which can't happen on 64-bit since we're dealing + * with 32-bit values. Perhaps reachable on 32-bit but the + * triggering class would be quite large */ + new Case("case60", "verifier.cpp", false, "verify_switch", + "high - low + 1 < 0 (overflow?)", + "too many keys in tableswitch"), + + /* Would have to create a 16G classfile to trip this. Possible but + * not reasonable to do in a test. */ + new Case("case61", "verifier.cpp", false, "verify_switch", + "lookupswitch keys < 0", + "number of keys in lookupswitch less than 0"), + + new Case("case62", "verifier.cpp", true, "verify_switch", + "lookupswitch keys out-of-order", + "Bad lookupswitch instruction"), + + /* Unreachable: Class file parser verifies Fieldref contents */ + new Case("case63", "verifier.cpp", false, "verify_field_instructions", + "referenced class is not an CP object", + "Expecting reference to class in class "), + + new Case("case64", "verifier.cpp", true, "verify_field_instructions", + "TOS not assignable to field type in putfield", + "Bad type on operand stack in putfield"), + + new Case("case65", "verifier.cpp", true, "verify_field_instructions", + "TOS not assignable to class when accessing protected field", + "Bad access to protected data in getfield"), + + new Case("case66", "verifier.cpp", true, "verify_invoke_init", + "Uninit_this is not of the current type or it's supertype", + "Bad <init> method call"), + + /* Unreachable: Stack map parsing ensures valid type and new + * instructions have a valid BCI. */ + new Case("case67", "verifier.cpp", false, "verify_invoke_init", + "Uninit type with bad new instruction index", + "Expecting new instruction"), + + new Case("case68", "verifier.cpp", true, "verify_invoke_init", + "calling other class's <init> method", + "Call to wrong <init> method"), + + new Case("case69", "verifier.cpp", true, "verify_invoke_init", + "Calling protected <init> and type unassignable from current", + "Bad access to protected <init> method"), + + new Case("case70", "verifier.cpp", true, "verify_invoke_init", + "TOS is not an uninitialized (or Uninit_this) type", + "Bad operand type when invoking <init>"), + + new Case("case71", "verifier.cpp", true, "verify_invoke_instructions", + "Arg count in instruction doesn't match signature", + "Inconsistent args count operand in invokeinterface"), + + new Case("case72", "verifier.cpp", true, "verify_invoke_instructions", + "Non-zero pad in invokeinterface", + "Fourth operand byte of invokeinterface must be zero"), + + new Case("case73", "verifier.cpp", true, "verify_invoke_instructions", + "Non-zero pad in invokedynamic", + "Third and fourth operand bytes of " + + "invokedynamic must be zero"), + + new Case("case74", "verifier.cpp", true, "verify_invoke_instructions", + "Non-invokespecial trying to invoke a '<' method", + "Illegal call to internal method"), + + new Case("case75", "verifier.cpp", true, "verify_invoke_instructions", + "invokespecial and current unassignable from referenced type", + "Bad invokespecial instruction: current class isn't " + + "assignable to reference class."), + + new Case("case76", "verifier.cpp", true, "verify_invoke_instructions", + "TOS not assignable to current when calling protected method", + "Bad access to protected data in invokevirtual"), + + /* Unreachable: class file parser enforces void signature */ + new Case("case77", "verifier.cpp", false, "verify_invoke_instructions", + "<init> method is not void return", + "Return type must be void in <init> method"), + + new Case("case78", "verifier.cpp", true, "get_newarray_type", + "newarray type invalid", + "Illegal newarray instruction"), + + new Case("case79", "verifier.cpp", true, "verify_return_value", + "void return from method which has a return value", + "Method expects a return value"), + + new Case("case80", "verifier.cpp", true, "verify_return_value", + "TOS type does not match signature", + "Bad return type"), + + new Case("case81", "verifier.cpp", true, "verify_stackmap_table", + "stack map does not match (flags)", + "Instruction type does not match stack map") + }; +} + +public class Test7116786 { + public static void main(String argv[]) throws Exception { + for (Case c : VerifyErrorCases.cases) { + System.out.println("******** " + c.getCaseName() + " ********"); + if (c.isTestable()) { + try { + ClassLoader cl = Test7116786.class.getClassLoader(); + Class<?> cls = Class.forName(c.getCaseName(), true, cl); + throw new RuntimeException( + "++ FAIL: No verify error encountered"); + } catch (VerifyError ve) { + String message = c.getMessage(); + String veMessage = ve.getMessage(); + System.out.print(veMessage); + if (!veMessage.startsWith(message)) { + // We're not seeing the message we expect. Could be + // that we've gotten the wrong VerifyError case, or + // maybe the message changed. + System.out.println("++ FAIL? " + + "Message does not match what was expected: " + + message); + continue; + } + if (!veMessage.contains("Exception Details:") && + !veMessage.contains("Reason:")) { + System.out.println("++ FAIL: No details found"); + throw new RuntimeException("FAIL: No details found"); + } + System.out.println("++ PASS"); + } + } else { + System.out.println("++ SKIPPED"); + } + } + } +}
--- a/test/runtime/7158800/Test7158800.sh Fri Nov 09 13:32:53 2012 +0100 +++ b/test/runtime/7158800/Test7158800.sh Fri Nov 09 13:35:26 2012 +0100 @@ -46,7 +46,7 @@ # set platform-dependent variables OS=`uname -s` case "$OS" in - SunOS | Linux ) + SunOS | Linux | Darwin ) NULL=/dev/null PS=":" FS="/" @@ -56,6 +56,11 @@ PS=";" FS="\\" ;; + CYGWIN_* ) + NULL=/dev/null + PS=";" + FS="/" + ;; * ) echo "Unrecognized system!" exit 1; @@ -67,13 +72,13 @@ THIS_DIR=`pwd` -${TESTJAVA}${FS}bin${FS}java -fullversion +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -fullversion ${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}InternTest.java cp ${TESTSRC}${FS}badstrings.txt . -${TESTJAVA}${FS}bin${FS}java -XX:+PrintStringTableStatistics -XX:+TraceSafepointCleanupTime InternTest bad > test.out 2>&1 & +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -XX:+PrintStringTableStatistics -XX:+TraceSafepointCleanupTime InternTest bad > test.out 2>&1 & C_PID=$! sleep 60
--- a/test/runtime/7158988/TestFieldMonitor.sh Fri Nov 09 13:32:53 2012 +0100 +++ b/test/runtime/7158988/TestFieldMonitor.sh Fri Nov 09 13:35:26 2012 +0100 @@ -21,7 +21,7 @@ # set platform-dependent variables OS=`uname -s` case "$OS" in - SunOS | Linux ) + SunOS | Linux | Darwin) NULL=/dev/null PS=":" FS="/" @@ -38,6 +38,18 @@ PS=";" FS="\\" ;; + CYGWIN_NT* ) + NULL=/dev/null + PS=";" + FS="/" + ;; + CYGWIN_* ) + NULL=/dev/null + PS=";" + FS="/" + echo "Test skipped, only for WinNT" + exit 0 + ;; * ) echo "Unrecognized system!" exit 1; @@ -52,30 +64,7 @@ ${TESTJAVA}${FS}bin${FS}javac -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar *.java -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar FieldMonitor > test.out 2>&1 & - -P_PID=$! - -sleep 60 -STATUS=0 - -case "$OS" in - SunOS | Linux ) - ps -ef | grep $P_PID | grep -v grep > ${NULL} - if [ $? = 0 ]; then - kill -9 $P_PID - STATUS=1 - fi - ;; - * ) - ps | grep -i "FieldMonitor" | grep -v grep > ${NULL} - if [ $? = 0 ]; then - C_PID=`ps | grep -i "FieldMonitor" | awk '{print $1}'` - kill -s 9 $C_PID - STATUS=1 - fi - ;; -esac +${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar FieldMonitor > test.out grep "A fatal error has been detected" test.out > ${NULL} if [ $? = 0 ]; then