diff --git a/.hgtags b/.hgtags index 649cfd98a86..1e380877a67 100644 --- a/.hgtags +++ b/.hgtags @@ -175,3 +175,5 @@ cecd7026f30cbd83b0601925a7a5e059aec98138 jdk8-b49 382651d28f2502d371eca751962232c0e535e57a jdk8-b51 b67041a6cb508da18d2f5c7687e6a31e08bea4fc jdk8-b52 c7aa5cca1c01689a7b1a92411daf83684af05a33 jdk8-b53 +7c6aa31ff1b2ae48c1c686ebe1aadf0c3da5be15 jdk8-b54 +319f583f66db47395fa86127dd3ddb729eb7c64f jdk8-b55 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 8e85f0c6a28..c1eee4053a2 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -175,3 +175,5 @@ c97b99424815c43818e3cc3ffcdd1a60f3198b52 jdk8-b49 57c0aee7309050b9d6cfcbd202dc704e9260b377 jdk8-b51 8d24def5ceb3b8f2e857f2e18b2804fc59eecf8d jdk8-b52 febd7ff5280067ca482faaeb9418ae88764c1a35 jdk8-b53 +c1a277c6022affbc6855bdfb039511e73fbe2395 jdk8-b54 +b85b44cced2406792cfb9baab1377ff03e7001d8 jdk8-b55 diff --git a/corba/.hgtags b/corba/.hgtags index 6a188eead8e..ac231ffd80f 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -175,3 +175,5 @@ d20d9eb9f093adbf392918c703960ad24c93a331 jdk8-b50 9b0f841ca9f7ee9bacf16a5ab41c4f829276bc6b jdk8-b51 80689ff9cb499837513f18a1136dac7f0686cd55 jdk8-b52 63aeb7a2472fb299134ad7388e0a111a5340b02d jdk8-b53 +16c82fc74695bab9b9e0fb05c086a5a08ba0082f jdk8-b54 +e8a0e84383d6fbd303ce44bd355fb25972b13286 jdk8-b55 diff --git a/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaResponseWaitingRoomImpl.java b/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaResponseWaitingRoomImpl.java index ce0752df09e..57104f297eb 100644 --- a/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaResponseWaitingRoomImpl.java +++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/CorbaResponseWaitingRoomImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2004, 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,10 @@ package com.sun.corba.se.impl.transport; -import java.util.Hashtable; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; import org.omg.CORBA.CompletionStatus; import org.omg.CORBA.SystemException; @@ -68,7 +71,7 @@ public class CorbaResponseWaitingRoomImpl private CorbaConnection connection; // Maps requestId to an OutCallDesc. - private Hashtable out_calls = null; // REVISIT - use int hastable/map + final private Map<Integer, OutCallDesc> out_calls; public CorbaResponseWaitingRoomImpl(ORB orb, CorbaConnection connection) { @@ -76,7 +79,8 @@ public class CorbaResponseWaitingRoomImpl wrapper = ORBUtilSystemException.get( orb, CORBALogDomains.RPC_TRANSPORT ) ; this.connection = connection; - out_calls = new Hashtable(); + out_calls = + Collections.synchronizedMap(new HashMap<Integer, OutCallDesc>()); } //////////////////////////////////////////////////// @@ -139,7 +143,7 @@ public class CorbaResponseWaitingRoomImpl return null; } - OutCallDesc call = (OutCallDesc)out_calls.get(requestId); + OutCallDesc call = out_calls.get(requestId); if (call == null) { throw wrapper.nullOutCall(CompletionStatus.COMPLETED_MAYBE); } @@ -197,7 +201,7 @@ public class CorbaResponseWaitingRoomImpl LocateReplyOrReplyMessage header = (LocateReplyOrReplyMessage) inputObject.getMessageHeader(); Integer requestId = new Integer(header.getRequestId()); - OutCallDesc call = (OutCallDesc) out_calls.get(requestId); + OutCallDesc call = out_calls.get(requestId); if (orb.transportDebugFlag) { dprint(".responseReceived: id/" @@ -248,7 +252,6 @@ public class CorbaResponseWaitingRoomImpl public int numberRegistered() { - // Note: Hashtable.size() is not synchronized return out_calls.size(); } @@ -264,29 +267,41 @@ public class CorbaResponseWaitingRoomImpl dprint(".signalExceptionToAllWaiters: " + systemException); } - OutCallDesc call; - java.util.Enumeration e = out_calls.elements(); - while(e.hasMoreElements()) { - call = (OutCallDesc) e.nextElement(); + synchronized (out_calls) { + if (orb.transportDebugFlag) { + dprint(".signalExceptionToAllWaiters: out_calls size :" + + out_calls.size()); + } - synchronized(call.done){ - // anything waiting for BufferManagerRead's fragment queue - // needs to be cancelled - CorbaMessageMediator corbaMsgMediator = - (CorbaMessageMediator)call.messageMediator; - CDRInputObject inputObject = - (CDRInputObject)corbaMsgMediator.getInputObject(); - // IMPORTANT: If inputObject is null, then no need to tell - // BufferManagerRead to cancel request processing. - if (inputObject != null) { - BufferManagerReadStream bufferManager = - (BufferManagerReadStream)inputObject.getBufferManager(); - int requestId = corbaMsgMediator.getRequestId(); - bufferManager.cancelProcessing(requestId); + for (OutCallDesc call : out_calls.values()) { + if (orb.transportDebugFlag) { + dprint(".signalExceptionToAllWaiters: signaling " + + call); + } + synchronized(call.done) { + try { + // anything waiting for BufferManagerRead's fragment queue + // needs to be cancelled + CorbaMessageMediator corbaMsgMediator = + (CorbaMessageMediator)call.messageMediator; + CDRInputObject inputObject = + (CDRInputObject)corbaMsgMediator.getInputObject(); + // IMPORTANT: If inputObject is null, then no need to tell + // BufferManagerRead to cancel request processing. + if (inputObject != null) { + BufferManagerReadStream bufferManager = + (BufferManagerReadStream)inputObject.getBufferManager(); + int requestId = corbaMsgMediator.getRequestId(); + bufferManager.cancelProcessing(requestId); + } + } catch (Exception e) { + } finally { + // attempt to wake up waiting threads in all cases + call.inputObject = null; + call.exception = systemException; + call.done.notifyAll(); + } } - call.inputObject = null; - call.exception = systemException; - call.done.notify(); } } } @@ -294,7 +309,7 @@ public class CorbaResponseWaitingRoomImpl public MessageMediator getMessageMediator(int requestId) { Integer id = new Integer(requestId); - OutCallDesc call = (OutCallDesc) out_calls.get(id); + OutCallDesc call = out_calls.get(id); if (call == null) { // This can happen when getting early reply fragments for a // request which has completed (e.g., client marshaling error). diff --git a/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java b/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java index 277657e7586..39fb4fecc14 100644 --- a/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java +++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/SocketOrChannelConnectionImpl.java @@ -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 @@ -1521,7 +1521,7 @@ public class SocketOrChannelConnectionImpl // connection and give them the SystemException; responseWaitingRoom.signalExceptionToAllWaiters(systemException); - + } finally { if (contactInfo != null) { ((OutboundConnectionCache)getConnectionCache()).remove(contactInfo); } else if (acceptor != null) { @@ -1542,7 +1542,6 @@ public class SocketOrChannelConnectionImpl writeUnlock(); - } finally { if (orb.transportDebugFlag) { dprint(".purgeCalls<-: " + minor_code + "/" + die + "/" + lockHeld diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 1bf06f8f90f..ab823043132 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -272,3 +272,6 @@ e3619706a7253540a2d94e9e841acaab8ace7038 jdk8-b49 6d0436885201db3f581523344a734793bb989549 jdk8-b52 54240c1b8e87758f28da2c6a569a926fd9e0910a jdk8-b53 9e3ae661284dc04185b029d85440fe7811f1ed07 hs24-b21 +e8fb566b94667f88462164defa654203f0ab6820 jdk8-b54 +09ea7e0752b306b8ae74713aeb4eb6263e1c6836 hs24-b22 +af0c8a0808516317333dcf9af15567cdd52761ce jdk8-b55 diff --git a/hotspot/agent/make/saenv.sh b/hotspot/agent/make/saenv.sh index 81c2d152c67..dcecd5187a8 100644 --- a/hotspot/agent/make/saenv.sh +++ b/hotspot/agent/make/saenv.sh @@ -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 diff --git a/hotspot/agent/make/start-debug-server-proc.sh b/hotspot/agent/make/start-debug-server-proc.sh index 791fd08032e..d538daf43f6 100644 --- a/hotspot/agent/make/start-debug-server-proc.sh +++ b/hotspot/agent/make/start-debug-server-proc.sh @@ -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 $* + diff --git a/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c b/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c index 5771fdd5d7d..5b49294e975 100644 --- a/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c +++ b/hotspot/agent/src/os/linux/LinuxDebuggerLocal.c @@ -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 @@ static jmethodID listAdd_ID = 0; #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 @@ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo 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 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT); return array; } +#endif diff --git a/hotspot/agent/src/os/linux/libproc.h b/hotspot/agent/src/os/linux/libproc.h index 9c941dd9019..5f583631c08 100644 --- a/hotspot/agent/src/os/linux/libproc.h +++ b/hotspot/agent/src/os/linux/libproc.h @@ -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 @@ uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name, // 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_ diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java index 029c20f0b8e..2526a325aaa 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotAgent.java @@ -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 @@ public class HotSpotAgent { 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 = diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java index 3b89f5996db..92d71356e65 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java @@ -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 @@ public class BugSpotAgent { 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). diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/ThreadContext.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/ThreadContext.java index 64a90f59257..ec6b7e6de11 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/ThreadContext.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/ThreadContext.java @@ -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 @@ public interface ThreadContext { /** 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); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/amd64/AMD64ThreadContext.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/amd64/AMD64ThreadContext.java index 2861545e5a7..5b2332a0fe6 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/amd64/AMD64ThreadContext.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/amd64/AMD64ThreadContext.java @@ -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 @@ public abstract class AMD64ThreadContext implements ThreadContext { 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); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/ia64/IA64ThreadContext.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/ia64/IA64ThreadContext.java index 5e1bc36f040..4a5aa00d945 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/ia64/IA64ThreadContext.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/ia64/IA64ThreadContext.java @@ -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 @@ public abstract class IA64ThreadContext implements ThreadContext { 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); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java index 4a155b2e2e0..f2d947493ee 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java @@ -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 @@ class LinuxCDebugger implements CDebugger { 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); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java index 94b56b108b7..44c2265d7a0 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java @@ -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 @@ class LinuxThreadContextFactory { 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"); + } } } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java index 1d9f7cea122..dbfed015c92 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java @@ -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 @@ package sun.jvm.hotspot.debugger.proc; 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 @@ public class ProcDebuggerLocal extends DebuggerBase implements ProcDebugger { 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 @@ public class ProcDebuggerLocal extends DebuggerBase implements ProcDebugger { 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; } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java index beb3f536a14..8417b8cb5a6 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java @@ -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 @@ package sun.jvm.hotspot.debugger.remote; 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 @@ public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger { 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. diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/sparc/SPARCThreadContext.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/sparc/SPARCThreadContext.java index 27f0132d538..228d9191dfe 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/sparc/SPARCThreadContext.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/sparc/SPARCThreadContext.java @@ -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 @@ public abstract class SPARCThreadContext implements ThreadContext { 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); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/x86/X86ThreadContext.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/x86/X86ThreadContext.java index 8222e925d45..9d51bcffc49 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/x86/X86ThreadContext.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/x86/X86ThreadContext.java @@ -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 @@ public abstract class X86ThreadContext implements ThreadContext { 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); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java index 67d929d1d12..5a4c344657d 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java @@ -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 @@ public class Threads { 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")) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java index ad0ff030346..a14347236ef 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -92,6 +92,8 @@ public class VM { 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 @@ public class VM { } useTLAB = (db.lookupIntConstant("UseTLAB").intValue() != 0); + enableInvokeDynamic = (db.lookupIntConstant("EnableInvokeDynamic").intValue() != 0); if (debugger != null) { isLP64 = debugger.getMachineDescription().isLP64(); @@ -552,6 +555,10 @@ public class VM { return useTLAB; } + public boolean getEnableInvokeDynamic() { + return enableInvokeDynamic; + } + public TypeDataBase getTypeDataBase() { return db; } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java index 2ab2bf6e2a3..5e55c32998d 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java @@ -204,7 +204,13 @@ public class HTMLGenerator implements /* imports */ ClassConstants { } 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!"); + } } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/AltPlatformInfo.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/AltPlatformInfo.java new file mode 100644 index 00000000000..0b802c3c237 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/AltPlatformInfo.java @@ -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 diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java index d069db2a365..9a5dc144a9c 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java @@ -64,6 +64,13 @@ public class PlatformInfo { } 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"); } } diff --git a/hotspot/make/defs.make b/hotspot/make/defs.make index b632ded2e00..63c6be7e274 100644 --- a/hotspot/make/defs.make +++ b/hotspot/make/defs.make @@ -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 @@ EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jmm.h ifndef JAVASE_EMBEDDED EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jfr.h endif + diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index 26660d0e795..adafbb4350d 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2012 HS_MAJOR_VER=24 HS_MINOR_VER=0 -HS_BUILD_NUMBER=21 +HS_BUILD_NUMBER=22 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff --git a/hotspot/make/linux/makefiles/defs.make b/hotspot/make/linux/makefiles/defs.make index 914a82fe52f..5a66e495a29 100644 --- a/hotspot/make/linux/makefiles/defs.make +++ b/hotspot/make/linux/makefiles/defs.make @@ -295,6 +295,8 @@ ADD_SA_BINARIES/ia64 = ADD_SA_BINARIES/arm = ADD_SA_BINARIES/zero = +-include $(HS_ALT_MAKE)/linux/makefiles/defs.make + EXPORT_LIST += $(ADD_SA_BINARIES/$(HS_ARCH)) diff --git a/hotspot/make/linux/makefiles/sa.make b/hotspot/make/linux/makefiles/sa.make index ede57619e95..f39e736827f 100644 --- a/hotspot/make/linux/makefiles/sa.make +++ b/hotspot/make/linux/makefiles/sa.make @@ -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_BUILD_VERSION_PROP = "sun.jvm.hotspot.runtime.VM.saBuildVersion=$(SA_BUILD_VE 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 @@ clean: rm -rf $(SA_CLASSDIR) rm -rf $(GENERATED)/sa-jdi.jar rm -rf $(AGENT_FILES_LIST) + +-include $(HS_ALT_MAKE)/linux/makefiles/sa-rules.make diff --git a/hotspot/make/linux/makefiles/saproc.make b/hotspot/make/linux/makefiles/saproc.make index 09beebd7f71..af0767a4385 100644 --- a/hotspot/make/linux/makefiles/saproc.make +++ b/hotspot/make/linux/makefiles/saproc.make @@ -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 @@ SASRCFILES = $(SASRCDIR)/salibelf.c \ $(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 @@ ifeq ($(DEBUG_BINARIES), true) 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 @@ $(LIBSAPROC): $(SASRCFILES) $(SAMAPFILE) -I$(GENERATED) \ -I$(BOOT_JAVA_HOME)/include \ -I$(BOOT_JAVA_HOME)/include/$(Platform_os_family) \ + $(ALT_SAINCDIR) \ $(SASRCFILES) \ $(SA_LFLAGS) \ $(SA_DEBUG_CFLAGS) \ diff --git a/hotspot/make/pic.make b/hotspot/make/pic.make index 79b2ea2f093..0e61ad93127 100644 --- a/hotspot/make/pic.make +++ b/hotspot/make/pic.make @@ -32,7 +32,7 @@ ifneq ($(OSNAME), windows) ifndef LP64 PARTIAL_NONPIC=1 endif - PIC_ARCH = ppc + PIC_ARCH = ppc arm ifneq ("$(filter $(PIC_ARCH),$(BUILDARCH))","") PARTIAL_NONPIC=0 endif diff --git a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp index dca0441cbaf..ee330c69fa3 100644 --- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp @@ -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 @@ define_pd_global(bool, UseMembar, false); // 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 diff --git a/hotspot/src/cpu/x86/vm/globals_x86.hpp b/hotspot/src/cpu/x86/vm/globals_x86.hpp index 1d0ef81d585..8d1cdfa71b8 100644 --- a/hotspot/src/cpu/x86/vm/globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp @@ -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 @@ define_pd_global(bool, UseMembar, false); // 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 diff --git a/hotspot/src/cpu/zero/vm/globals_zero.hpp b/hotspot/src/cpu/zero/vm/globals_zero.hpp index 6754e690797..7e0ae86b3be 100644 --- a/hotspot/src/cpu/zero/vm/globals_zero.hpp +++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp @@ -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 @@ define_pd_global(bool, UseMembar, false); // 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 diff --git a/hotspot/src/os/bsd/vm/os_bsd.hpp b/hotspot/src/os/bsd/vm/os_bsd.hpp index bb8fe3f211e..d9ab28afcc4 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.hpp +++ b/hotspot/src/os/bsd/vm/os_bsd.hpp @@ -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 @@ class Bsd { static void fast_thread_clock_init(void); #endif - static bool supports_monotonic_clock() { + static inline bool supports_monotonic_clock() { return _clock_gettime != NULL; } diff --git a/hotspot/src/os/linux/vm/os_linux.hpp b/hotspot/src/os/linux/vm/os_linux.hpp index 0f0fa214a04..7bbc041ed90 100644 --- a/hotspot/src/os/linux/vm/os_linux.hpp +++ b/hotspot/src/os/linux/vm/os_linux.hpp @@ -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 @@ class Linux { // 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; } diff --git a/hotspot/src/os/posix/launcher/launcher.script b/hotspot/src/os/posix/launcher/launcher.script index c4db5a423bf..4f5fff8b13e 100644 --- a/hotspot/src/os/posix/launcher/launcher.script +++ b/hotspot/src/os/posix/launcher/launcher.script @@ -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 @@ esac JDK= if [ "${ALT_JAVA_HOME}" = "" ]; then . ${MYDIR}/jdkpath.sh -else +else JDK=${ALT_JAVA_HOME%%/jre}; fi @@ -114,22 +114,34 @@ fi # any. JRE=$JDK/jre JAVA_HOME=$JDK -ARCH=@@LIBARCH@@ +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 diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index 1865e9c4b05..c447382f1d5 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -1646,15 +1646,15 @@ Dependencies* GraphBuilder::dependency_recorder() const { void GraphBuilder::invoke(Bytecodes::Code code) { - 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)"); } @@ -1840,7 +1840,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) { 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,7 +1877,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) { // inlining not successful => standard invoke bool is_loaded = target->is_loaded(); - ValueType* result_type = as_ValueType(target->return_type()); + 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. @@ -3823,7 +3823,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode } -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) { @@ -3858,7 +3858,7 @@ bool GraphBuilder::for_method_handle_inline(ciMethod* callee) { // 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 { diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp index e54863e0d1e..8d7e7de3436 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp @@ -346,7 +346,7 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC { 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); diff --git a/hotspot/src/share/vm/c1/c1_globals.hpp b/hotspot/src/share/vm/c1/c1_globals.hpp index 15f3cc10f32..ed7ea9a6ec0 100644 --- a/hotspot/src/share/vm/c1/c1_globals.hpp +++ b/hotspot/src/share/vm/c1/c1_globals.hpp @@ -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 @@ -156,18 +156,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")\ \ @@ -224,9 +218,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") \ \ diff --git a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp index 20ad22ea6d4..31bd06c2685 100644 --- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp +++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp @@ -236,12 +236,16 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* 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 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl 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 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl 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()) { diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index 30a54a32a7f..947c72e244f 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -738,91 +738,81 @@ methodOop ciEnv::lookup_method(instanceKlass* accessor, 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); + 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. - // 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 (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 (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); -} - - -// ------------------------------------------------------------------ -// 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 invoker methodOop and the extra argument from the constant pool. - methodOop adapter = secondary_entry->f2_as_vfinal_method(); - return get_object(adapter)->as_method(); + // 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: + { + 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); + } } @@ -853,11 +843,7 @@ ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* m 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);) } diff --git a/hotspot/src/share/vm/ci/ciEnv.hpp b/hotspot/src/share/vm/ci/ciEnv.hpp index d00c9f78bef..57323a6f1e4 100644 --- a/hotspot/src/share/vm/ci/ciEnv.hpp +++ b/hotspot/src/share/vm/ci/ciEnv.hpp @@ -152,9 +152,6 @@ private: 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, diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index 579e1de475e..fcadab76d5b 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -1215,9 +1215,10 @@ void ciMethod::print_impl(outputStream* st) { 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"); diff --git a/hotspot/src/share/vm/ci/ciStreams.cpp b/hotspot/src/share/vm/ci/ciStreams.cpp index 23dc891bf51..92ab59d607c 100644 --- a/hotspot/src/share/vm/ci/ciStreams.cpp +++ b/hotspot/src/share/vm/ci/ciStreams.cpp @@ -355,11 +355,23 @@ int ciBytecodeStream::get_method_index() { // 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; } @@ -418,24 +430,6 @@ int ciBytecodeStream::get_method_holder_index() { return cpool->klass_ref_index_at(get_method_index()); } -// ------------------------------------------------------------------ -// 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 // @@ -443,11 +437,12 @@ ciSignature* ciBytecodeStream::get_declared_method_signature() { // 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); + ) } // ------------------------------------------------------------------ diff --git a/hotspot/src/share/vm/ci/ciStreams.hpp b/hotspot/src/share/vm/ci/ciStreams.hpp index 5689d4ca153..0f442539ef3 100644 --- a/hotspot/src/share/vm/ci/ciStreams.hpp +++ b/hotspot/src/share/vm/ci/ciStreams.hpp @@ -151,6 +151,8 @@ public: // 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 @@ public: 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; diff --git a/hotspot/src/share/vm/ci/ciTypeFlow.cpp b/hotspot/src/share/vm/ci/ciTypeFlow.cpp index 94c6123c967..d28ed53d29d 100644 --- a/hotspot/src/share/vm/ci/ciTypeFlow.cpp +++ b/hotspot/src/share/vm/ci/ciTypeFlow.cpp @@ -643,9 +643,11 @@ void ciTypeFlow::StateVector::do_getstatic(ciBytecodeStream* str) { // ------------------------------------------------------------------ // 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 @@ void ciTypeFlow::StateVector::do_invoke(ciBytecodeStream* str, 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 @@ void ciTypeFlow::StateVector::do_invoke(ciBytecodeStream* str, 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(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index d0b0a79f586..42ec32d8b2e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -1246,6 +1246,31 @@ void G1CollectedHeap::print_hrs_post_compaction() { 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 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, 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 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, 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(); @@ -1933,6 +1945,9 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : 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. @@ -2327,8 +2342,7 @@ void G1CollectedHeap::iterate_dirty_card_closure(CardTableEntryClosure* cl, 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!"); } @@ -3735,8 +3749,9 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { 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()); @@ -3765,13 +3780,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { 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()); @@ -3984,10 +3993,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { 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. @@ -4020,13 +4025,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { // 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(); @@ -4050,10 +4049,35 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { gc_epilogue(false); - g1_policy()->phase_times()->note_gc_end(os::elapsedTime()); + if (G1Log::fine()) { + if (PrintGCTimeStamps) { + gclog_or_tty->stamp(); + gclog_or_tty->print(": "); + } - // We have to do this after we decide whether to expand the heap or not. + 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 @@ -4543,7 +4567,15 @@ oop G1ParCopyClosure<do_gen_barrier, barrier, do_mark_object> 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 @@ -4552,6 +4584,8 @@ oop G1ParCopyClosure<do_gen_barrier, barrier, do_mark_object> 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); @@ -4863,7 +4897,7 @@ public: 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()); @@ -4991,27 +5025,28 @@ g1_process_strong_roots(bool collecting_perm_gen, 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. @@ -5556,6 +5591,9 @@ void G1CollectedHeap::evacuate_collection_set() { _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(); @@ -5647,11 +5685,11 @@ void G1CollectedHeap::evacuate_collection_set() { 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 diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 901248d776e..facc576f77b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -405,6 +405,10 @@ private: // 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. @@ -911,6 +915,39 @@ protected: 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 diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp index ee18c4de450..4f9c7726292 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp @@ -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 @@ inline RefToScanQueue* G1CollectedHeap::task_queue(int i) const { 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 @@ inline bool G1CollectedHeap::isMarkedNext(oop obj) const { 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 diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 6e8bf2c3660..6e9170a0006 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -795,7 +795,7 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec, _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(); @@ -947,7 +947,7 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) { _trace_gen0_time_data.record_end_collection(pause_time_ms, phase_times()); // this is where we update the allocation rate of the application double app_time_ms = - (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. @@ -1035,7 +1035,7 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) { if (update_stats) { 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); } @@ -1043,7 +1043,7 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) { 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 { @@ -1083,7 +1083,7 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) { 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 { @@ -1092,21 +1092,22 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) { } 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()); @@ -1133,7 +1134,8 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) { // 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(); } @@ -1144,7 +1146,11 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms) { 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(); @@ -1171,11 +1177,6 @@ void G1CollectorPolicy::print_heap_transition() { 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, @@ -1900,8 +1901,7 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { 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); // Set the start of the non-young choice time. double non_young_start_time_sec = young_end_time_sec; @@ -2015,8 +2015,7 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { 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) { @@ -2035,25 +2034,25 @@ void TraceGen0TimeData::record_end_collection(double pause_time_ms, G1GCPhaseTim 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()); } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index da664b3835e..fdeaf8ef155 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -683,6 +683,7 @@ public: 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(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp index 8bb9e552492..ae8439ad25f 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp @@ -79,119 +79,145 @@ public: } }; -G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : - _max_gc_threads(max_gc_threads), - _min_clear_cc_time_ms(-1.0), - _max_clear_cc_time_ms(-1.0), - _cur_clear_cc_time_ms(0.0), - _cum_clear_cc_time_ms(0.0), - _num_cc_clears(0L) -{ - assert(max_gc_threads > 0, "Must have some GC threads"); - _par_last_gc_worker_start_times_ms = new double[_max_gc_threads]; - _par_last_ext_root_scan_times_ms = new double[_max_gc_threads]; - _par_last_satb_filtering_times_ms = new double[_max_gc_threads]; - _par_last_update_rs_times_ms = new double[_max_gc_threads]; - _par_last_update_rs_processed_buffers = new double[_max_gc_threads]; - _par_last_scan_rs_times_ms = new double[_max_gc_threads]; - _par_last_obj_copy_times_ms = new double[_max_gc_threads]; - _par_last_termination_times_ms = new double[_max_gc_threads]; - _par_last_termination_attempts = new double[_max_gc_threads]; - _par_last_gc_worker_end_times_ms = new double[_max_gc_threads]; - _par_last_gc_worker_times_ms = new double[_max_gc_threads]; - _par_last_gc_worker_other_times_ms = new double[_max_gc_threads]; -} - -void G1GCPhaseTimes::note_gc_start(double pause_start_time_sec, uint active_gc_threads, - bool is_young_gc, bool is_initial_mark_gc, GCCause::Cause gc_cause) { - assert(active_gc_threads > 0, "The number of threads must be > 0"); - assert(active_gc_threads <= _max_gc_threads, "The number of active threads must be <= the max nubmer of threads"); - _active_gc_threads = active_gc_threads; - _pause_start_time_sec = pause_start_time_sec; - _is_young_gc = is_young_gc; - _is_initial_mark_gc = is_initial_mark_gc; - _gc_cause = gc_cause; - -#ifdef ASSERT - // initialise the timing data to something well known so that we can spot - // if something is not set properly - - for (uint i = 0; i < _max_gc_threads; ++i) { - _par_last_gc_worker_start_times_ms[i] = -1234.0; - _par_last_ext_root_scan_times_ms[i] = -1234.0; - _par_last_satb_filtering_times_ms[i] = -1234.0; - _par_last_update_rs_times_ms[i] = -1234.0; - _par_last_update_rs_processed_buffers[i] = -1234.0; - _par_last_scan_rs_times_ms[i] = -1234.0; - _par_last_obj_copy_times_ms[i] = -1234.0; - _par_last_termination_times_ms[i] = -1234.0; - _par_last_termination_attempts[i] = -1234.0; - _par_last_gc_worker_end_times_ms[i] = -1234.0; - _par_last_gc_worker_times_ms[i] = -1234.0; - _par_last_gc_worker_other_times_ms[i] = -1234.0; - } -#endif -} - -void G1GCPhaseTimes::note_gc_end(double pause_end_time_sec) { - if (G1Log::fine()) { - double pause_time_ms = (pause_end_time_sec - _pause_start_time_sec) * MILLIUNITS; - - for (uint i = 0; i < _active_gc_threads; i++) { - _par_last_gc_worker_times_ms[i] = _par_last_gc_worker_end_times_ms[i] - - _par_last_gc_worker_start_times_ms[i]; - - double worker_known_time = _par_last_ext_root_scan_times_ms[i] + - _par_last_satb_filtering_times_ms[i] + - _par_last_update_rs_times_ms[i] + - _par_last_scan_rs_times_ms[i] + - _par_last_obj_copy_times_ms[i] + - _par_last_termination_times_ms[i]; - - _par_last_gc_worker_other_times_ms[i] = _par_last_gc_worker_times_ms[i] - - worker_known_time; - } - - print(pause_time_ms); +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; -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; + 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()) { - if (showDecimals) { - buf.append(" %.1lf", val); - } else { - buf.append(" %d", (int)val); - } + buf.append(" "); + buf.append(_print_format, 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); + + 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), + _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"); +} + +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; + + _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() { + _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++) { + 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 = _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); + + double worker_other_time = worker_time - worker_known_time; + _last_gc_worker_other_times_ms.set(i, worker_other_time); + } + + _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 @@ void G1GCPhaseTimes::print_stats(int level, const char* str, double value, int w 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 @@ double G1GCPhaseTimes::accounted_time_ms() { return misc_time_ms; } -void G1GCPhaseTimes::print(double pause_time_ms) { - - if (PrintGCTimeStamps) { - gclog_or_tty->stamp(); - gclog_or_tty->print(": "); - } - - GCCauseString gc_cause_str = GCCauseString("GC pause", _gc_cause) - .append(_is_young_gc ? " (young)" : " (mixed)") - .append(_is_initial_mark_gc ? " (initial-mark)" : ""); - gclog_or_tty->print_cr("[%s, %3.7f secs]", (const char*)gc_cause_str, pause_time_ms / 1000.0); - - if (!G1Log::finer()) { - return; - } - +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); + _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, "Processed Buffers", _par_last_update_rs_processed_buffers, - false /* showDecimals */); + _last_termination_attempts.print(3, "Termination Attempts"); } - print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms); - print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms); - print_par_stats(2, "Termination", _par_last_termination_times_ms); - if (G1Log::finest()) { - print_par_stats(3, "Termination Attempts", _par_last_termination_attempts, - false /* showDecimals */); - } - print_par_stats(2, "GC Worker Other", _par_last_gc_worker_other_times_ms); - print_par_stats(2, "GC Worker Total", _par_last_gc_worker_times_ms); - print_par_stats(2, "GC Worker End", _par_last_gc_worker_end_times_ms); + _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 @@ void G1GCPhaseTimes::print(double pause_time_ms) { 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 @@ void G1GCPhaseTimes::print(double pause_time_ms) { 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) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp index d9eaf37261b..99e35c63d43 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp @@ -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 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> { 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 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> { 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 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> { 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 diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp index 3e2e07b2ce6..b6d82194fce 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp @@ -324,7 +324,7 @@ void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc, 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)) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp index 14aadb8ab4c..a8405e0c50e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp @@ -311,7 +311,35 @@ "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) diff --git a/hotspot/src/share/vm/interpreter/bytecodes.hpp b/hotspot/src/share/vm/interpreter/bytecodes.hpp index 4d6e173aa53..4cd078a306c 100644 --- a/hotspot/src/share/vm/interpreter/bytecodes.hpp +++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp @@ -424,6 +424,8 @@ class Bytecodes: AllStatic { || 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"); diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index cc72fc0a1cf..c5c7768dccf 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -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) diff --git a/hotspot/src/share/vm/opto/chaitin.cpp b/hotspot/src/share/vm/opto/chaitin.cpp index ae057c06966..9e5234de615 100644 --- a/hotspot/src/share/vm/opto/chaitin.cpp +++ b/hotspot/src/share/vm/opto/chaitin.cpp @@ -222,6 +222,7 @@ void PhaseChaitin::Register_Allocate() { _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 @@ void PhaseChaitin::Register_Allocate() { // 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 @@ void PhaseChaitin::Register_Allocate() { } 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; diff --git a/hotspot/src/share/vm/opto/chaitin.hpp b/hotspot/src/share/vm/opto/chaitin.hpp index c10f18d742e..340e46d49b1 100644 --- a/hotspot/src/share/vm/opto/chaitin.hpp +++ b/hotspot/src/share/vm/opto/chaitin.hpp @@ -470,7 +470,7 @@ private: // 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 ); diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp index 580740b9fe4..a348705095c 100644 --- a/hotspot/src/share/vm/opto/doCall.cpp +++ b/hotspot/src/share/vm/opto/doCall.cpp @@ -341,25 +341,26 @@ void Parse::do_call() { 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 @@ void Parse::do_call() { // 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 @@ void Parse::do_call() { // 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 @@ void Parse::do_call() { // 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 @@ void Parse::do_call() { 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 @@ void Parse::do_call() { } 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)); diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index da24dc369e7..f844eaaa41c 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -1006,11 +1006,11 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth, bool for_parse) { 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 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth, bool for_parse) { 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 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth, bool for_parse) { // 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; diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index 0ee3436c73a..8d88242ffe3 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -547,11 +547,6 @@ void PhaseIdealLoop::do_peeling( IdealLoopTree *loop, Node_List &old_new ) { 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 diff --git a/hotspot/src/share/vm/opto/loopnode.cpp b/hotspot/src/share/vm/opto/loopnode.cpp index ae267c589f3..511cca449f7 100644 --- a/hotspot/src/share/vm/opto/loopnode.cpp +++ b/hotspot/src/share/vm/opto/loopnode.cpp @@ -577,6 +577,9 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) { 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 @@ bool PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) { // 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::allpaths_check_safepts(VectorSet &visited, Node_List &stack) 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 @@ void IdealLoopTree::counted_loop( PhaseIdealLoop *phase ) { 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)); + } + } } } @@ -2766,6 +2781,10 @@ int PhaseIdealLoop::build_loop_tree_impl( Node *n, int pre_order ) { // 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); } } } @@ -2816,6 +2835,9 @@ void PhaseIdealLoop::build_loop_early( VectorSet &visited, Node_List &worklist, 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 ) ) { diff --git a/hotspot/src/share/vm/opto/loopnode.hpp b/hotspot/src/share/vm/opto/loopnode.hpp index d2ea55610b8..92f6912389c 100644 --- a/hotspot/src/share/vm/opto/loopnode.hpp +++ b/hotspot/src/share/vm/opto/loopnode.hpp @@ -336,6 +336,7 @@ public: _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 @@ public: : _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) diff --git a/hotspot/src/share/vm/opto/reg_split.cpp b/hotspot/src/share/vm/opto/reg_split.cpp index cae363bea7a..2c488894a52 100644 --- a/hotspot/src/share/vm/opto/reg_split.cpp +++ b/hotspot/src/share/vm/opto/reg_split.cpp @@ -449,9 +449,12 @@ bool PhaseChaitin::prompt_use( Block *b, uint lidx ) { // 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 @@ uint PhaseChaitin::Split( uint maxlrg ) { 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 @@ uint PhaseChaitin::Split( uint maxlrg ) { // 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 @@ uint PhaseChaitin::Split( uint maxlrg ) { } } +#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---------- diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index c6c325553c7..75e6d751572 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -880,46 +880,6 @@ JRT_LEAF(void, OptoRuntime::profile_receiver_type_C(DataLayout* data, oopDesc* r } 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 diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index ef1a3e0b08c..27085b3f8eb 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1916,7 +1916,7 @@ bool Arguments::check_vm_args_consistency() { (ExplicitGCInvokesConcurrent || ExplicitGCInvokesConcurrentAndUnloadsClasses)) { jio_fprintf(defaultStream::error_stream(), - "error: +ExplictGCInvokesConcurrent[AndUnloadsClasses] conflicts" + "error: +ExplicitGCInvokesConcurrent[AndUnloadsClasses] conflicts" " with -UseAsyncConcMarkSweepGC"); status = false; } diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp index 3dad7a0f05d..569a3f4bef8 100644 --- a/hotspot/src/share/vm/runtime/globals.cpp +++ b/hotspot/src/share/vm/runtime/globals.cpp @@ -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 @@ RUNTIME_OS_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \ 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 @@ void Flag::print_as_flag(outputStream* st) { #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 @@ void Flag::print_as_flag(outputStream* st) { #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 @@ static Flag flagTable[] = { #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} }; diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 2ab25546229..777af035963 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -530,12 +530,6 @@ class CommandLineFlags { 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 @@ class CommandLineFlags { 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 @@ class CommandLineFlags { "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") \ \ @@ -633,31 +620,9 @@ class CommandLineFlags { 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") \ \ @@ -667,9 +632,6 @@ class CommandLineFlags { 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") \ \ @@ -756,9 +718,6 @@ class CommandLineFlags { 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") \ \ @@ -915,15 +874,6 @@ class CommandLineFlags { "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)") \ \ @@ -1037,9 +987,6 @@ class CommandLineFlags { 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") \ @@ -1109,8 +1056,6 @@ class CommandLineFlags { "(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") \ @@ -1118,9 +1063,6 @@ class CommandLineFlags { 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)" ) \ @@ -1150,10 +1092,6 @@ class CommandLineFlags { "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") \ \ @@ -1188,15 +1126,6 @@ class CommandLineFlags { "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") \ \ @@ -1225,39 +1154,9 @@ class CommandLineFlags { 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") \ @@ -1387,9 +1286,6 @@ class CommandLineFlags { 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") \ \ @@ -1405,10 +1301,6 @@ class CommandLineFlags { product(bool, TraceMonitorInflation, false, \ "Trace monitor inflation in JVM") \ \ - /* assembler */ \ - product(bool, Use486InstrsOnly, false, \ - "Use 80486 Compliant instruction subset") \ - \ /* gc */ \ \ product(bool, UseSerialGC, false, \ @@ -1467,9 +1359,6 @@ class CommandLineFlags { 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") \ \ @@ -1621,10 +1510,6 @@ class CommandLineFlags { "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.") \ \ @@ -1632,12 +1517,6 @@ class CommandLineFlags { "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") \ \ @@ -2017,9 +1896,6 @@ class CommandLineFlags { 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") \ @@ -2044,18 +1920,6 @@ class CommandLineFlags { 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") \ \ @@ -2248,9 +2112,6 @@ class CommandLineFlags { 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") \ \ @@ -2486,27 +2347,9 @@ class CommandLineFlags { 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, \ @@ -2520,12 +2363,6 @@ class CommandLineFlags { "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") \ \ @@ -2557,9 +2394,6 @@ class CommandLineFlags { "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") \ \ @@ -2572,33 +2406,15 @@ class CommandLineFlags { 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") \ \ @@ -2608,10 +2424,6 @@ class CommandLineFlags { 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") \ \ @@ -2621,9 +2433,6 @@ class CommandLineFlags { 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") \ \ @@ -2700,9 +2509,6 @@ class CommandLineFlags { 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") \ \ @@ -2712,12 +2518,6 @@ class CommandLineFlags { 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") \ @@ -2732,19 +2532,9 @@ class CommandLineFlags { 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") \ \ @@ -2757,22 +2547,9 @@ class CommandLineFlags { 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")\ @@ -2829,15 +2606,6 @@ class CommandLineFlags { 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") \ \ @@ -2854,9 +2622,6 @@ class CommandLineFlags { 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") \ @@ -2899,9 +2664,6 @@ class CommandLineFlags { 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") \ \ @@ -2989,15 +2751,6 @@ class CommandLineFlags { 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 */ \ develop(bool, TraceDeoptimization, false, \ "Trace deoptimization") \ @@ -3088,9 +2841,6 @@ class CommandLineFlags { 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)") \ \ @@ -3130,9 +2880,6 @@ class CommandLineFlags { "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") \ \ @@ -3171,9 +2918,6 @@ class CommandLineFlags { 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") \ \ @@ -3187,29 +2931,12 @@ class CommandLineFlags { 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") \ @@ -3466,10 +3193,6 @@ class CommandLineFlags { "(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") \ \ @@ -3663,9 +3386,6 @@ class CommandLineFlags { 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") \ @@ -3835,9 +3555,6 @@ class CommandLineFlags { "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") \ \ @@ -3952,6 +3669,8 @@ RUNTIME_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT 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" diff --git a/hotspot/src/share/vm/runtime/globals_extension.hpp b/hotspot/src/share/vm/runtime/globals_extension.hpp index a87e78168a3..064b489b642 100644 --- a/hotspot/src/share/vm/runtime/globals_extension.hpp +++ b/hotspot/src/share/vm/runtime/globals_extension.hpp @@ -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 @@ typedef enum { #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 @@ typedef enum { #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 @@ typedef enum { #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 @@ typedef enum { 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; diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 6188e7d8e5f..bc916d9f2c8 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -2135,6 +2135,7 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable; /******************/ \ \ declare_constant(UseTLAB) \ + declare_constant(EnableInvokeDynamic) \ \ /**************/ \ /* Stack bias */ \ diff --git a/hotspot/test/compiler/6894807/Test6894807.sh b/hotspot/test/compiler/6894807/Test6894807.sh index 20fee43ea69..229fb545108 100644 --- a/hotspot/test/compiler/6894807/Test6894807.sh +++ b/hotspot/test/compiler/6894807/Test6894807.sh @@ -31,6 +31,11 @@ case "$OS" in PS=";" FS="\\" ;; + CYGWIN_* ) + NULL=/dev/null + PS=";" + FS="/" + ;; * ) echo "Unrecognized system!" exit 1; diff --git a/hotspot/test/gc/6941923/test6941923.sh b/hotspot/test/gc/6941923/test6941923.sh index e6641963568..0c751de12e0 100644 --- a/hotspot/test/gc/6941923/test6941923.sh +++ b/hotspot/test/gc/6941923/test6941923.sh @@ -14,7 +14,7 @@ case "$OS" in PS=":" FS="/" ;; - Windows_* ) + Windows_* | CYGWIN_* ) echo "Test skipped for Windows" exit 0 ;; diff --git a/hotspot/test/runtime/6626217/Test6626217.sh b/hotspot/test/runtime/6626217/Test6626217.sh index e7414983b9c..a8c8a2395cf 100644 --- a/hotspot/test/runtime/6626217/Test6626217.sh +++ b/hotspot/test/runtime/6626217/Test6626217.sh @@ -65,6 +65,14 @@ case "$OS" in CP=cp MV=mv ;; + CYGWIN_* ) + NULL=/dev/null + PS=";" + FS="/" + RM=rm + CP=cp + MV=mv + ;; * ) echo "Unrecognized system!" exit 1; diff --git a/hotspot/test/runtime/6878713/Test6878713.sh b/hotspot/test/runtime/6878713/Test6878713.sh index 73d91fc0c32..a452ad58fcd 100644 --- a/hotspot/test/runtime/6878713/Test6878713.sh +++ b/hotspot/test/runtime/6878713/Test6878713.sh @@ -38,6 +38,11 @@ case "$OS" in PS=";" FS="\\" ;; + CYGWIN_* ) + NULL=/dev/null + PS=";" + FS="/" + ;; * ) echo "Unrecognized system!" exit 1; diff --git a/hotspot/test/runtime/7020373/Test7020373.sh b/hotspot/test/runtime/7020373/Test7020373.sh index 54b8b32974e..83e7f4c449d 100644 --- a/hotspot/test/runtime/7020373/Test7020373.sh +++ b/hotspot/test/runtime/7020373/Test7020373.sh @@ -40,6 +40,11 @@ case "$OS" in PS=";" FS="\\" ;; + CYGWIN_* ) + NULL=/dev/null + PS=";" + FS="/" + ;; * ) echo "Unrecognized system!" exit 1; diff --git a/hotspot/test/runtime/7051189/Xchecksig.sh b/hotspot/test/runtime/7051189/Xchecksig.sh index b4fbbd7d7c8..f3eabce57d5 100644 --- a/hotspot/test/runtime/7051189/Xchecksig.sh +++ b/hotspot/test/runtime/7051189/Xchecksig.sh @@ -46,7 +46,7 @@ case "$OS" in SunOS | Linux | Darwin ) FS="/" ;; - Windows_* ) + Windows_* | CYGWIN_* ) printf "Not testing libjsig.so on Windows. PASSED.\n " exit 0 ;; diff --git a/hotspot/test/runtime/7110720/Test7110720.sh b/hotspot/test/runtime/7110720/Test7110720.sh index ef13888ee57..0788cb56a58 100644 --- a/hotspot/test/runtime/7110720/Test7110720.sh +++ b/hotspot/test/runtime/7110720/Test7110720.sh @@ -55,6 +55,12 @@ case "$OS" in CP=cp MV=mv ;; + CYGWIN_* ) + FS="/" + RM=rm + CP=cp + MV=mv + ;; * ) echo "Unrecognized system!" exit 1; diff --git a/hotspot/test/runtime/7158800/Test7158800.sh b/hotspot/test/runtime/7158800/Test7158800.sh index 781922a3c5b..81fa7aca8a8 100644 --- a/hotspot/test/runtime/7158800/Test7158800.sh +++ b/hotspot/test/runtime/7158800/Test7158800.sh @@ -56,6 +56,11 @@ case "$OS" in PS=";" FS="\\" ;; + CYGWIN_* ) + NULL=/dev/null + PS=";" + FS="/" + ;; * ) echo "Unrecognized system!" exit 1; diff --git a/hotspot/test/runtime/7158988/TestFieldMonitor.sh b/hotspot/test/runtime/7158988/TestFieldMonitor.sh index cf7fcf39319..aa18c1609ba 100644 --- a/hotspot/test/runtime/7158988/TestFieldMonitor.sh +++ b/hotspot/test/runtime/7158988/TestFieldMonitor.sh @@ -38,6 +38,18 @@ case "$OS" in 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; diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 4cd999549d0..55ffe019b2e 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -175,3 +175,5 @@ f81e981eca7b63316cf9d778f93903a4fc62161d jdk8-b49 dc1ea77ed9d9746e0f98bb1268987c3596c8b4b5 jdk8-b51 bd3c00d5761408954cc29ffb82016a76cbc90b43 jdk8-b52 2c566f25c39f0087464b73e3bcf1c1421d0f2a7e jdk8-b53 +7dd81ccb7c1134df70969b3068b1e98def701746 jdk8-b54 +7c2363666890c6675194948fbcd74d81ddb84298 jdk8-b55 diff --git a/jaxp/src/javax/xml/stream/XMLEventFactory.java b/jaxp/src/javax/xml/stream/XMLEventFactory.java index 9f9e86ef8e3..f92d77805f7 100644 --- a/jaxp/src/javax/xml/stream/XMLEventFactory.java +++ b/jaxp/src/javax/xml/stream/XMLEventFactory.java @@ -49,6 +49,10 @@ import java.util.Iterator; public abstract class XMLEventFactory { protected XMLEventFactory(){} + static final String JAXPFACTORYID = "javax.xml.stream.XMLEventFactory"; + static final String DEFAULIMPL = "com.sun.xml.internal.stream.events.XMLEventFactoryImpl"; + + /** * Create a new instance of the factory * @throws FactoryConfigurationError if an instance of this factory cannot be loaded @@ -57,8 +61,8 @@ public abstract class XMLEventFactory { throws FactoryConfigurationError { return (XMLEventFactory) FactoryFinder.find( - "javax.xml.stream.XMLEventFactory", - "com.sun.xml.internal.stream.events.XMLEventFactoryImpl"); + JAXPFACTORYID, + DEFAULIMPL); } /** @@ -90,8 +94,8 @@ public abstract class XMLEventFactory { throws FactoryConfigurationError { return (XMLEventFactory) FactoryFinder.find( - "javax.xml.stream.XMLEventFactory", - "com.sun.xml.internal.stream.events.XMLEventFactoryImpl"); + JAXPFACTORYID, + DEFAULIMPL); } /** @@ -114,7 +118,7 @@ public abstract class XMLEventFactory { throws FactoryConfigurationError { try { //do not fallback if given classloader can't find the class, throw exception - return (XMLEventFactory) FactoryFinder.newInstance(factoryId, classLoader, false); + return (XMLEventFactory) FactoryFinder.find(factoryId, classLoader, null); } catch (FactoryFinder.ConfigurationError e) { throw new FactoryConfigurationError(e.getException(), e.getMessage()); @@ -141,7 +145,7 @@ public abstract class XMLEventFactory { throws FactoryConfigurationError { try { //do not fallback if given classloader can't find the class, throw exception - return (XMLEventFactory) FactoryFinder.newInstance(factoryId, classLoader, false); + return (XMLEventFactory) FactoryFinder.find(factoryId, classLoader, null); } catch (FactoryFinder.ConfigurationError e) { throw new FactoryConfigurationError(e.getException(), e.getMessage()); diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 12ddc0ce1d9..89f54c11cc1 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -175,3 +175,5 @@ bdab72e87b83bcccf3abe6eaaa4cdc7b1cd2d92b jdk8-b50 1a70b6333ebe12e1c6dbca30e58bc1ba894ab898 jdk8-b51 f62bc618122e87a8bea69865cc02074e9d850426 jdk8-b52 8a35fd644d3c0b75813ff0236adef8a1c6f895c6 jdk8-b53 +91970935926a20f19a5cbbf20931745ac1975e91 jdk8-b54 +109c9e1f2d8546e9954e1b7be9a37a4396434544 jdk8-b55 diff --git a/jdk/.hgtags b/jdk/.hgtags index 7b1dd87bd4e..3c028e89658 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -176,3 +176,5 @@ e865efbc71059a414b3b2dd2e0adfcb3d2ab6ff9 jdk8-b51 e8569a473cee7f4955bd9e76a9bdf6c6a07ced27 jdk8-b52 2c6933c5106b81a8578b70996fe5b735fb3adb60 jdk8-b53 70ad0ed1d6cef0e7712690d1bab21e4769708aad jdk8-b54 +1f3f4b333341873f00da3dee85e4879f0e89c9bb jdk8-b55 +2e9eeef2909b33c9224a024afddb61ccb0b77f14 jdk8-b56 diff --git a/jdk/make/common/Defs.gmk b/jdk/make/common/Defs.gmk index 70ce7783053..00646df3e72 100644 --- a/jdk/make/common/Defs.gmk +++ b/jdk/make/common/Defs.gmk @@ -542,6 +542,21 @@ CFLAGS_$(VARIANT)/BYFILE = $(CFLAGS_$(VARIANT)/$(@F)) \ CXXFLAGS_$(VARIANT)/BYFILE = $(CXXFLAGS_$(VARIANT)/$(@F)) \ $(CXXFLAGS_$(VARIANT)$(CXXFLAGS_$(VARIANT)/$(@F))) +# Command line define to provide basename of file being compiled to source. +# The C macro THIS_FILE can replace the use of __FILE__ in the source +# files for the current filename being compiled. +# The value of the __FILE__ macro is unpredictable and can be anything +# from a relative path to a full path, THIS_FILE will be more consistent.. +# The THIS_FILE macro will always be just the basename of the file being +# compiled. +# Different string literals in the the object files makes it difficult to +# compare shared libraries from different builds. +# +# NOTE: If the THIS_FILE macro is actually expanded while in an included +# source file, it will not return the name of the included file. +# +CPP_THIS_FILE = -DTHIS_FILE='"$(<F)"' + # # Tool flags # @@ -551,7 +566,7 @@ ASFLAGS = $(ASFLAGS_$(VARIANT)) $(ASFLAGS_COMMON) $(OTHER_ASFLAGS) CFLAGS = $(CFLAGS_$(VARIANT)/BYFILE) $(CFLAGS_COMMON) $(OTHER_CFLAGS) $(EXTRA_CFLAGS) CXXFLAGS = $(CXXFLAGS_$(VARIANT)/BYFILE) $(CXXFLAGS_COMMON) $(OTHER_CXXFLAGS) $(EXTRA_CFLAGS) CPPFLAGS = $(CPPFLAGS_$(VARIANT)) $(CPPFLAGS_COMMON) $(OTHER_CPPFLAGS) \ - $(DEFINES) $(OPTIONS:%=-D%) + $(DEFINES) $(OPTIONS:%=-D%) $(CPP_THIS_FILE) LDFLAGS = $(LDFLAGS_$(VARIANT)) $(LDFLAGS_COMMON) $(OTHER_LDFLAGS) LDLIBS = $(OTHER_LDLIBS) $(LDLIBS_$(VARIANT)) $(LDLIBS_COMMON) LINTFLAGS = $(LINTFLAGS_$(VARIANT)) $(LINTFLAGS_COMMON) \ diff --git a/jdk/make/common/Demo.gmk b/jdk/make/common/Demo.gmk index c6cf41d6b3f..3aba9a62c07 100644 --- a/jdk/make/common/Demo.gmk +++ b/jdk/make/common/Demo.gmk @@ -320,10 +320,10 @@ $(DEMO_LIBRARY): $(DEMO_FULL_OBJECTS) ifeq ($(PLATFORM),windows) $(RC) $(RC_FLAGS) $(CC_OBJECT_OUTPUT_FLAG)$(DEMO_VERSION_INFO) $(VERSIONINFO_RESOURCE) $(LINK.demo) $(SHARED_LIBRARY_FLAG) -Fe$@ \ - $(DEMO_FULL_OBJECTS) $(LDLIBS.demo) + $(sort $(DEMO_FULL_OBJECTS)) $(LDLIBS.demo) else $(LINK.demo) $(SHARED_LIBRARY_FLAG) -o $@ \ - $(DEMO_FULL_OBJECTS) $(LDLIBS.demo) + $(sort $(DEMO_FULL_OBJECTS)) $(LDLIBS.demo) endif @$(call binary_file_verification,$@) diff --git a/jdk/make/common/Library.gmk b/jdk/make/common/Library.gmk index 7b47adf7786..b04095c93e2 100644 --- a/jdk/make/common/Library.gmk +++ b/jdk/make/common/Library.gmk @@ -199,7 +199,7 @@ endif # LIBRARY $(OBJDIR)/$(LIBRARY).lcf: $(OBJDIR)/$(LIBRARY).res $(COMPILE_FILES_o) $(FILES_m) @$(prep-target) @$(MKDIR) -p $(TEMPDIR) - @$(ECHO) $(FILES_o) > $@ + @$(ECHO) $(sort $(FILES_o)) > $@ ifndef LOCAL_RESOURCE_FILE @$(ECHO) $(OBJDIR)/$(LIBRARY).res >> $@ endif @@ -256,9 +256,9 @@ $(ACTUAL_LIBRARY):: $(COMPILE_FILES_o) $(FILES_m) $(FILES_reorder) @$(ECHO) "STATS: LIBRARY=$(LIBRARY), PRODUCT=$(PRODUCT), OPTIMIZATION_LEVEL=$(OPTIMIZATION_LEVEL)" @$(ECHO) "Rebuilding $@ because of $?" ifeq ($(LIBRARY), fdlibm) - $(AR) $(ARFLAGS) $@ $(FILES_o) + $(AR) $(ARFLAGS) $@ $(sort $(FILES_o)) else # LIBRARY - $(LINKER) $(SHARED_LIBRARY_FLAG) -o $@ $(FILES_o) $(LDLIBS) + $(LINKER) $(SHARED_LIBRARY_FLAG) -o $@ $(sort $(FILES_o)) $(LDLIBS) @$(call binary_file_verification,$@) ifeq ($(WRITE_LIBVERSION),true) $(MCS) -d -a "$(FULL_VERSION)" $@ diff --git a/jdk/make/common/Program.gmk b/jdk/make/common/Program.gmk index 5a2e7464c73..094d18ff997 100644 --- a/jdk/make/common/Program.gmk +++ b/jdk/make/common/Program.gmk @@ -262,7 +262,7 @@ else $(ECHO) Rebuilding $@ because of $$1 $$2 $$3 $$4 $$5 $$6 $${7:+...}; @$(MKDIR) -p $(TEMPDIR) $(LINK_PRE_CMD) $(CC) $(CC_OBJECT_OUTPUT_FLAG)$@ $(LDFLAGS) \ - $(FILES_o) $(THREADLIBS) $(LDLIBS) + $(sort $(FILES_o)) $(THREADLIBS) $(LDLIBS) ifeq ($(findstring privileged, $(INFO_PLIST_FILE)), privileged) -codesign -s openjdk_codesign $@ endif @@ -392,8 +392,6 @@ VERSION_DEFINES += -DFULL_VERSION='"$(FULL_VERSION)"' VERSION_DEFINES += -DJDK_MAJOR_VERSION='"$(JDK_MAJOR_VERSION)"' \ -DJDK_MINOR_VERSION='"$(JDK_MINOR_VERSION)"' - - $(OBJDIR)/main.$(OBJECT_SUFFIX): $(LAUNCHER_SHARE_SRC)/bin/main.c @$(prep-target) $(COMPILE.c) $(CC_OBJECT_OUTPUT_FLAG)$(OBJDIR)/main.$(OBJECT_SUFFIX) \ diff --git a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java index 76d8161c749..1704b3bdd25 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java @@ -40,6 +40,7 @@ import java.awt.image.VolatileImage; import java.awt.peer.ComponentPeer; import java.awt.peer.ContainerPeer; +import java.awt.peer.KeyboardFocusManagerPeer; import java.util.concurrent.atomic.AtomicBoolean; import java.lang.reflect.Field; import java.security.AccessController; @@ -894,15 +895,15 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent> ", focusedWindowChangeAllowed=" + focusedWindowChangeAllowed + ", time= " + time + ", cause=" + cause); } - if (LWKeyboardFocusManagerPeer.getInstance(getAppContext()). - processSynchronousLightweightTransfer(getTarget(), lightweightChild, temporary, - focusedWindowChangeAllowed, time)) { + if (LWKeyboardFocusManagerPeer.processSynchronousLightweightTransfer( + getTarget(), lightweightChild, temporary, + focusedWindowChangeAllowed, time)) { return true; } - int result = LWKeyboardFocusManagerPeer.getInstance(getAppContext()). - shouldNativelyFocusHeavyweight(getTarget(), lightweightChild, temporary, - focusedWindowChangeAllowed, time, cause); + int result = LWKeyboardFocusManagerPeer.shouldNativelyFocusHeavyweight( + getTarget(), lightweightChild, temporary, + focusedWindowChangeAllowed, time, cause); switch (result) { case LWKeyboardFocusManagerPeer.SNFH_FAILURE: return false; @@ -951,14 +952,13 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent> return false; } - LWComponentPeer focusOwnerPeer = - LWKeyboardFocusManagerPeer.getInstance(getAppContext()). - getFocusOwner(); - Component focusOwner = (focusOwnerPeer != null) ? focusOwnerPeer.getTarget() : null; + KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); + Component focusOwner = kfmPeer.getCurrentFocusOwner(); return LWKeyboardFocusManagerPeer.deliverFocus(lightweightChild, getTarget(), temporary, focusedWindowChangeAllowed, time, cause, focusOwner); + case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED: return true; } @@ -1251,9 +1251,6 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent> if (!target.isFocusOwner() && LWKeyboardFocusManagerPeer.shouldFocusOnClick(target)) { LWKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT); - } else { - // Anyway request focus to the toplevel. - getWindowPeerOrSelf().requestWindowFocus(CausedFocusEvent.Cause.MOUSE_EVENT); } } @@ -1263,8 +1260,8 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent> protected void handleJavaFocusEvent(FocusEvent e) { // Note that the peer receives all the FocusEvents from // its lightweight children as well - LWKeyboardFocusManagerPeer.getInstance(getAppContext()). - setFocusOwner(e.getID() == FocusEvent.FOCUS_GAINED ? this : null); + KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); + kfmPeer.setCurrentFocusOwner(e.getID() == FocusEvent.FOCUS_GAINED ? getTarget() : null); } /** diff --git a/jdk/src/macosx/classes/sun/lwawt/LWKeyboardFocusManagerPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWKeyboardFocusManagerPeer.java index 4263660517f..421c8af57e0 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWKeyboardFocusManagerPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWKeyboardFocusManagerPeer.java @@ -26,85 +26,47 @@ package sun.lwawt; import java.awt.Component; -import java.awt.KeyboardFocusManager; import java.awt.Window; - -import java.util.Map; -import java.util.HashMap; - -import sun.awt.AWTAccessor; -import sun.awt.AppContext; import sun.awt.KeyboardFocusManagerPeerImpl; public class LWKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl { + private static final LWKeyboardFocusManagerPeer inst = new LWKeyboardFocusManagerPeer(); - private Object lock = new Object(); - private LWWindowPeer focusedWindow; - private LWComponentPeer focusOwner; + private Window focusedWindow; + private Component focusOwner; - private static Map<KeyboardFocusManager, LWKeyboardFocusManagerPeer> instances = - new HashMap<KeyboardFocusManager, LWKeyboardFocusManagerPeer>(); - - public static synchronized LWKeyboardFocusManagerPeer getInstance(AppContext ctx) { - return getInstance(AWTAccessor.getKeyboardFocusManagerAccessor(). - getCurrentKeyboardFocusManager(ctx)); + public static LWKeyboardFocusManagerPeer getInstance() { + return inst; } - public static synchronized LWKeyboardFocusManagerPeer getInstance(KeyboardFocusManager manager) { - LWKeyboardFocusManagerPeer instance = instances.get(manager); - if (instance == null) { - instance = new LWKeyboardFocusManagerPeer(manager); - instances.put(manager, instance); + private LWKeyboardFocusManagerPeer() { + } + + @Override + public void setCurrentFocusedWindow(Window win) { + synchronized (this) { + focusedWindow = win; } - return instance; - } - - public LWKeyboardFocusManagerPeer(KeyboardFocusManager manager) { - super(manager); } @Override public Window getCurrentFocusedWindow() { - synchronized (lock) { - return (focusedWindow != null) ? (Window)focusedWindow.getTarget() : null; + synchronized (this) { + return focusedWindow; } } @Override public Component getCurrentFocusOwner() { - synchronized (lock) { - return (focusOwner != null) ? focusOwner.getTarget() : null; + synchronized (this) { + return focusOwner; } } @Override public void setCurrentFocusOwner(Component comp) { - synchronized (lock) { - focusOwner = (comp != null) ? (LWComponentPeer)comp.getPeer() : null; - } - } - - void setFocusedWindow(LWWindowPeer peer) { - synchronized (lock) { - focusedWindow = peer; - } - } - - LWWindowPeer getFocusedWindow() { - synchronized (lock) { - return focusedWindow; - } - } - - void setFocusOwner(LWComponentPeer peer) { - synchronized (lock) { - focusOwner = peer; - } - } - - LWComponentPeer getFocusOwner() { - synchronized (lock) { - return focusOwner; + synchronized (this) { + focusOwner = comp; } } } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java index 04fd4066cfe..3c6ab83bcd6 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java @@ -415,8 +415,8 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { } @Override - public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) { - return LWKeyboardFocusManagerPeer.getInstance(manager); + public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() { + return LWKeyboardFocusManagerPeer.getInstance(); } @Override diff --git a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java index 3b7cb79728c..8212722dfbc 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -88,10 +88,16 @@ public class LWWindowPeer private volatile int windowState = Frame.NORMAL; - // A peer where the last mouse event came to. Used to generate - // MOUSE_ENTERED/EXITED notifications and by cursor manager to + // check that the mouse is over the window + private volatile boolean isMouseOver = false; + + // A peer where the last mouse event came to. Used by cursor manager to // find the component under cursor - private static volatile LWComponentPeer lastMouseEventPeer = null; + private static volatile LWComponentPeer lastCommonMouseEventPeer = null; + + // A peer where the last mouse event came to. Used to generate + // MOUSE_ENTERED/EXITED notifications + private volatile LWComponentPeer lastMouseEventPeer; // Peers where all dragged/released events should come to, // depending on what mouse button is being dragged according to Cocoa @@ -232,8 +238,7 @@ public class LWWindowPeer // TODO: update graphicsConfig, see 4868278 platformWindow.setVisible(visible); if (isSimpleWindow()) { - LWKeyboardFocusManagerPeer manager = LWKeyboardFocusManagerPeer. - getInstance(getAppContext()); + KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); if (visible) { if (!getTarget().isAutoRequestFocus()) { @@ -242,7 +247,7 @@ public class LWWindowPeer requestWindowFocus(CausedFocusEvent.Cause.ACTIVATION); } // Focus the owner in case this window is focused. - } else if (manager.getCurrentFocusedWindow() == getTarget()) { + } else if (kfmPeer.getCurrentFocusedWindow() == getTarget()) { // Transfer focus to the owner. LWWindowPeer owner = getOwnerFrameDialog(LWWindowPeer.this); if (owner != null) { @@ -707,66 +712,65 @@ public class LWWindowPeer Rectangle r = getBounds(); // findPeerAt() expects parent coordinates LWComponentPeer targetPeer = findPeerAt(r.x + x, r.y + y); - LWWindowPeer lastWindowPeer = - (lastMouseEventPeer != null) ? lastMouseEventPeer.getWindowPeerOrSelf() : null; - LWWindowPeer curWindowPeer = - (targetPeer != null) ? targetPeer.getWindowPeerOrSelf() : null; if (id == MouseEvent.MOUSE_EXITED) { - // Sometimes we may get MOUSE_EXITED after lastMouseEventPeer is switched - // to a peer from another window. So we must first check if this peer is - // the same as lastWindowPeer - if (lastWindowPeer == this) { - if (isEnabled()) { + isMouseOver = false; + if (lastMouseEventPeer != null) { + if (lastMouseEventPeer.isEnabled()) { Point lp = lastMouseEventPeer.windowToLocal(x, y, - lastWindowPeer); + this); postEvent(new MouseEvent(lastMouseEventPeer.getTarget(), - MouseEvent.MOUSE_EXITED, when, - modifiers, lp.x, lp.y, screenX, - screenY, clickCount, popupTrigger, - button)); + MouseEvent.MOUSE_EXITED, when, + modifiers, lp.x, lp.y, screenX, + screenY, clickCount, popupTrigger, + button)); + } + + // Sometimes we may get MOUSE_EXITED after lastCommonMouseEventPeer is switched + // to a peer from another window. So we must first check if this peer is + // the same as lastWindowPeer + if (lastCommonMouseEventPeer != null && lastCommonMouseEventPeer.getWindowPeerOrSelf() == this) { + lastCommonMouseEventPeer = null; } lastMouseEventPeer = null; } - } else { - if (targetPeer != lastMouseEventPeer) { - - if (id != MouseEvent.MOUSE_DRAGGED || lastMouseEventPeer == null) { - // lastMouseEventPeer may be null if mouse was out of Java windows - if (lastMouseEventPeer != null && lastMouseEventPeer.isEnabled()) { - // Sometimes, MOUSE_EXITED is not sent by delegate (or is sent a bit - // later), in which case lastWindowPeer is another window - if (lastWindowPeer != this) { - Point oldp = lastMouseEventPeer.windowToLocal(x, y, lastWindowPeer); - // Additionally translate from this to lastWindowPeer coordinates - Rectangle lr = lastWindowPeer.getBounds(); - oldp.x += r.x - lr.x; - oldp.y += r.y - lr.y; - postEvent(new MouseEvent(lastMouseEventPeer.getTarget(), - MouseEvent.MOUSE_EXITED, - when, modifiers, - oldp.x, oldp.y, screenX, screenY, - clickCount, popupTrigger, button)); - } else { - Point oldp = lastMouseEventPeer.windowToLocal(x, y, this); - postEvent(new MouseEvent(lastMouseEventPeer.getTarget(), - MouseEvent.MOUSE_EXITED, - when, modifiers, - oldp.x, oldp.y, screenX, screenY, - clickCount, popupTrigger, button)); - } - } - if (targetPeer != null && targetPeer.isEnabled() && id != MouseEvent.MOUSE_ENTERED) { - Point newp = targetPeer.windowToLocal(x, y, curWindowPeer); + } else if(id == MouseEvent.MOUSE_ENTERED) { + isMouseOver = true; + if (targetPeer != null) { + if (targetPeer.isEnabled()) { + Point lp = targetPeer.windowToLocal(x, y, this); postEvent(new MouseEvent(targetPeer.getTarget(), - MouseEvent.MOUSE_ENTERED, - when, modifiers, - newp.x, newp.y, screenX, screenY, - clickCount, popupTrigger, button)); - } + MouseEvent.MOUSE_ENTERED, when, + modifiers, lp.x, lp.y, screenX, + screenY, clickCount, popupTrigger, + button)); } + lastCommonMouseEventPeer = targetPeer; lastMouseEventPeer = targetPeer; } + } else { + PlatformWindow topmostPlatforWindow = + platformWindow.getTopmostPlatformWindowUnderMouse(); + + LWWindowPeer topmostWindowPeer = + topmostPlatforWindow != null ? topmostPlatforWindow.getPeer() : null; + + // topmostWindowPeer == null condition is added for the backward + // compatibility with applets. It can be removed when the + // getTopmostPlatformWindowUnderMouse() method will be properly + // implemented in CPlatformEmbeddedFrame class + if (topmostWindowPeer == this || topmostWindowPeer == null) { + generateMouseEnterExitEventsForComponents(when, button, x, y, + screenX, screenY, modifiers, clickCount, popupTrigger, + targetPeer); + } else { + LWComponentPeer topmostTargetPeer = + topmostWindowPeer != null ? topmostWindowPeer.findPeerAt(r.x + x, r.y + y) : null; + topmostWindowPeer.generateMouseEnterExitEventsForComponents(when, button, x, y, + screenX, screenY, modifiers, clickCount, popupTrigger, + topmostTargetPeer); + } + // TODO: fill "bdata" member of AWTEvent int eventButtonMask = (button > 0)? MouseEvent.getMaskForButton(button) : 0; @@ -794,6 +798,14 @@ public class LWWindowPeer mouseClickButtons |= eventButtonMask; } + // The window should be focused on mouse click. If it gets activated by the native platform, + // this request will be no op. It will take effect when: + // 1. A simple not focused window is clicked. + // 2. An active but not focused owner frame/dialog is clicked. + // The mouse event then will trigger a focus request "in window" to the component, so the window + // should gain focus before. + requestWindowFocus(CausedFocusEvent.Cause.MOUSE_EVENT); + mouseDownTarget[targetIdx] = targetPeer; } else if (id == MouseEvent.MOUSE_DRAGGED) { // Cocoa dragged event has the information about which mouse @@ -816,19 +828,13 @@ public class LWWindowPeer // mouseClickButtons is updated below, after MOUSE_CLICK is sent } - // check if we receive mouseEvent from outside the window's bounds - // it can be either mouseDragged or mouseReleased - if (curWindowPeer == null) { - //TODO This can happen if this window is invisible. this is correct behavior in this case? - curWindowPeer = this; - } if (targetPeer == null) { //TODO This can happen if this window is invisible. this is correct behavior in this case? targetPeer = this; } - Point lp = targetPeer.windowToLocal(x, y, curWindowPeer); + Point lp = targetPeer.windowToLocal(x, y, this); if (targetPeer.isEnabled()) { MouseEvent event = new MouseEvent(targetPeer.getTarget(), id, when, modifiers, lp.x, lp.y, @@ -852,6 +858,38 @@ public class LWWindowPeer notifyUpdateCursor(); } + private void generateMouseEnterExitEventsForComponents(long when, + int button, int x, int y, int screenX, int screenY, + int modifiers, int clickCount, boolean popupTrigger, + LWComponentPeer targetPeer) { + + if (!isMouseOver || targetPeer == lastMouseEventPeer) { + return; + } + + // Generate Mouse Exit for components + if (lastMouseEventPeer != null && lastMouseEventPeer.isEnabled()) { + Point oldp = lastMouseEventPeer.windowToLocal(x, y, this); + postEvent(new MouseEvent(lastMouseEventPeer.getTarget(), + MouseEvent.MOUSE_EXITED, + when, modifiers, + oldp.x, oldp.y, screenX, screenY, + clickCount, popupTrigger, button)); + } + lastCommonMouseEventPeer = targetPeer; + lastMouseEventPeer = targetPeer; + + // Generate Mouse Enter for components + if (targetPeer != null && targetPeer.isEnabled()) { + Point newp = targetPeer.windowToLocal(x, y, this); + postEvent(new MouseEvent(targetPeer.getTarget(), + MouseEvent.MOUSE_ENTERED, + when, modifiers, + newp.x, newp.y, screenX, screenY, + clickCount, popupTrigger, button)); + } + } + public void dispatchMouseWheelEvent(long when, int x, int y, int modifiers, int scrollType, int scrollAmount, int wheelRotation, double preciseWheelRotation, @@ -884,20 +922,16 @@ public class LWWindowPeer public void dispatchKeyEvent(int id, long when, int modifiers, int keyCode, char keyChar, int keyLocation) { - LWComponentPeer focusOwner = - LWKeyboardFocusManagerPeer.getInstance(getAppContext()). - getFocusOwner(); + LWKeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); + Component focusOwner = kfmPeer.getCurrentFocusOwner(); - // Null focus owner may receive key event when - // application hides the focused window upon ESC press - // (AWT transfers/clears the focus owner) and pending ESC release - // may come to already hidden window. This check eliminates NPE. - if (focusOwner != null) { - KeyEvent event = - new KeyEvent(focusOwner.getTarget(), id, when, modifiers, - keyCode, keyChar, keyLocation); - focusOwner.postEvent(event); + if (focusOwner == null) { + focusOwner = kfmPeer.getCurrentFocusedWindow(); + if (focusOwner == null) { + focusOwner = this.getTarget(); + } } + postEvent(new KeyEvent(focusOwner, id, when, modifiers, keyCode, keyChar, keyLocation)); } @@ -1096,11 +1130,11 @@ public class LWWindowPeer } public static LWWindowPeer getWindowUnderCursor() { - return lastMouseEventPeer != null ? lastMouseEventPeer.getWindowPeerOrSelf() : null; + return lastCommonMouseEventPeer != null ? lastCommonMouseEventPeer.getWindowPeerOrSelf() : null; } public static LWComponentPeer<?, ?> getPeerUnderCursor() { - return lastMouseEventPeer; + return lastCommonMouseEventPeer; } /* @@ -1213,10 +1247,8 @@ public class LWWindowPeer } } - LWKeyboardFocusManagerPeer manager = LWKeyboardFocusManagerPeer. - getInstance(getAppContext()); - - Window oppositeWindow = becomesFocused ? manager.getCurrentFocusedWindow() : null; + KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); + Window oppositeWindow = becomesFocused ? kfmPeer.getCurrentFocusedWindow() : null; // Note, the method is not called: // - when the opposite (gaining focus) window is an owned/owner window. @@ -1229,10 +1261,10 @@ public class LWWindowPeer grabbingWindow.ungrab(); } - manager.setFocusedWindow(becomesFocused ? LWWindowPeer.this : null); + kfmPeer.setCurrentFocusedWindow(becomesFocused ? getTarget() : null); int eventID = becomesFocused ? WindowEvent.WINDOW_GAINED_FOCUS : WindowEvent.WINDOW_LOST_FOCUS; - WindowEvent windowEvent = new WindowEvent(getTarget(), eventID, oppositeWindow); + WindowEvent windowEvent = new TimedWindowEvent(getTarget(), eventID, oppositeWindow, System.currentTimeMillis()); // TODO: wrap in SequencedEvent postEvent(windowEvent); diff --git a/jdk/src/macosx/classes/sun/lwawt/PlatformWindow.java b/jdk/src/macosx/classes/sun/lwawt/PlatformWindow.java index 2c7df7c3308..d4a470de5cf 100644 --- a/jdk/src/macosx/classes/sun/lwawt/PlatformWindow.java +++ b/jdk/src/macosx/classes/sun/lwawt/PlatformWindow.java @@ -118,6 +118,8 @@ public interface PlatformWindow { public void setAlwaysOnTop(boolean value); + public PlatformWindow getTopmostPlatformWindowUnderMouse(); + public void updateFocusableWindowState(); public boolean rejectFocusRequest(CausedFocusEvent.Cause cause); diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java index c21247f1057..e93f1ec4b9f 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java @@ -151,6 +151,10 @@ public class CPlatformEmbeddedFrame implements PlatformWindow { @Override public void setAlwaysOnTop(boolean value) {} + // This method should be properly implemented for applets. + // It returns null just as a stub. + public PlatformWindow getTopmostPlatformWindowUnderMouse() { return null; } + @Override public void updateFocusableWindowState() {} diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index b826f74dd04..15502d1f8d7 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -61,8 +61,9 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo private static native void nativeSetNSWindowRepresentedFilename(long nsWindowPtr, String representedFilename); private static native void nativeSetNSWindowSecurityWarningPositioning(long nsWindowPtr, double x, double y, float biasX, float biasY); private static native void nativeSetEnabled(long nsWindowPtr, boolean isEnabled); - private static native void nativeSynthesizeMouseEnteredExitedEvents(long nsWindowPtr); + private static native void nativeSynthesizeMouseEnteredExitedEvents(); private static native void nativeDispose(long nsWindowPtr); + private static native CPlatformWindow nativeGetTopmostPlatformWindowUnderMouse(); private static native int nativeGetNSWindowDisplayID_AppKitThread(long nsWindowPtr); @@ -588,7 +589,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo } } - nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr); + nativeSynthesizeMouseEnteredExitedEvents(); // Configure stuff #2 updateFocusabilityForAutoRequestFocus(true); @@ -729,6 +730,10 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo setStyleBits(ALWAYS_ON_TOP, isAlwaysOnTop); } + public PlatformWindow getTopmostPlatformWindowUnderMouse(){ + return CPlatformWindow.nativeGetTopmostPlatformWindowUnderMouse(); + } + @Override public void setOpacity(float opacity) { CWrapper.NSWindow.setAlphaValue(getNSWindowPtr(), opacity); @@ -803,7 +808,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo throw new RuntimeException("Unknown window state: " + windowState); } - nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr); + nativeSynthesizeMouseEnteredExitedEvents(); // NOTE: the SWP.windowState field gets updated to the newWindowState // value when the native notification comes to us diff --git a/jdk/src/macosx/native/com/apple/laf/ScreenMenu.m b/jdk/src/macosx/native/com/apple/laf/ScreenMenu.m index 8dab11cc624..4b49b5b5d79 100644 --- a/jdk/src/macosx/native/com/apple/laf/ScreenMenu.m +++ b/jdk/src/macosx/native/com/apple/laf/ScreenMenu.m @@ -37,7 +37,11 @@ #import "ThreadUtilities.h" #import "CMenuBar.h" - +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + static JNF_CLASS_CACHE(sjc_ScreenMenu, "com/apple/laf/ScreenMenu"); static jint ns2awtModifiers(NSUInteger keyMods) { @@ -97,7 +101,7 @@ static jint ns2awtMouseButton(NSInteger mouseButton) { { if (self.javaObjectWrapper == nil) { #ifdef DEBUG - NSLog(@"_javaObject is NULL: (%s - %s : %d)", __FILE__, __FUNCTION__, __LINE__); + NSLog(@"_javaObject is NULL: (%s - %s : %d)", THIS_FILE, __FUNCTION__, __LINE__); #endif return; } @@ -115,7 +119,7 @@ JNF_COCOA_EXIT(env); { if (self.javaObjectWrapper == nil) { #ifdef DEBUG - NSLog(@"_javaObject is NULL: (%s - %s : %d)", __FILE__, __FUNCTION__, __LINE__); + NSLog(@"_javaObject is NULL: (%s - %s : %d)", THIS_FILE, __FUNCTION__, __LINE__); #endif return; } @@ -133,7 +137,7 @@ JNF_COCOA_EXIT(env); { if (self.javaObjectWrapper == nil) { #ifdef DEBUG - NSLog(@"_javaObject is NULL: (%s - %s : %d)", __FILE__, __FUNCTION__, __LINE__); + NSLog(@"_javaObject is NULL: (%s - %s : %d)", THIS_FILE, __FUNCTION__, __LINE__); #endif return; } diff --git a/jdk/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiOut.c b/jdk/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiOut.c index e9814153e65..fe29efdccfd 100644 --- a/jdk/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiOut.c +++ b/jdk/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiOut.c @@ -26,6 +26,11 @@ //#define USE_ERROR //#define USE_TRACE +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + #if USE_PLATFORM_MIDI_OUT == TRUE #include "PLATFORM_API_MacOSX_MidiUtils.h" @@ -128,7 +133,7 @@ INT32 MIDI_OUT_SendShortMessage(MidiDeviceHandle* handle, UINT32 packedMsg, UINT case 0xF7: // System exclusive fprintf(stderr, "%s: %d->internal error: sysex message status=0x%X while sending short message\n", - __FILE__, __LINE__, data[0]); + THIS_FILE, __LINE__, data[0]); byteIsInvalid = TRUE; break; @@ -154,7 +159,7 @@ INT32 MIDI_OUT_SendShortMessage(MidiDeviceHandle* handle, UINT32 packedMsg, UINT default: // Invalid message fprintf(stderr, "%s: %d->Invalid message: message status=0x%X while sending short message\n", - __FILE__, __LINE__, data[0]); + THIS_FILE, __LINE__, data[0]); byteIsInvalid = TRUE; break; } @@ -164,7 +169,7 @@ INT32 MIDI_OUT_SendShortMessage(MidiDeviceHandle* handle, UINT32 packedMsg, UINT default: // This can't happen, but handle it anyway. fprintf(stderr, "%s: %d->Invalid message: message status=0x%X while sending short message\n", - __FILE__, __LINE__, data[0]); + THIS_FILE, __LINE__, data[0]); byteIsInvalid = TRUE; break; } diff --git a/jdk/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiUtils.c b/jdk/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiUtils.c index b044dac0fc7..d5e47fa1f0a 100644 --- a/jdk/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiUtils.c +++ b/jdk/src/macosx/native/com/sun/media/sound/PLATFORM_API_MacOSX_MidiUtils.c @@ -42,6 +42,11 @@ //#define USE_ERROR //#define USE_TRACE +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + #if (USE_PLATFORM_MIDI_IN == TRUE) || (USE_PLATFORM_MIDI_OUT == TRUE) #include "PLATFORM_API_MacOSX_MidiUtils.h" @@ -317,7 +322,7 @@ static void processMessagesForPacket(const MIDIPacket* packet, MacMidiDeviceHand packedMsg = pendingMessageStatus | pendingData[0] << 8; } else { fprintf(stderr, "%s: %d->internal error: pendingMessageStatus=0x%X, pendingDataLength=%d\n", - __FILE__, __LINE__, pendingMessageStatus, pendingDataLength); + THIS_FILE, __LINE__, pendingMessageStatus, pendingDataLength); byteIsInvalid = TRUE; } pendingDataLength = 0; diff --git a/jdk/src/macosx/native/sun/awt/AWTView.h b/jdk/src/macosx/native/sun/awt/AWTView.h index f1d141fc2a0..b0246f862c8 100644 --- a/jdk/src/macosx/native/sun/awt/AWTView.h +++ b/jdk/src/macosx/native/sun/awt/AWTView.h @@ -33,8 +33,8 @@ @private jobject m_cPlatformView; - // Handler for the tracking rect needed for Enter/Exit events management. - NSTrackingRectTag rolloverTrackingRectTag; + // Handler for the tracking area needed for Enter/Exit events management. + NSTrackingArea* rolloverTrackingArea; // TODO: NSMenu *contextualMenu; @@ -61,7 +61,7 @@ - (id) initWithRect:(NSRect) rect platformView:(jobject)cPlatformView windowLayer:(CALayer*)windowLayer; - (void) deliverJavaMouseEvent: (NSEvent *) event; -- (void) resetTrackingRect; +- (void) resetTrackingArea; - (void) deliverJavaKeyEventHelper: (NSEvent *) event; - (jobject) awtComponent:(JNIEnv *)env; diff --git a/jdk/src/macosx/native/sun/awt/AWTView.m b/jdk/src/macosx/native/sun/awt/AWTView.m index b4cb30aa13c..2d271777321 100644 --- a/jdk/src/macosx/native/sun/awt/AWTView.m +++ b/jdk/src/macosx/native/sun/awt/AWTView.m @@ -82,6 +82,7 @@ AWT_ASSERT_APPKIT_THREAD; fPAHNeedsToSelect = NO; mouseIsOver = NO; + [self resetTrackingArea]; if (windowLayer != nil) { self.cglLayer = windowLayer; @@ -146,7 +147,7 @@ AWT_ASSERT_APPKIT_THREAD; [[self window] makeFirstResponder: self]; }]; if ([self window] != NULL) { - [self resetTrackingRect]; + [self resetTrackingArea]; } } @@ -368,30 +369,31 @@ AWT_ASSERT_APPKIT_THREAD; JNFCallVoidMethod(env, m_cPlatformView, jm_deliverMouseEvent, jEvent); } - -- (void) clearTrackingRect { - if (rolloverTrackingRectTag > 0) { - [self removeTrackingRect:rolloverTrackingRectTag]; - rolloverTrackingRectTag = 0; +- (void) resetTrackingArea { + if (rolloverTrackingArea != nil) { + [self removeTrackingArea:rolloverTrackingArea]; + [rolloverTrackingArea release]; } -} -- (void) resetTrackingRect { - [self clearTrackingRect]; - rolloverTrackingRectTag = [self addTrackingRect:[self visibleRect] - owner:self - userData:NULL - assumeInside:NO]; + int options = (NSTrackingActiveInActiveApp | NSTrackingMouseEnteredAndExited | + NSTrackingMouseMoved | NSTrackingEnabledDuringMouseDrag); + + rolloverTrackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect] + options: options + owner:self + userInfo:nil + ]; + [self addTrackingArea:rolloverTrackingArea]; } - (void)updateTrackingAreas { [super updateTrackingAreas]; - [self resetTrackingRect]; + [self resetTrackingArea]; } - (void) resetCursorRects { [super resetCursorRects]; - [self resetTrackingRect]; + [self resetTrackingArea]; } -(void) deliverJavaKeyEventHelper: (NSEvent *) event { @@ -402,7 +404,7 @@ AWT_ASSERT_APPKIT_THREAD; } [sLastKeyEvent release]; sLastKeyEvent = [event retain]; - + [AWTToolkit eventCountPlusPlus]; JNIEnv *env = [ThreadUtilities getJNIEnv]; diff --git a/jdk/src/macosx/native/sun/awt/AWTWindow.m b/jdk/src/macosx/native/sun/awt/AWTWindow.m index 48ab428521c..f0d689b546e 100644 --- a/jdk/src/macosx/native/sun/awt/AWTWindow.m +++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m @@ -238,10 +238,12 @@ AWT_ASSERT_APPKIT_THREAD; return self; } -// checks that this window is under the mouse cursor and this point is not overlapped by others windows -- (BOOL) isTopmostWindowUnderMouse { ++ (BOOL) isAWTWindow:(NSWindow *)window { + return [window isKindOfClass: [AWTWindow_Panel class]] || [window isKindOfClass: [AWTWindow_Normal class]]; +} - int currentWinID = [self.nsWindow windowNumber]; +// returns id for the topmost window under mouse ++ (NSInteger) getTopmostWindowUnderMouseID { NSRect screenRect = [[NSScreen mainScreen] frame]; NSPoint nsMouseLocation = [NSEvent mouseLocation]; @@ -249,53 +251,77 @@ AWT_ASSERT_APPKIT_THREAD; NSMutableArray *windows = (NSMutableArray *)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID); - for (NSDictionary *window in windows) { - int layer = [[window objectForKey:(id)kCGWindowLayer] intValue]; + NSInteger layer = [[window objectForKey:(id)kCGWindowLayer] integerValue]; if (layer == 0) { - int winID = [[window objectForKey:(id)kCGWindowNumber] intValue]; CGRect rect; CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[window objectForKey:(id)kCGWindowBounds], &rect); if (CGRectContainsPoint(rect, cgMouseLocation)) { - return currentWinID == winID; - } else if (currentWinID == winID) { - return NO; + return [[window objectForKey:(id)kCGWindowNumber] integerValue]; } } } - return NO; + return -1; } -- (void) synthesizeMouseEnteredExitedEvents { +// checks that this window is under the mouse cursor and this point is not overlapped by others windows +- (BOOL) isTopmostWindowUnderMouse { + return [self.nsWindow windowNumber] == [AWTWindow getTopmostWindowUnderMouseID]; +} - int eventType = 0; - BOOL isUnderMouse = [self isTopmostWindowUnderMouse]; - BOOL mouseIsOver = [[self.nsWindow contentView] mouseIsOver]; ++ (AWTWindow *) getTopmostWindowUnderMouse { + NSEnumerator *windowEnumerator = [[NSApp windows] objectEnumerator]; + NSWindow *window; - if (isUnderMouse && !mouseIsOver) { - eventType = NSMouseEntered; - } else if (!isUnderMouse && mouseIsOver) { - eventType = NSMouseExited; - } else { - return; + NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID]; + + while ((window = [windowEnumerator nextObject]) != nil) { + if ([window windowNumber] == topmostWindowUnderMouseID) { + BOOL isAWTWindow = [AWTWindow isAWTWindow: window]; + return isAWTWindow ? (AWTWindow *) [window delegate] : nil; + } } + return nil; +} + ++ (void) synthesizeMouseEnteredExitedEvents:(NSWindow*)window withType:(NSEventType)eventType { NSPoint screenLocation = [NSEvent mouseLocation]; - NSPoint windowLocation = [self.nsWindow convertScreenToBase: screenLocation]; + NSPoint windowLocation = [window convertScreenToBase: screenLocation]; int modifierFlags = (eventType == NSMouseEntered) ? NSMouseEnteredMask : NSMouseExitedMask; NSEvent *mouseEvent = [NSEvent enterExitEventWithType: eventType - location: windowLocation - modifierFlags: modifierFlags - timestamp: 0 - windowNumber: [self.nsWindow windowNumber] - context: nil - eventNumber: 0 - trackingNumber: 0 - userData: nil - ]; + location: windowLocation + modifierFlags: modifierFlags + timestamp: 0 + windowNumber: [window windowNumber] + context: nil + eventNumber: 0 + trackingNumber: 0 + userData: nil + ]; - [[self.nsWindow contentView] deliverJavaMouseEvent: mouseEvent]; + [[window contentView] deliverJavaMouseEvent: mouseEvent]; +} + ++ (void) synthesizeMouseEnteredExitedEventsForAllWindows { + + NSInteger topmostWindowUnderMouseID = [AWTWindow getTopmostWindowUnderMouseID]; + NSArray *windows = [NSApp windows]; + NSWindow *window; + + NSEnumerator *windowEnumerator = [windows objectEnumerator]; + while ((window = [windowEnumerator nextObject]) != nil) { + if ([AWTWindow isAWTWindow: window]) { + BOOL isUnderMouse = ([window windowNumber] == topmostWindowUnderMouseID); + BOOL mouseIsOver = [[window contentView] mouseIsOver]; + if (isUnderMouse && !mouseIsOver) { + [AWTWindow synthesizeMouseEnteredExitedEvents:window withType:NSMouseEntered]; + } else if (!isUnderMouse && mouseIsOver) { + [AWTWindow synthesizeMouseEnteredExitedEvents:window withType:NSMouseExited]; + } + } + } } - (void) dealloc { @@ -825,7 +851,7 @@ AWT_ASSERT_NOT_APPKIT_THREAD; // (this will also re-enable screen updates, which were disabled above) // TODO: send PaintEvent - [window synthesizeMouseEnteredExitedEvents]; + [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows]; }]; JNF_COCOA_EXIT(env); @@ -1038,24 +1064,44 @@ AWT_ASSERT_NOT_APPKIT_THREAD; JNF_COCOA_EXIT(env); } +/* + * Class: sun_lwawt_macosx_CPlatformWindow + * Method: nativeGetTopmostPlatformWindowUnderMouse + * Signature: (J)V + */ +JNIEXPORT jobject +JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetTopmostPlatformWindowUnderMouse +(JNIEnv *env, jclass clazz) +{ + jobject topmostWindowUnderMouse = nil; + + JNF_COCOA_ENTER(env); + AWT_ASSERT_APPKIT_THREAD; + + AWTWindow *awtWindow = [AWTWindow getTopmostWindowUnderMouse]; + if (awtWindow != nil) { + topmostWindowUnderMouse = [awtWindow.javaPlatformWindow jObject]; + } + + JNF_COCOA_EXIT(env); + + return topmostWindowUnderMouse; +} + /* * Class: sun_lwawt_macosx_CPlatformWindow * Method: nativeSynthesizeMouseEnteredExitedEvents * Signature: (J)V */ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSynthesizeMouseEnteredExitedEvents -(JNIEnv *env, jclass clazz, jlong windowPtr) +(JNIEnv *env, jclass clazz) { JNF_COCOA_ENTER(env); AWT_ASSERT_NOT_APPKIT_THREAD; - NSWindow *nsWindow = OBJC(windowPtr); [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){ AWT_ASSERT_APPKIT_THREAD; - - AWTWindow *window = (AWTWindow*)[nsWindow delegate]; - - [window synthesizeMouseEnteredExitedEvents]; + [AWTWindow synthesizeMouseEnteredExitedEventsForAllWindows]; }]; JNF_COCOA_EXIT(env); diff --git a/jdk/src/macosx/native/sun/awt/CSystemColors.m b/jdk/src/macosx/native/sun/awt/CSystemColors.m index 01ab8016116..4e8c64debd2 100644 --- a/jdk/src/macosx/native/sun/awt/CSystemColors.m +++ b/jdk/src/macosx/native/sun/awt/CSystemColors.m @@ -33,6 +33,11 @@ #import "ThreadUtilities.h" +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + NSColor **sColors = nil; NSColor **appleColors = nil; @@ -130,7 +135,7 @@ static JNF_STATIC_MEMBER_CACHE(jm_systemColorsChanged, jc_LWCToolkit, "systemCol result = (useAppleColor ? appleColors : sColors)[colorIndex]; } else { - NSLog(@"%s: %s %sColor: %ld not found, returning black.", __FILE__, __FUNCTION__, (useAppleColor) ? "Apple" : "System", colorIndex); + NSLog(@"%s: %s %sColor: %ld not found, returning black.", THIS_FILE, __FUNCTION__, (useAppleColor) ? "Apple" : "System", colorIndex); result = [NSColor blackColor]; } diff --git a/jdk/src/macosx/native/sun/awt/CTextPipe.m b/jdk/src/macosx/native/sun/awt/CTextPipe.m index 37e8d4a5eaf..dbf0e01a715 100644 --- a/jdk/src/macosx/native/sun/awt/CTextPipe.m +++ b/jdk/src/macosx/native/sun/awt/CTextPipe.m @@ -36,6 +36,10 @@ #import "QuartzSurfaceData.h" #include "AWTStrike.h" +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif static const CGAffineTransform sInverseTX = { 1, 0, 0, -1, 0, 0 }; @@ -488,7 +492,7 @@ static inline void doDrawGlyphsPipe_getGlyphVectorLengthAndAlloc if (glyphs == NULL || advances == NULL) { (*env)->DeleteLocalRef(env, glyphsArray); - [NSException raise:NSMallocException format:@"%s-%s:%d", __FILE__, __FUNCTION__, __LINE__]; + [NSException raise:NSMallocException format:@"%s-%s:%d", THIS_FILE, __FUNCTION__, __LINE__]; return; } diff --git a/jdk/src/macosx/native/sun/awt/ImageSurfaceData.h b/jdk/src/macosx/native/sun/awt/ImageSurfaceData.h index 0e4d306f252..97094028808 100644 --- a/jdk/src/macosx/native/sun/awt/ImageSurfaceData.h +++ b/jdk/src/macosx/native/sun/awt/ImageSurfaceData.h @@ -41,7 +41,7 @@ void UnlockImagePixels(JNIEnv* env, ImageSDOps* isdo); // If there is an image present, this is a no-op void makeSureImageIsCreated(ImageSDOps* isdo); -struct _ContextInfo +typedef struct _ContextInfo { BOOL useWindowContextReference; BOOL canUseJavaPixelsAsContext; @@ -50,10 +50,9 @@ struct _ContextInfo size_t bytesPerRow; CGImageAlphaInfo alphaInfo; CGColorSpaceRef colorSpace; -} -typedef ContextInfo; +} ContextInfo; -struct _ImageInfo +typedef struct _ImageInfo { size_t bitsPerComponent; size_t bitsPerPixel; @@ -61,8 +60,7 @@ struct _ImageInfo size_t bytesPerRow; CGImageAlphaInfo alphaInfo; CGColorSpaceRef colorSpace; -} -typedef ImageInfo; +} ImageInfo; struct _ImageSDOps { diff --git a/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m b/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m index f2ebd28431f..af7ce4ba38c 100644 --- a/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m +++ b/jdk/src/macosx/native/sun/awt/ImageSurfaceData.m @@ -53,10 +53,6 @@ // for vImage framework headers #include <Accelerate/Accelerate.h> - -// private Quartz routines needed here -CG_EXTERN void CGContextSetCTM(CGContextRef ref, CGAffineTransform tx); - static ContextInfo sDefaultContextInfo[sun_java2d_OSXOffScreenSurfaceData_TYPE_3BYTE_RGB+1] = { {YES, YES, 8, 4, 0, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, NULL}, // TYPE_CUSTOM // special case @@ -942,7 +938,6 @@ PRINT("createContext") // intitalize the context to match the Java coordinate system // BG, since the context is created above, we can just concat - //CGContextSetCTM(qsdo->cgRef, CGAffineTransformMake(1, 0, 0, -1, 0, isdo->height)); CGContextConcatCTM(qsdo->cgRef, CGAffineTransformMake(1, 0, 0, -1, 0, isdo->height)); CGContextSaveGState(qsdo->cgRef); // this will make sure we don't go pass device context settings @@ -1114,7 +1109,10 @@ PRINT("syncFromJavaPixels") if (qsdo->cgRef != NULL) { CGContextSaveGState(qsdo->cgRef); - CGContextSetCTM(qsdo->cgRef, CGAffineTransformMake(1, 0, 0, 1, 0, 0)); + CGAffineTransform currCTM = CGContextGetCTM(qsdo->cgRef); + CGAffineTransform inverse = CGAffineTransformInvert(currCTM); + CGContextConcatCTM(qsdo->cgRef, inverse); + CGContextConcatCTM(qsdo->cgRef, CGAffineTransformMake(1, 0, 0, 1, 0, 0)); CGContextSetBlendMode(qsdo->cgRef, kCGBlendModeCopy); CGContextSetAlpha(qsdo->cgRef, 1.0f); CGContextDrawImage(qsdo->cgRef, CGRectMake(0, 0, width, height), javaImg); diff --git a/jdk/src/macosx/native/sun/awt/QuartzRenderer.m b/jdk/src/macosx/native/sun/awt/QuartzRenderer.m index e5784f69122..7550904096c 100644 --- a/jdk/src/macosx/native/sun/awt/QuartzRenderer.m +++ b/jdk/src/macosx/native/sun/awt/QuartzRenderer.m @@ -50,9 +50,6 @@ // same value as defined in Sun's own code #define XOR_ALPHA_CUTOFF 128 -// private Quartz routines needed here -CG_EXTERN void CGContextSetCTM(CGContextRef ref, CGAffineTransform tx); - static CGFloat gRoundRectCtrlpts[10][12] = { @@ -536,7 +533,7 @@ QUARTZ_RENDERER_INLINE void doImageCG(JNIEnv *env, CGContextRef cgRef, jobject i makeSureImageIsCreated(isdo); - CGAffineTransform ctm = CGContextGetCTM(cgRef); + CGContextSaveGState(cgRef); CGContextConcatCTM(cgRef, CGAffineTransformMake(a, b, c, d, tx, ty)); jint alphaInfo = isdo->contextInfo.alphaInfo & kCGBitmapAlphaInfoMask; @@ -551,7 +548,7 @@ QUARTZ_RENDERER_INLINE void doImageCG(JNIEnv *env, CGContextRef cgRef, jobject i CGImageRelease(subImg); } - CGContextSetCTM(cgRef, ctm); + CGContextRestoreGState(cgRef); UnlockImage(env, isdo); } diff --git a/jdk/src/macosx/native/sun/awt/QuartzSurfaceData.m b/jdk/src/macosx/native/sun/awt/QuartzSurfaceData.m index 8d3784cf2bc..3a0eea126db 100644 --- a/jdk/src/macosx/native/sun/awt/QuartzSurfaceData.m +++ b/jdk/src/macosx/native/sun/awt/QuartzSurfaceData.m @@ -40,9 +40,6 @@ #import <AppKit/AppKit.h> #import "ThreadUtilities.h" -// private Quartz routines needed here -CG_EXTERN void CGContextSetCTM(CGContextRef ref, CGAffineTransform tx); - //#define DEBUG #if defined DEBUG #define PRINT(msg) {fprintf(stderr, "%s\n", msg);} @@ -50,9 +47,6 @@ CG_EXTERN void CGContextSetCTM(CGContextRef ref, CGAffineTransform tx); #define PRINT(msg) {} #endif -// from CGAffineTransformPrivate.h -extern CGPoint CGPointApplyInverseAffineTransform(CGPoint point, CGAffineTransform t); - #define kOffset (0.5f) BOOL gAdjustForJavaDrawing; @@ -608,7 +602,8 @@ PRINT(" SetUpCGContext") // We need to flip both y coefficeints to flip the offset point into the java coordinate system. ctm.b = -ctm.b; ctm.d = -ctm.d; ctm.tx = 0.0f; ctm.ty = 0.0f; CGPoint offsets = {kOffset, kOffset}; - offsets = CGPointApplyInverseAffineTransform(offsets, ctm); + CGAffineTransform inverse = CGAffineTransformInvert(ctm); + offsets = CGPointApplyAffineTransform(offsets, inverse); qsdo->graphicsStateInfo.offsetX = offsets.x; qsdo->graphicsStateInfo.offsetY = offsets.y; } diff --git a/jdk/src/macosx/native/sun/font/AWTStrike.m b/jdk/src/macosx/native/sun/font/AWTStrike.m index fbb39791e79..261bd34ae57 100644 --- a/jdk/src/macosx/native/sun/font/AWTStrike.m +++ b/jdk/src/macosx/native/sun/font/AWTStrike.m @@ -33,6 +33,11 @@ #import "CoreTextSupport.h" //#import "jni_util.h" +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + @implementation AWTStrike static CGAffineTransform sInverseTX = { 1, 0, 0, -1, 0, 0 }; @@ -102,7 +107,7 @@ static CGAffineTransform sInverseTX = { 1, 0, 0, -1, 0, 0 }; #define AWT_FONT_CLEANUP_FINISH \ if (_fontThrowJavaException == YES) { \ char s[512]; \ - sprintf(s, "%s-%s:%d", __FILE__, __FUNCTION__, __LINE__); \ + sprintf(s, "%s-%s:%d", THIS_FILE, __FUNCTION__, __LINE__); \ [JNFException raise:env as:kRuntimeException reason:s]; \ } diff --git a/jdk/src/share/back/error_messages.h b/jdk/src/share/back/error_messages.h index 8e3ae908d9e..b886063f043 100644 --- a/jdk/src/share/back/error_messages.h +++ b/jdk/src/share/back/error_messages.h @@ -42,31 +42,36 @@ const char * jvmtiErrorText(jvmtiError); const char * eventText(int); const char * jdwpErrorText(jdwpError); +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + #define EXIT_ERROR(error,msg) \ { \ print_message(stderr, "JDWP exit error ", "\n", \ "%s(%d): %s [%s:%d]", \ jvmtiErrorText((jvmtiError)error), error, (msg==NULL?"":msg), \ - __FILE__, __LINE__); \ + THIS_FILE, __LINE__); \ debugInit_exit((jvmtiError)error, msg); \ } #define JDI_ASSERT(expression) \ do { \ if (gdata && gdata->assertOn && !(expression)) { \ - jdiAssertionFailed(__FILE__, __LINE__, #expression); \ + jdiAssertionFailed(THIS_FILE, __LINE__, #expression); \ } \ } while (0) #define JDI_ASSERT_MSG(expression, msg) \ do { \ if (gdata && gdata->assertOn && !(expression)) { \ - jdiAssertionFailed(__FILE__, __LINE__, msg); \ + jdiAssertionFailed(THIS_FILE, __LINE__, msg); \ } \ } while (0) #define JDI_ASSERT_FAILED(msg) \ - jdiAssertionFailed(__FILE__, __LINE__, msg) + jdiAssertionFailed(THIS_FILE, __LINE__, msg) void do_pause(void); diff --git a/jdk/src/share/back/log_messages.h b/jdk/src/share/back/log_messages.h index bbab3ba826f..507b62a2c08 100644 --- a/jdk/src/share/back/log_messages.h +++ b/jdk/src/share/back/log_messages.h @@ -33,11 +33,15 @@ void finish_logging(int); #define LOG_NULL ((void)0) +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + #ifdef JDWP_LOGGING - #define _LOG(flavor,args) \ - (log_message_begin(flavor,__FILE__,__LINE__), \ + (log_message_begin(flavor,THIS_FILE,__LINE__), \ log_message_end args) #define LOG_TEST(flag) (gdata->log_flags & (flag)) diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java index a468e09f3b5..3da08300638 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java @@ -30,6 +30,8 @@ import java.awt.Container; import java.awt.Event; import java.awt.KeyEventPostProcessor; import java.awt.Window; +import java.awt.Toolkit; +import sun.awt.SunToolkit; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; @@ -125,7 +127,19 @@ public class WindowsRootPaneUI extends BasicRootPaneUI { } JMenu menu = mbar != null ? mbar.getMenu(0) : null; - if (menu != null) { + // It might happen that the altRelease event is processed + // with a reasonable delay since it has been generated. + // Here we check the last deactivation time of the containing + // window. If this time appears to be greater than the altRelease + // event time the event is skipped to avoid unexpected menu + // activation. See 7121442. + boolean skip = false; + Toolkit tk = Toolkit.getDefaultToolkit(); + if (tk instanceof SunToolkit) { + skip = ev.getWhen() <= ((SunToolkit)tk).getWindowDeactivationTime(winAncestor); + } + + if (menu != null && !skip) { MenuElement[] path = new MenuElement[2]; path[0] = mbar; path[1] = menu; diff --git a/jdk/src/share/classes/java/awt/Component.java b/jdk/src/share/classes/java/awt/Component.java index 6fc78b15487..e4f25f0da2b 100644 --- a/jdk/src/share/classes/java/awt/Component.java +++ b/jdk/src/share/classes/java/awt/Component.java @@ -4710,7 +4710,10 @@ public abstract class Component implements ImageObserver, MenuContainer, /* * 0. Set timestamp and modifiers of current event. */ - EventQueue.setCurrentEventAndMostRecentTime(e); + if (!(e instanceof KeyEvent)) { + // Timestamp of a key event is set later in DKFM.preDispatchKeyEvent(KeyEvent). + EventQueue.setCurrentEventAndMostRecentTime(e); + } /* * 1. Pre-dispatchers. Do any necessary retargeting/reordering here @@ -7606,13 +7609,33 @@ public abstract class Component implements ImageObserver, MenuContainer, boolean focusedWindowChangeAllowed, CausedFocusEvent.Cause cause) { + // 1) Check if the event being dispatched is a system-generated mouse event. + AWTEvent currentEvent = EventQueue.getCurrentEvent(); + if (currentEvent instanceof MouseEvent && + SunToolkit.isSystemGenerated(currentEvent)) + { + // 2) Sanity check: if the mouse event component source belongs to the same containing window. + Component source = ((MouseEvent)currentEvent).getComponent(); + if (source == null || source.getContainingWindow() == getContainingWindow()) { + focusLog.finest("requesting focus by mouse event \"in window\""); + + // If both the conditions are fulfilled the focus request should be strictly + // bounded by the toplevel window. It's assumed that the mouse event activates + // the window (if it wasn't active) and this makes it possible for a focus + // request with a strong in-window requirement to change focus in the bounds + // of the toplevel. If, by any means, due to asynchronous nature of the event + // dispatching mechanism, the window happens to be natively inactive by the time + // this focus request is eventually handled, it should not re-activate the + // toplevel. Otherwise the result may not meet user expectations. See 6981400. + focusedWindowChangeAllowed = false; + } + } if (!isRequestFocusAccepted(temporary, focusedWindowChangeAllowed, cause)) { if (focusLog.isLoggable(PlatformLogger.FINEST)) { focusLog.finest("requestFocus is not accepted"); } return false; } - // Update most-recent map KeyboardFocusManager.setMostRecentFocusOwner(this); @@ -7645,7 +7668,15 @@ public abstract class Component implements ImageObserver, MenuContainer, } // Focus this Component - long time = EventQueue.getMostRecentEventTime(); + long time = 0; + if (EventQueue.isDispatchThread()) { + time = Toolkit.getEventQueue().getMostRecentKeyEventTime(); + } else { + // A focus request made from outside EDT should not be associated with any event + // and so its time stamp is simply set to the current time. + time = System.currentTimeMillis(); + } + boolean success = peer.requestFocus (this, temporary, focusedWindowChangeAllowed, time, cause); if (!success) { diff --git a/jdk/src/share/classes/java/awt/Container.java b/jdk/src/share/classes/java/awt/Container.java index 65c7ceaec5f..ce2a19138b1 100644 --- a/jdk/src/share/classes/java/awt/Container.java +++ b/jdk/src/share/classes/java/awt/Container.java @@ -2863,7 +2863,7 @@ public class Container extends Component { // keep the KeyEvents from being dispatched // until the focus has been transfered - long time = Toolkit.getEventQueue().getMostRecentEventTime(); + long time = Toolkit.getEventQueue().getMostRecentKeyEventTime(); Component predictedFocusOwner = (Component.isInstanceOf(this, "javax.swing.JInternalFrame")) ? ((javax.swing.JInternalFrame)(this)).getMostRecentFocusOwner() : null; if (predictedFocusOwner != null) { KeyboardFocusManager.getCurrentKeyboardFocusManager(). diff --git a/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java b/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java index a5132464ceb..d2d6bf3175f 100644 --- a/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java +++ b/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java @@ -41,6 +41,7 @@ import sun.awt.AppContext; import sun.awt.SunToolkit; import sun.awt.AWTAccessor; import sun.awt.CausedFocusEvent; +import sun.awt.TimedWindowEvent; /** * The default KeyboardFocusManager for AWT applications. Focus traversal is @@ -72,8 +73,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { private WeakReference<Window> realOppositeWindowWR = NULL_WINDOW_WR; private WeakReference<Component> realOppositeComponentWR = NULL_COMPONENT_WR; private int inSendMessage; - private LinkedList enqueuedKeyEvents = new LinkedList(), - typeAheadMarkers = new LinkedList(); + private LinkedList<KeyEvent> enqueuedKeyEvents = new LinkedList<KeyEvent>(); + private LinkedList<TypeAheadMarker> typeAheadMarkers = new LinkedList<TypeAheadMarker>(); private boolean consumeNextKeyTyped; static { @@ -269,6 +270,31 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { return se.dispatched; } + /* + * Checks if the focus window event follows key events waiting in the type-ahead + * queue (if any). This may happen when a user types ahead in the window, the client + * listeners hang EDT for a while, and the user switches b/w toplevels. In that + * case the focus window events may be dispatched before the type-ahead events + * get handled. This may lead to wrong focus behavior and in order to avoid it, + * the focus window events are reposted to the end of the event queue. See 6981400. + */ + private boolean repostIfFollowsKeyEvents(WindowEvent e) { + if (!(e instanceof TimedWindowEvent)) { + return false; + } + TimedWindowEvent we = (TimedWindowEvent)e; + long time = we.getWhen(); + synchronized (this) { + for (KeyEvent ke: enqueuedKeyEvents) { + if (time >= ke.getWhen()) { + SunToolkit.postEvent(AppContext.getAppContext(), new SequencedEvent(e)); + return true; + } + } + } + return false; + } + /** * This method is called by the AWT event dispatcher requesting that the * current KeyboardFocusManager dispatch the specified event on its behalf. @@ -287,6 +313,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { if (focusLog.isLoggable(PlatformLogger.FINE) && (e instanceof WindowEvent || e instanceof FocusEvent)) focusLog.fine("" + e); switch (e.getID()) { case WindowEvent.WINDOW_GAINED_FOCUS: { + if (repostIfFollowsKeyEvents((WindowEvent)e)) { + break; + } + WindowEvent we = (WindowEvent)e; Window oldFocusedWindow = getGlobalFocusedWindow(); Window newFocusedWindow = we.getWindow(); @@ -646,6 +676,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { } case WindowEvent.WINDOW_LOST_FOCUS: { + if (repostIfFollowsKeyEvents((WindowEvent)e)) { + break; + } + WindowEvent we = (WindowEvent)e; Window currentFocusedWindow = getGlobalFocusedWindow(); Window losingFocusWindow = we.getWindow(); @@ -825,10 +859,9 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { ke = null; synchronized (this) { if (enqueuedKeyEvents.size() != 0) { - ke = (KeyEvent)enqueuedKeyEvents.getFirst(); + ke = enqueuedKeyEvents.getFirst(); if (typeAheadMarkers.size() != 0) { - TypeAheadMarker marker = (TypeAheadMarker) - typeAheadMarkers.getFirst(); + TypeAheadMarker marker = typeAheadMarkers.getFirst(); // Fixed 5064013: may appears that the events have the same time // if (ke.getWhen() >= marker.after) { // The fix is rolled out. @@ -857,9 +890,9 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { focusLog.finest(">>> Markers dump, time: {0}", System.currentTimeMillis()); synchronized (this) { if (typeAheadMarkers.size() != 0) { - Iterator iter = typeAheadMarkers.iterator(); + Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); while (iter.hasNext()) { - TypeAheadMarker marker = (TypeAheadMarker)iter.next(); + TypeAheadMarker marker = iter.next(); focusLog.finest(" {0}", marker); } } @@ -881,8 +914,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { KeyEvent ke = (KeyEvent)e; synchronized (this) { if (e.isPosted && typeAheadMarkers.size() != 0) { - TypeAheadMarker marker = (TypeAheadMarker) - typeAheadMarkers.getFirst(); + TypeAheadMarker marker = typeAheadMarkers.getFirst(); // Fixed 5064013: may appears that the events have the same time // if (ke.getWhen() >= marker.after) { // The fix is rolled out. @@ -915,12 +947,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { synchronized (this) { boolean found = false; if (hasMarker(target)) { - for (Iterator iter = typeAheadMarkers.iterator(); + for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { - if (((TypeAheadMarker)iter.next()).untilFocused == - target) - { + if (iter.next().untilFocused == target) { found = true; } else if (found) { break; @@ -955,8 +985,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { * @since 1.5 */ private boolean hasMarker(Component comp) { - for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { - if (((TypeAheadMarker)iter.next()).untilFocused == comp) { + for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { + if (iter.next().untilFocused == comp) { return true; } } @@ -982,11 +1012,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { return true; } - // Explicitly set the current event and most recent timestamp here in - // addition to the call in Component.dispatchEventImpl. Because - // KeyEvents can be delivered in response to a FOCUS_GAINED event, the - // current timestamp may be incorrect. We need to set it here so that - // KeyEventDispatchers will use the correct time. + // Explicitly set the key event timestamp here (not in Component.dispatchEventImpl): + // - A key event is anyway passed to this method which starts its actual dispatching. + // - If a key event is put to the type ahead queue, its time stamp should not be registered + // until its dispatching actually starts (by this method). EventQueue.setCurrentEventAndMostRecentTime(ke); /** @@ -1174,10 +1203,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { int insertionIndex = 0, i = typeAheadMarkers.size(); - ListIterator iter = typeAheadMarkers.listIterator(i); + ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator(i); for (; i > 0; i--) { - TypeAheadMarker marker = (TypeAheadMarker)iter.previous(); + TypeAheadMarker marker = iter.previous(); if (marker.after <= after) { insertionIndex = i; break; @@ -1213,12 +1242,12 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { after, untilFocused); TypeAheadMarker marker; - ListIterator iter = typeAheadMarkers.listIterator + ListIterator<TypeAheadMarker> iter = typeAheadMarkers.listIterator ((after >= 0) ? typeAheadMarkers.size() : 0); if (after < 0) { while (iter.hasNext()) { - marker = (TypeAheadMarker)iter.next(); + marker = iter.next(); if (marker.untilFocused == untilFocused) { iter.remove(); @@ -1227,7 +1256,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { } } else { while (iter.hasPrevious()) { - marker = (TypeAheadMarker)iter.previous(); + marker = iter.previous(); if (marker.untilFocused == untilFocused && marker.after == after) { @@ -1255,8 +1284,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { long start = -1; - for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { - TypeAheadMarker marker = (TypeAheadMarker)iter.next(); + for (Iterator<TypeAheadMarker> iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { + TypeAheadMarker marker = iter.next(); Component toTest = marker.untilFocused; boolean match = (toTest == comp); while (!match && toTest != null && !(toTest instanceof Window)) { @@ -1287,8 +1316,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { return; } - for (Iterator iter = enqueuedKeyEvents.iterator(); iter.hasNext(); ) { - KeyEvent ke = (KeyEvent)iter.next(); + for (Iterator<KeyEvent> iter = enqueuedKeyEvents.iterator(); iter.hasNext(); ) { + KeyEvent ke = iter.next(); long time = ke.getWhen(); if (start < time && (end < 0 || time <= end)) { diff --git a/jdk/src/share/classes/java/awt/Dialog.java b/jdk/src/share/classes/java/awt/Dialog.java index 47f2f221c0d..800d19c0200 100644 --- a/jdk/src/share/classes/java/awt/Dialog.java +++ b/jdk/src/share/classes/java/awt/Dialog.java @@ -924,7 +924,7 @@ public class Dialog extends Window { isEnabled() && !isModalBlocked()) { // keep the KeyEvents from being dispatched // until the focus has been transfered - time.set(Toolkit.getEventQueue().getMostRecentEventTimeEx()); + time.set(Toolkit.getEventQueue().getMostRecentKeyEventTime()); KeyboardFocusManager.getCurrentKeyboardFocusManager(). enqueueKeyEvents(time.get(), toFocus); } diff --git a/jdk/src/share/classes/java/awt/EventQueue.java b/jdk/src/share/classes/java/awt/EventQueue.java index 747cbc8600b..5c38e466f84 100644 --- a/jdk/src/share/classes/java/awt/EventQueue.java +++ b/jdk/src/share/classes/java/awt/EventQueue.java @@ -162,6 +162,11 @@ public class EventQueue { */ private long mostRecentEventTime = System.currentTimeMillis(); + /* + * The time stamp of the last KeyEvent . + */ + private long mostRecentKeyEventTime = System.currentTimeMillis(); + /** * The modifiers field of the current event, if the current event is an * InputEvent or ActionEvent. @@ -1142,6 +1147,15 @@ public class EventQueue { } } + synchronized long getMostRecentKeyEventTime() { + pushPopLock.lock(); + try { + return mostRecentKeyEventTime; + } finally { + pushPopLock.unlock(); + } + } + static void setCurrentEventAndMostRecentTime(AWTEvent e) { Toolkit.getEventQueue().setCurrentEventAndMostRecentTimeImpl(e); } @@ -1166,6 +1180,9 @@ public class EventQueue { if (e instanceof InputEvent) { InputEvent ie = (InputEvent)e; mostRecentEventTime2 = ie.getWhen(); + if (e instanceof KeyEvent) { + mostRecentKeyEventTime = ie.getWhen(); + } } else if (e instanceof InputMethodEvent) { InputMethodEvent ime = (InputMethodEvent)e; mostRecentEventTime2 = ime.getWhen(); diff --git a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java index 8c0cc884779..36a5b9b7fae 100644 --- a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java +++ b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java @@ -445,7 +445,7 @@ public abstract class KeyboardFocusManager private void initPeer() { Toolkit tk = Toolkit.getDefaultToolkit(); KeyboardFocusManagerPeerProvider peerProvider = (KeyboardFocusManagerPeerProvider)tk; - peer = peerProvider.createKeyboardFocusManagerPeer(this); + peer = peerProvider.getKeyboardFocusManagerPeer(); } /** diff --git a/jdk/src/share/classes/java/awt/SequencedEvent.java b/jdk/src/share/classes/java/awt/SequencedEvent.java index b9fe1cbe5ee..b57cde2683f 100644 --- a/jdk/src/share/classes/java/awt/SequencedEvent.java +++ b/jdk/src/share/classes/java/awt/SequencedEvent.java @@ -26,6 +26,7 @@ package java.awt; import java.util.LinkedList; +import sun.awt.AWTAccessor; import sun.awt.AppContext; import sun.awt.SunToolkit; @@ -54,6 +55,17 @@ class SequencedEvent extends AWTEvent implements ActiveEvent { private AppContext appContext; private boolean disposed; + static { + AWTAccessor.setSequencedEventAccessor(new AWTAccessor.SequencedEventAccessor() { + public AWTEvent getNested(AWTEvent sequencedEvent) { + return ((SequencedEvent)sequencedEvent).nested; + } + public boolean isSequencedEvent(AWTEvent event) { + return event instanceof SequencedEvent; + } + }); + } + /** * Constructs a new SequencedEvent which will dispatch the specified * nested event. diff --git a/jdk/src/share/classes/java/awt/peer/KeyboardFocusManagerPeer.java b/jdk/src/share/classes/java/awt/peer/KeyboardFocusManagerPeer.java index 0d533e53414..97d9b60016d 100644 --- a/jdk/src/share/classes/java/awt/peer/KeyboardFocusManagerPeer.java +++ b/jdk/src/share/classes/java/awt/peer/KeyboardFocusManagerPeer.java @@ -33,6 +33,14 @@ import java.awt.Window; */ public interface KeyboardFocusManagerPeer { + /** + * Sets the window that should become the focused window. + * + * @param win the window that should become the focused window + * + */ + void setCurrentFocusedWindow(Window win); + /** * Returns the currently focused window. * diff --git a/jdk/src/share/classes/java/beans/Introspector.java b/jdk/src/share/classes/java/beans/Introspector.java index 7e4c6dd2a9e..54a5e49915a 100644 --- a/jdk/src/share/classes/java/beans/Introspector.java +++ b/jdk/src/share/classes/java/beans/Introspector.java @@ -1460,7 +1460,7 @@ class GenericBeanInfo extends SimpleBeanInfo { private PropertyDescriptor[] properties; private int defaultProperty; private MethodDescriptor[] methods; - private final Reference<BeanInfo> targetBeanInfoRef; + private Reference<BeanInfo> targetBeanInfoRef; public GenericBeanInfo(BeanDescriptor beanDescriptor, EventSetDescriptor[] events, int defaultEvent, @@ -1472,7 +1472,9 @@ class GenericBeanInfo extends SimpleBeanInfo { this.properties = properties; this.defaultProperty = defaultProperty; this.methods = methods; - this.targetBeanInfoRef = new SoftReference<>(targetBeanInfo); + this.targetBeanInfoRef = (targetBeanInfo != null) + ? new SoftReference<>(targetBeanInfo) + : null; } /** @@ -1539,10 +1541,25 @@ class GenericBeanInfo extends SimpleBeanInfo { } public java.awt.Image getIcon(int iconKind) { - BeanInfo targetBeanInfo = this.targetBeanInfoRef.get(); + BeanInfo targetBeanInfo = getTargetBeanInfo(); if (targetBeanInfo != null) { return targetBeanInfo.getIcon(iconKind); } return super.getIcon(iconKind); } + + private BeanInfo getTargetBeanInfo() { + if (this.targetBeanInfoRef == null) { + return null; + } + BeanInfo targetBeanInfo = this.targetBeanInfoRef.get(); + if (targetBeanInfo == null) { + targetBeanInfo = ThreadGroupContext.getContext().getBeanInfoFinder() + .find(this.beanDescriptor.getBeanClass()); + if (targetBeanInfo != null) { + this.targetBeanInfoRef = new SoftReference<>(targetBeanInfo); + } + } + return targetBeanInfo; + } } diff --git a/jdk/src/share/classes/java/beans/PropertyDescriptor.java b/jdk/src/share/classes/java/beans/PropertyDescriptor.java index 91e17e38aa7..e5b42631fbe 100644 --- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java @@ -109,6 +109,10 @@ public class PropertyDescriptor extends FeatureDescriptor { if (writeMethodName != null && getWriteMethod() == null) { throw new IntrospectionException("Method not found: " + writeMethodName); } + boundInitialization(beanClass); + } + + private void boundInitialization(Class<?> beanClass) { // If this class or one of its base classes allow PropertyChangeListener, // then we assume that any properties we discover are "bound". // See Introspector.getTargetPropertyInfo() method. @@ -159,6 +163,7 @@ public class PropertyDescriptor extends FeatureDescriptor { setReadMethod(read); setWriteMethod(write); this.baseName = base; + boundInitialization(bean); } /** @@ -588,7 +593,7 @@ public class PropertyDescriptor extends FeatureDescriptor { Method yw = y.getWriteMethod(); try { - if (yw != null && yw.getDeclaringClass() == getClass0()) { + if (yw != null) { setWriteMethod(yw); } else { setWriteMethod(xw); diff --git a/jdk/src/share/classes/java/beans/XMLEncoder.java b/jdk/src/share/classes/java/beans/XMLEncoder.java index 21749e0db9c..97e1359268a 100644 --- a/jdk/src/share/classes/java/beans/XMLEncoder.java +++ b/jdk/src/share/classes/java/beans/XMLEncoder.java @@ -631,7 +631,12 @@ public class XMLEncoder extends Encoder implements AutoCloseable { } if (d.name != null) { - outputXML(isArgument ? "object" : "void", " idref=" + quote(d.name), value); + if (isArgument) { + writeln("<object idref=" + quote(d.name) + "/>"); + } + else { + outputXML("void", " idref=" + quote(d.name), value); + } } else if (d.exp != null) { outputStatement(d.exp, outer, isArgument); @@ -710,12 +715,14 @@ public class XMLEncoder extends Encoder implements AutoCloseable { } else { d.refs = 2; - getValueData(target).refs++; - List<Statement> statements = statementList(target); - if (!statements.contains(exp)) { - statements.add(exp); + if (d.name == null) { + getValueData(target).refs++; + List<Statement> statements = statementList(target); + if (!statements.contains(exp)) { + statements.add(exp); + } + outputValue(target, outer, false); } - outputValue(target, outer, false); if (expression) { outputValue(value, outer, isArgument); } diff --git a/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java b/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java index c5818d9cb3a..4071305abc5 100644 --- a/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java +++ b/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java @@ -142,6 +142,11 @@ import com.sun.xml.internal.ws.org.objectweb.asm.Type; */ protected abstract SpeciesData speciesData(); + @Override + final Object internalProperties() { + return "/BMH="+internalValues(); + } + @Override final Object internalValues() { Object[] boundValues = new Object[speciesData().fieldCount()]; diff --git a/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java b/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java index 4e5d591af0a..b1c7f82da9a 100644 --- a/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java +++ b/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java @@ -108,8 +108,8 @@ class DirectMethodHandle extends MethodHandle { } @Override - String debugString() { - return "DMH["+member.toString()+"]="+super.debugString(); + String internalProperties() { + return "/DMH="+member.toString(); } //// Implementation methods. diff --git a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 632ae583a20..48f88adeecc 100644 --- a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -185,12 +185,17 @@ class InvokerBytecodeGenerator { } class CpPatch { - int index; - Object value; - CpPatch(int index, Object value) { + final int index; + final String placeholder; + final Object value; + CpPatch(int index, String placeholder, Object value) { this.index = index; + this.placeholder = placeholder; this.value = value; } + public String toString() { + return "CpPatch/index="+index+",placeholder="+placeholder+",value="+value; + } } Map<Object, CpPatch> cpPatches = new HashMap<>(); @@ -205,7 +210,7 @@ class InvokerBytecodeGenerator { } // insert placeholder in CP and remember the patch int index = cw.newConst((Object) cpPlaceholder); // TODO check if aready in the constant pool - cpPatches.put(cpPlaceholder, new CpPatch(index, arg)); + cpPatches.put(cpPlaceholder, new CpPatch(index, cpPlaceholder, arg)); return cpPlaceholder; } @@ -213,7 +218,9 @@ class InvokerBytecodeGenerator { int size = getConstantPoolSize(classFile); Object[] res = new Object[size]; for (CpPatch p : cpPatches.values()) { - res[p.index] = p.value; + if (p.index >= size) + throw new InternalError("in cpool["+size+"]: "+p+"\n"+Arrays.toString(Arrays.copyOf(classFile, 20))); + res[p.index] = p.value; } return res; } diff --git a/jdk/src/share/classes/java/lang/invoke/Invokers.java b/jdk/src/share/classes/java/lang/invoke/Invokers.java index 904a8c73e72..0e3dcf64bc7 100644 --- a/jdk/src/share/classes/java/lang/invoke/Invokers.java +++ b/jdk/src/share/classes/java/lang/invoke/Invokers.java @@ -74,8 +74,18 @@ class Invokers { MethodHandle invoker = exactInvoker; if (invoker != null) return invoker; MethodType mtype = targetType; - LambdaForm lform = invokeForm(mtype, MethodTypeForm.LF_EX_INVOKER); - invoker = BoundMethodHandle.bindSingle(mtype.invokerType(), lform, mtype); + MethodType invokerType = mtype.invokerType(); + LambdaForm lform; + final int MTYPE_ARG_APPENDED = 1; // argument count for appended mtype value + if (mtype.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY - MTYPE_ARG_APPENDED) { + lform = invokeForm(mtype, false, MethodTypeForm.LF_EX_INVOKER); + invoker = BoundMethodHandle.bindSingle(invokerType, lform, mtype); + } else { + // At maximum arity, we cannot afford an extra mtype argument, + // so build a fully customized (non-cached) invoker form. + lform = invokeForm(mtype, true, MethodTypeForm.LF_EX_INVOKER); + invoker = SimpleMethodHandle.make(invokerType, lform); + } assert(checkInvoker(invoker)); exactInvoker = invoker; return invoker; @@ -85,9 +95,20 @@ class Invokers { MethodHandle invoker = generalInvoker; if (invoker != null) return invoker; MethodType mtype = targetType; - prepareForGenericCall(mtype); - LambdaForm lform = invokeForm(mtype, MethodTypeForm.LF_GEN_INVOKER); - invoker = BoundMethodHandle.bindSingle(mtype.invokerType(), lform, mtype); + MethodType invokerType = mtype.invokerType(); + LambdaForm lform; + final int MTYPE_ARG_APPENDED = 1; // argument count for appended mtype value + assert(GENERIC_INVOKER_SLOP >= MTYPE_ARG_APPENDED); + if (mtype.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY - GENERIC_INVOKER_SLOP) { + prepareForGenericCall(mtype); + lform = invokeForm(mtype, false, MethodTypeForm.LF_GEN_INVOKER); + invoker = BoundMethodHandle.bindSingle(invokerType, lform, mtype); + } else { + // At maximum arity, we cannot afford an extra mtype argument, + // so build a fully customized (non-cached) invoker form. + lform = invokeForm(mtype, true, MethodTypeForm.LF_GEN_INVOKER); + invoker = SimpleMethodHandle.make(invokerType, lform); + } assert(checkInvoker(invoker)); generalInvoker = invoker; return invoker; @@ -102,6 +123,7 @@ class Invokers { } static MemberName invokeBasicMethod(MethodType type) { + type = type.basicType(); String name = "invokeBasic"; try { //Lookup.findVirtual(MethodHandle.class, name, type); @@ -135,9 +157,31 @@ class Invokers { /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) { MethodHandle vaInvoker = spreadInvokers[leadingArgCount]; if (vaInvoker != null) return vaInvoker; - MethodHandle gInvoker = generalInvoker(); int spreadArgCount = targetType.parameterCount() - leadingArgCount; - vaInvoker = gInvoker.asSpreader(Object[].class, spreadArgCount); + MethodType spreadInvokerType = targetType + .replaceParameterTypes(leadingArgCount, targetType.parameterCount(), Object[].class); + if (targetType.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY) { + // Factor sinvoker.invoke(mh, a) into ginvoker.asSpreader().invoke(mh, a) + // where ginvoker.invoke(mh, a*) => mh.invoke(a*). + MethodHandle genInvoker = generalInvoker(); + vaInvoker = genInvoker.asSpreader(Object[].class, spreadArgCount); + } else { + // Cannot build a general invoker here of type ginvoker.invoke(mh, a*[254]). + // Instead, factor sinvoker.invoke(mh, a) into ainvoker.invoke(filter(mh), a) + // where filter(mh) == mh.asSpreader(Object[], spreadArgCount) + MethodHandle arrayInvoker = MethodHandles.exactInvoker(spreadInvokerType); + MethodHandle makeSpreader; + try { + makeSpreader = IMPL_LOOKUP + .findVirtual(MethodHandle.class, "asSpreader", + MethodType.methodType(MethodHandle.class, Class.class, int.class)); + } catch (ReflectiveOperationException ex) { + throw new InternalError(ex); + } + makeSpreader = MethodHandles.insertArguments(makeSpreader, 1, Object[].class, spreadArgCount); + vaInvoker = MethodHandles.filterArgument(arrayInvoker, 0, makeSpreader); + } + assert(vaInvoker.type().equals(spreadInvokerType.invokerType())); spreadInvokers[leadingArgCount] = vaInvoker; return vaInvoker; } @@ -171,7 +215,7 @@ class Invokers { .findStatic(CallSite.class, "uninitializedCallSite", MethodType.methodType(Empty.class)); } catch (ReflectiveOperationException ex) { - throw new RuntimeException(ex); + throw new InternalError(ex); } } invoker = MethodHandles.explicitCastArguments(invoker, MethodType.methodType(targetType.returnType())); @@ -185,30 +229,39 @@ class Invokers { return "Invokers"+targetType; } - private static MethodType fixMethodType(Class<?> callerClass, Object type) { - if (type instanceof MethodType) - return (MethodType) type; - else - return MethodType.fromMethodDescriptorString((String)type, callerClass.getClassLoader()); - } - - static MemberName exactInvokerMethod(Class<?> callerClass, Object type, Object[] appendixResult) { - MethodType mtype = fixMethodType(callerClass, type); - LambdaForm lform = invokeForm(mtype, MethodTypeForm.LF_EX_LINKER); - appendixResult[0] = mtype; + static MemberName exactInvokerMethod(MethodType mtype, Object[] appendixResult) { + LambdaForm lform; + final int MTYPE_ARG_APPENDED = 1; // argument count for appended mtype value + if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MTYPE_ARG_APPENDED) { + lform = invokeForm(mtype, false, MethodTypeForm.LF_EX_LINKER); + appendixResult[0] = mtype; + } else { + lform = invokeForm(mtype, true, MethodTypeForm.LF_EX_LINKER); + } return lform.vmentry; } - static MemberName genericInvokerMethod(Class<?> callerClass, Object type, Object[] appendixResult) { - MethodType mtype = fixMethodType(callerClass, type); - LambdaForm lform = invokeForm(mtype, MethodTypeForm.LF_GEN_LINKER); - prepareForGenericCall(mtype); - appendixResult[0] = mtype; + static MemberName genericInvokerMethod(MethodType mtype, Object[] appendixResult) { + LambdaForm lform; + final int MTYPE_ARG_APPENDED = 1; // argument count for appended mtype value + if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - (MTYPE_ARG_APPENDED + GENERIC_INVOKER_SLOP)) { + lform = invokeForm(mtype, false, MethodTypeForm.LF_GEN_LINKER); + appendixResult[0] = mtype; + prepareForGenericCall(mtype); + } else { + lform = invokeForm(mtype, true, MethodTypeForm.LF_GEN_LINKER); + } return lform.vmentry; } - private static LambdaForm invokeForm(MethodType mtype, int which) { - mtype = mtype.basicType(); // normalize Z to I, String to Object, etc. + private static LambdaForm invokeForm(MethodType mtype, boolean customized, int which) { + boolean isCached; + if (!customized) { + mtype = mtype.basicType(); // normalize Z to I, String to Object, etc. + isCached = true; + } else { + isCached = false; // maybe cache if mtype == mtype.basicType() + } boolean isLinker, isGeneric; String debugName; switch (which) { @@ -218,27 +271,32 @@ class Invokers { case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true; debugName = "invoker"; break; default: throw new InternalError(); } - LambdaForm lform = mtype.form().cachedLambdaForm(which); - if (lform != null) return lform; + LambdaForm lform; + if (isCached) { + lform = mtype.form().cachedLambdaForm(which); + if (lform != null) return lform; + } // exactInvokerForm (Object,Object)Object // link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial final int THIS_MH = 0; final int CALL_MH = THIS_MH + (isLinker ? 0 : 1); final int ARG_BASE = CALL_MH + 1; final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount(); - final int INARG_LIMIT = OUTARG_LIMIT + (isLinker ? 1 : 0); + final int INARG_LIMIT = OUTARG_LIMIT + (isLinker && !customized ? 1 : 0); int nameCursor = OUTARG_LIMIT; - final int MTYPE_ARG = nameCursor++; // might be last in-argument + final int MTYPE_ARG = customized ? -1 : nameCursor++; // might be last in-argument final int CHECK_TYPE = nameCursor++; final int LINKER_CALL = nameCursor++; MethodType invokerFormType = mtype.invokerType(); if (isLinker) { - invokerFormType = invokerFormType.appendParameterTypes(MemberName.class); + if (!customized) + invokerFormType = invokerFormType.appendParameterTypes(MemberName.class); } else { invokerFormType = invokerFormType.invokerType(); } Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType); - assert(names.length == nameCursor); + assert(names.length == nameCursor) + : Arrays.asList(mtype, customized, which, nameCursor, names.length); if (MTYPE_ARG >= INARG_LIMIT) { assert(names[MTYPE_ARG] == null); names[MTYPE_ARG] = BoundMethodHandle.getSpeciesData("L").getterName(names[THIS_MH], 0); @@ -248,31 +306,42 @@ class Invokers { // Make the final call. If isGeneric, then prepend the result of type checking. MethodType outCallType; Object[] outArgs; + Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]); if (!isGeneric) { - names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], names[MTYPE_ARG]); + names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], mtypeArg); // mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*) outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class); outCallType = mtype; + } else if (customized) { + names[CHECK_TYPE] = new Name(NF_asType, names[CALL_MH], mtypeArg); + // mh.invokeGeneric(a*):R => + // let mt=TYPEOF(a*:R), tmh=asType(mh, mt); + // tmh.invokeBasic(a*) + outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class); + outCallType = mtype; } else { - names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], names[MTYPE_ARG]); + names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], mtypeArg); // mh.invokeGeneric(a*):R => // let mt=TYPEOF(a*:R), gamh=checkGenericType(mh, mt); // gamh.invokeBasic(mt, mh, a*) final int PREPEND_GAMH = 0, PREPEND_MT = 1, PREPEND_COUNT = 2; + assert(GENERIC_INVOKER_SLOP == PREPEND_COUNT); outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT + PREPEND_COUNT, Object[].class); // prepend arguments: System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT); outArgs[PREPEND_GAMH] = names[CHECK_TYPE]; - outArgs[PREPEND_MT] = names[MTYPE_ARG]; + outArgs[PREPEND_MT] = mtypeArg; outCallType = mtype.insertParameterTypes(0, MethodType.class, MethodHandle.class); } names[LINKER_CALL] = new Name(invokeBasicMethod(outCallType), outArgs); lform = new LambdaForm(debugName, INARG_LIMIT, names); if (isLinker) lform.compileToBytecode(); // JVM needs a real methodOop - lform = mtype.form().setCachedLambdaForm(which, lform); + if (isCached) + lform = mtype.form().setCachedLambdaForm(which, lform); return lform; } + private static final int GENERIC_INVOKER_SLOP = 2; // used elsewhere to avoid arity problems /*non-public*/ static WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) { @@ -370,6 +439,7 @@ class Invokers { // Local constant functions: private static final NamedFunction NF_checkExactType; private static final NamedFunction NF_checkGenericType; + private static final NamedFunction NF_asType; private static final NamedFunction NF_getCallSiteTarget; static { try { @@ -377,6 +447,8 @@ class Invokers { .getDeclaredMethod("checkExactType", Object.class, Object.class)); NF_checkGenericType = new NamedFunction(Invokers.class .getDeclaredMethod("checkGenericType", Object.class, Object.class)); + NF_asType = new NamedFunction(MethodHandle.class + .getDeclaredMethod("asType", MethodType.class)); NF_getCallSiteTarget = new NamedFunction(Invokers.class .getDeclaredMethod("getCallSiteTarget", Object.class)); NF_checkExactType.resolve(); diff --git a/jdk/src/share/classes/java/lang/invoke/LambdaForm.java b/jdk/src/share/classes/java/lang/invoke/LambdaForm.java index 2b9a0383858..e39896afecb 100644 --- a/jdk/src/share/classes/java/lang/invoke/LambdaForm.java +++ b/jdk/src/share/classes/java/lang/invoke/LambdaForm.java @@ -596,14 +596,7 @@ class LambdaForm { Object interpretWithArguments(Object... argumentValues) throws Throwable { if (TRACE_INTERPRETER) return interpretWithArgumentsTracing(argumentValues); - if (COMPILE_THRESHOLD != 0 && - invocationCounter < COMPILE_THRESHOLD) { - invocationCounter++; // benign race - if (invocationCounter >= COMPILE_THRESHOLD) { - // Replace vmentry with a bytecode version of this LF. - compileToBytecode(); - } - } + checkInvocationCounter(); assert(arityCheck(argumentValues)); Object[] values = Arrays.copyOf(argumentValues, names.length); for (int i = argumentValues.length; i < values.length; i++) { @@ -630,6 +623,16 @@ class LambdaForm { return name.function.invokeWithArguments(arguments); } + private void checkInvocationCounter() { + if (COMPILE_THRESHOLD != 0 && + invocationCounter < COMPILE_THRESHOLD) { + invocationCounter++; // benign race + if (invocationCounter >= COMPILE_THRESHOLD) { + // Replace vmentry with a bytecode version of this LF. + compileToBytecode(); + } + } + } Object interpretWithArgumentsTracing(Object... argumentValues) throws Throwable { traceInterpreter("[ interpretWithArguments", this, argumentValues); if (invocationCounter < COMPILE_THRESHOLD) { @@ -703,7 +706,7 @@ class LambdaForm { } public String toString() { - StringBuilder buf = new StringBuilder("Lambda("); + StringBuilder buf = new StringBuilder(debugName+"=Lambda("); for (int i = 0; i < names.length; i++) { if (i == arity) buf.append(")=>{"); Name n = names[i]; diff --git a/jdk/src/share/classes/java/lang/invoke/MemberName.java b/jdk/src/share/classes/java/lang/invoke/MemberName.java index e38b6594e60..595b1145fe1 100644 --- a/jdk/src/share/classes/java/lang/invoke/MemberName.java +++ b/jdk/src/share/classes/java/lang/invoke/MemberName.java @@ -306,12 +306,6 @@ import java.util.Objects; return this; } - private void setFlags(int flags) { - this.flags = flags; - assert(testAnyFlags(ALL_KINDS)); - assert(referenceKindIsConsistent()); - } - private boolean testFlags(int mask, int value) { return (flags & mask) == value; } @@ -452,8 +446,10 @@ import java.util.Objects; this.clazz = defClass; this.name = name; this.type = type; - setFlags(flags); + this.flags = flags; + assert(testAnyFlags(ALL_KINDS)); assert(this.resolution == null); // nobody should have touched this yet + //assert(referenceKindIsConsistent()); // do this after resolution } private void expandFromVM() { diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandle.java b/jdk/src/share/classes/java/lang/invoke/MethodHandle.java index 76429a84a91..a5e4e584d18 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandle.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandle.java @@ -924,7 +924,7 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123)); if (arrayType != type().parameterType(collectArgPos)) target = convertArguments(type().changeParameterType(collectArgPos, arrayType)); MethodHandle collector = ValueConversions.varargsArray(arrayType, arrayLength); - return MethodHandleImpl.makeCollectArguments(target, collector, collectArgPos, false); + return MethodHandles.collectArguments(target, collectArgPos, collector); } // private API: return true if last param exactly matches arrayType @@ -1226,7 +1226,7 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); return "MethodHandle"+type; } String debugString() { - return standardString()+"="+internalForm()+internalValues(); + return standardString()+"/LF="+internalForm()+internalProperties(); } //// Implementation methods. @@ -1269,6 +1269,12 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); /*non-public*/ Object internalValues() { + return null; + } + + /*non-public*/ + Object internalProperties() { + // Override to something like "/FOO=bar" return ""; } diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java index 39dfdf232b2..d9822bd7189 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -59,7 +59,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; Name[] args = Arrays.copyOfRange(names, 1, 1 + srcType.parameterCount()); names[names.length - 1] = new Name(accessor.asType(srcType), (Object[]) args); LambdaForm form = new LambdaForm("getElement", lambdaType.parameterCount(), names); - MethodHandle mh = new SimpleMethodHandle(srcType, form); + MethodHandle mh = SimpleMethodHandle.make(srcType, form); if (ArrayAccessor.needCast(arrayClass)) { mh = mh.bindTo(arrayClass); } @@ -171,38 +171,46 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; // Calculate extra arguments (temporaries) required in the names array. // FIXME: Use an ArrayList<Name>. Some arguments require more than one conversion step. - int extra = 0; - for (int i = 0; i < srcType.parameterCount(); i++) { - Class<?> src = srcType.parameterType(i); - Class<?> dst = dstType.parameterType(i); - if (!VerifyType.isNullConversion(src, dst)) { - extra++; + final int INARG_COUNT = srcType.parameterCount(); + int conversions = 0; + boolean[] needConv = new boolean[1+INARG_COUNT]; + for (int i = 0; i <= INARG_COUNT; i++) { + Class<?> src = (i == INARG_COUNT) ? dstType.returnType() : srcType.parameterType(i); + Class<?> dst = (i == INARG_COUNT) ? srcType.returnType() : dstType.parameterType(i); + if (!VerifyType.isNullConversion(src, dst) || + level <= 1 && dst.isInterface() && !dst.isAssignableFrom(src)) { + needConv[i] = true; + conversions++; } } + boolean retConv = needConv[INARG_COUNT]; - Class<?> needReturn = srcType.returnType(); - Class<?> haveReturn = dstType.returnType(); - boolean retConv = !VerifyType.isNullConversion(haveReturn, needReturn); + final int IN_MH = 0; + final int INARG_BASE = 1; + final int INARG_LIMIT = INARG_BASE + INARG_COUNT; + final int NAME_LIMIT = INARG_LIMIT + conversions + 1; + final int RETURN_CONV = (!retConv ? -1 : NAME_LIMIT - 1); + final int OUT_CALL = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1; // Now build a LambdaForm. - MethodType lambdaType = srcType.invokerType(); - Name[] names = arguments(extra + 1, lambdaType); - int[] indexes = new int[lambdaType.parameterCount()]; + MethodType lambdaType = srcType.basicType().invokerType(); + Name[] names = arguments(NAME_LIMIT - INARG_LIMIT, lambdaType); - MethodType midType = dstType; - for (int i = 0, argIndex = 1, tmpIndex = lambdaType.parameterCount(); i < srcType.parameterCount(); i++, argIndex++) { + // Collect the arguments to the outgoing call, maybe with conversions: + final int OUTARG_BASE = 0; // target MH is Name.function, name Name.arguments[0] + Object[] outArgs = new Object[OUTARG_BASE + INARG_COUNT]; + + int nameCursor = INARG_LIMIT; + for (int i = 0; i < INARG_COUNT; i++) { Class<?> src = srcType.parameterType(i); - Class<?> dst = midType.parameterType(i); + Class<?> dst = dstType.parameterType(i); - if (VerifyType.isNullConversion(src, dst)) { + if (!needConv[i]) { // do nothing: difference is trivial - indexes[i] = argIndex; + outArgs[OUTARG_BASE + i] = names[INARG_BASE + i]; continue; } - // Work the current type backward toward the desired caller type: - midType = midType.changeParameterType(i, src); - // Tricky case analysis follows. MethodHandle fn = null; if (src.isPrimitive()) { @@ -246,33 +254,41 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; fn = ValueConversions.cast(dst); } } - names[tmpIndex] = new Name(fn, names[argIndex]); - indexes[i] = tmpIndex; - tmpIndex++; - } - if (retConv) { - MethodHandle adjustReturn; - if (haveReturn == void.class) { - // synthesize a zero value for the given void - Object zero = Wrapper.forBasicType(needReturn).zero(); - adjustReturn = MethodHandles.constant(needReturn, zero); - } else { - MethodHandle identity = MethodHandles.identity(needReturn); - MethodType needConversion = identity.type().changeParameterType(0, haveReturn); - adjustReturn = makePairwiseConvert(identity, needConversion, level); - } - target = makeCollectArguments(adjustReturn, target, 0, false); + Name conv = new Name(fn, names[INARG_BASE + i]); + assert(names[nameCursor] == null); + names[nameCursor++] = conv; + assert(outArgs[OUTARG_BASE + i] == null); + outArgs[OUTARG_BASE + i] = conv; } // Build argument array for the call. - Name[] targetArgs = new Name[dstType.parameterCount()]; - for (int i = 0; i < dstType.parameterCount(); i++) { - int idx = indexes[i]; - targetArgs[i] = names[idx]; + assert(nameCursor == OUT_CALL); + names[OUT_CALL] = new Name(target, outArgs); + + if (RETURN_CONV < 0) { + assert(OUT_CALL == names.length-1); + } else { + Class<?> needReturn = srcType.returnType(); + Class<?> haveReturn = dstType.returnType(); + MethodHandle fn; + Object[] arg = { names[OUT_CALL] }; + if (haveReturn == void.class) { + // synthesize a zero value for the given void + Object zero = Wrapper.forBasicType(needReturn).zero(); + fn = MethodHandles.constant(needReturn, zero); + arg = new Object[0]; // don't pass names[OUT_CALL] to conversion + } else { + MethodHandle identity = MethodHandles.identity(needReturn); + MethodType needConversion = identity.type().changeParameterType(0, haveReturn); + fn = makePairwiseConvert(identity, needConversion, level); + } + assert(names[RETURN_CONV] == null); + names[RETURN_CONV] = new Name(fn, arg); + assert(RETURN_CONV == names.length-1); } - names[names.length - 1] = new Name(target, (Object[]) targetArgs); + LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names); - return new SimpleMethodHandle(srcType, form); + return SimpleMethodHandle.make(srcType, form); } static MethodHandle makeReferenceIdentity(Class<?> refType) { @@ -280,7 +296,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; Name[] names = arguments(1, lambdaType); names[names.length - 1] = new Name(ValueConversions.identity(), names[1]); LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names); - return new SimpleMethodHandle(MethodType.methodType(refType, refType), form); + return SimpleMethodHandle.make(MethodType.methodType(refType, refType), form); } static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) { @@ -334,8 +350,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; MethodHandle collector; try { collector = asFixedArity().asCollector(arrayType, arrayLength); + assert(collector.type().parameterCount() == newArity) : "newArity="+newArity+" but collector="+collector; } catch (IllegalArgumentException ex) { - throw new WrongMethodTypeException("cannot build collector"); + throw new WrongMethodTypeException("cannot build collector", ex); } cache = collector; return collector.asType(newType); @@ -429,12 +446,18 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; names[names.length - 1] = new Name(target, (Object[]) targetArgs); LambdaForm form = new LambdaForm("spread", lambdaType.parameterCount(), names); - return new SimpleMethodHandle(srcType, form); + return SimpleMethodHandle.make(srcType, form); } static void checkSpreadArgument(Object av, int n) { + // FIXME: regression test for bug 7141637 erroneously expects an NPE, and other tests may expect IAE + // but the actual exception raised by an arity mismatch should be WMTE + final boolean RAISE_RANDOM_EXCEPTIONS = true; // FIXME: delete in JSR 292 M1 if (av == null) { if (n == 0) return; + int len; + if (RAISE_RANDOM_EXCEPTIONS) + len = ((Object[])av).length; // throw NPE; but delete this after tests are fixed } else if (av instanceof Object[]) { int len = ((Object[])av).length; if (len == n) return; @@ -443,7 +466,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; if (len == n) return; } // fall through to error: - throw newIllegalArgumentException("Array is not of length "+n); + if (RAISE_RANDOM_EXCEPTIONS) + throw newIllegalArgumentException("Array is not of length "+n); + throw new WrongMethodTypeException("Array is not of length "+n); } private static final NamedFunction NF_checkSpreadArgument; @@ -508,7 +533,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; names[targetNamePos] = new Name(target, (Object[]) targetArgs); LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names); - return new SimpleMethodHandle(srcType, form); + return SimpleMethodHandle.make(srcType, form); } static @@ -555,7 +580,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; names[arity + 3] = new Name(new NamedFunction(invokeBasic), targetArgs); LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names); - return new SimpleMethodHandle(target.type(), form); + return SimpleMethodHandle.make(target.type(), form); } private static class GuardWithCatch { diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java index a01f8a076c9..d27256fb337 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -325,15 +325,28 @@ class MethodHandleNatives { static MemberName linkMethodImpl(Class<?> callerClass, int refKind, Class<?> defc, String name, Object type, Object[] appendixResult) { - if (defc != MethodHandle.class || refKind != REF_invokeVirtual) - throw new LinkageError("no such method "+defc.getName()+"."+name+type); - switch (name) { - case "invoke": - return Invokers.genericInvokerMethod(callerClass, type, appendixResult); - case "invokeExact": - return Invokers.exactInvokerMethod(callerClass, type, appendixResult); + try { + if (defc == MethodHandle.class && refKind == REF_invokeVirtual) { + switch (name) { + case "invoke": + return Invokers.genericInvokerMethod(fixMethodType(callerClass, type), appendixResult); + case "invokeExact": + return Invokers.exactInvokerMethod(fixMethodType(callerClass, type), appendixResult); + } + } + } catch (Throwable ex) { + if (ex instanceof LinkageError) + throw (LinkageError) ex; + else + throw new LinkageError(ex.getMessage(), ex); } - throw new UnsupportedOperationException("linkMethod "+name); + throw new LinkageError("no such method "+defc.getName()+"."+name+type); + } + private static MethodType fixMethodType(Class<?> callerClass, Object type) { + if (type instanceof MethodType) + return (MethodType) type; + else + return MethodType.fromMethodDescriptorString((String)type, callerClass.getClassLoader()); } // Tracing logic: static MemberName linkMethodTracing(Class<?> callerClass, int refKind, @@ -351,6 +364,7 @@ class MethodHandleNatives { } } + /** * The JVM is resolving a CONSTANT_MethodHandle CP entry. And it wants our help. * It will make an up-call to this method. (Do not change the name or signature.) diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java index e338e9645de..5c55f202353 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java @@ -1876,6 +1876,17 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY return MethodHandleImpl.makeCollectArguments(target, filter, pos, false); } + // FIXME: Make this public in M1. + /*non-public*/ static + MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle collector) { + MethodType targetType = target.type(); + MethodType filterType = collector.type(); + if (filterType.returnType() != void.class && + filterType.returnType() != targetType.parameterType(pos)) + throw newIllegalArgumentException("target and filter types do not match", targetType, filterType); + return MethodHandleImpl.makeCollectArguments(target, collector, pos, false); + } + /** * Adapts a target method handle by post-processing * its return value (if any) with a filter (another method handle). diff --git a/jdk/src/share/classes/java/lang/invoke/MethodType.java b/jdk/src/share/classes/java/lang/invoke/MethodType.java index 38610d81403..c690dad3d8a 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodType.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodType.java @@ -111,6 +111,36 @@ class MethodType implements java.io.Serializable { void setForm(MethodTypeForm f) { form = f; } + /** This number, mandated by the JVM spec as 255, + * is the maximum number of <em>slots</em> + * that any Java method can receive in its argument list. + * It limits both JVM signatures and method type objects. + * The longest possible invocation will look like + * {@code staticMethod(arg1, arg2, ..., arg255)} or + * {@code x.virtualMethod(arg1, arg2, ..., arg254)}. + */ + /*non-public*/ static final int MAX_JVM_ARITY = 255; // this is mandated by the JVM spec. + + /** This number is the maximum arity of a method handle, 254. + * It is derived from the absolute JVM-imposed arity by subtracting one, + * which is the slot occupied by the method handle itself at the + * beginning of the argument list used to invoke the method handle. + * The longest possible invocation will look like + * {@code mh.invoke(arg1, arg2, ..., arg254)}. + */ + // Issue: Should we allow MH.invokeWithArguments to go to the full 255? + /*non-public*/ static final int MAX_MH_ARITY = MAX_JVM_ARITY-1; // deduct one for mh receiver + + /** This number is the maximum arity of a method handle invoker, 253. + * It is derived from the absolute JVM-imposed arity by subtracting two, + * which are the slots occupied by invoke method handle, and the the + * target method handle, which are both at the beginning of the argument + * list used to invoke the target method handle. + * The longest possible invocation will look like + * {@code invokermh.invoke(targetmh, arg1, arg2, ..., arg253)}. + */ + /*non-public*/ static final int MAX_MH_INVOKER_ARITY = MAX_MH_ARITY-1; // deduct one more for invoker + private static void checkRtype(Class<?> rtype) { rtype.equals(rtype); // null check } @@ -131,7 +161,9 @@ class MethodType implements java.io.Serializable { return slots; } static void checkSlotCount(int count) { - if ((count & 0xFF) != count) + assert((MAX_JVM_ARITY & (MAX_JVM_ARITY+1)) == 0); + // MAX_JVM_ARITY must be power of 2 minus 1 for following code trick to work: + if ((count & MAX_JVM_ARITY) != count) throw newIllegalArgumentException("bad parameter count "+count); } private static IndexOutOfBoundsException newIndexOutOfBoundsException(Object num) { diff --git a/jdk/src/share/classes/java/lang/invoke/SimpleMethodHandle.java b/jdk/src/share/classes/java/lang/invoke/SimpleMethodHandle.java index 0ea6d38b1b9..1cd6daf5ae6 100644 --- a/jdk/src/share/classes/java/lang/invoke/SimpleMethodHandle.java +++ b/jdk/src/share/classes/java/lang/invoke/SimpleMethodHandle.java @@ -35,10 +35,14 @@ import java.util.logging.Logger; * @author jrose */ final class SimpleMethodHandle extends MethodHandle { - SimpleMethodHandle(MethodType type, LambdaForm form) { + private SimpleMethodHandle(MethodType type, LambdaForm form) { super(type, form); } + /*non-public*/ static SimpleMethodHandle make(MethodType type, LambdaForm form) { + return new SimpleMethodHandle(type, form); + } + @Override MethodHandle bindArgument(int pos, char basicType, Object value) { MethodType type2 = type().dropParameterTypes(pos, pos+1); diff --git a/jdk/src/share/classes/java/lang/invoke/WrongMethodTypeException.java b/jdk/src/share/classes/java/lang/invoke/WrongMethodTypeException.java index 7d538dc8096..dba07d9fecd 100644 --- a/jdk/src/share/classes/java/lang/invoke/WrongMethodTypeException.java +++ b/jdk/src/share/classes/java/lang/invoke/WrongMethodTypeException.java @@ -59,4 +59,27 @@ public class WrongMethodTypeException extends RuntimeException { public WrongMethodTypeException(String s) { super(s); } + + /** + * Constructs a {@code WrongMethodTypeException} with the specified + * detail message and cause. + * + * @param s the detail message. + * @param cause the cause of the exception, or null. + */ + //FIXME: make this public in MR1 + /*non-public*/ WrongMethodTypeException(String s, Throwable cause) { + super(s, cause); + } + + /** + * Constructs a {@code WrongMethodTypeException} with the specified + * cause. + * + * @param cause the cause of the exception, or null. + */ + //FIXME: make this public in MR1 + /*non-public*/ WrongMethodTypeException(Throwable cause) { + super(cause); + } } diff --git a/jdk/src/share/classes/sun/awt/AWTAccessor.java b/jdk/src/share/classes/sun/awt/AWTAccessor.java index 0679f108f54..21f426da2f5 100644 --- a/jdk/src/share/classes/sun/awt/AWTAccessor.java +++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java @@ -666,6 +666,21 @@ public final class AWTAccessor { public void consumeNextKeyTyped(DefaultKeyboardFocusManager dkfm, KeyEvent e); } + /* + * An accessor for the SequencedEventAccessor class + */ + public interface SequencedEventAccessor { + /* + * Returns the nested event. + */ + AWTEvent getNested(AWTEvent sequencedEvent); + + /* + * Returns true if the event is an instances of SequencedEvent. + */ + boolean isSequencedEvent(AWTEvent event); + } + /* * Accessor instances are initialized in the static initializers of * corresponding AWT classes by using setters defined below. @@ -692,6 +707,7 @@ public final class AWTAccessor { private static SystemTrayAccessor systemTrayAccessor; private static TrayIconAccessor trayIconAccessor; private static DefaultKeyboardFocusManagerAccessor defaultKeyboardFocusManagerAccessor; + private static SequencedEventAccessor sequencedEventAccessor; /* * Set an accessor object for the java.awt.Component class. @@ -1069,4 +1085,20 @@ public final class AWTAccessor { } return defaultKeyboardFocusManagerAccessor; } + /* + * Set an accessor object for the java.awt.SequencedEvent class. + */ + public static void setSequencedEventAccessor(SequencedEventAccessor sea) { + sequencedEventAccessor = sea; + } + + /* + * Get the accessor object for the java.awt.SequencedEvent class. + */ + public static SequencedEventAccessor getSequencedEventAccessor() { + // The class is not public. So we can't ensure it's initialized. + // Null returned value means it's not initialized + // (so not a single instance of the event has been created). + return sequencedEventAccessor; + } } diff --git a/jdk/src/share/classes/sun/awt/HToolkit.java b/jdk/src/share/classes/sun/awt/HToolkit.java index edadb84f397..57217678bfc 100644 --- a/jdk/src/share/classes/sun/awt/HToolkit.java +++ b/jdk/src/share/classes/sun/awt/HToolkit.java @@ -44,6 +44,14 @@ import java.util.Properties; public class HToolkit extends SunToolkit implements ComponentFactory { + private static final KeyboardFocusManagerPeer kfmPeer = new KeyboardFocusManagerPeer() { + public void setCurrentFocusedWindow(Window win) {} + public Window getCurrentFocusedWindow() { return null; } + public void setCurrentFocusOwner(Component comp) {} + public Component getCurrentFocusOwner() { return null; } + public void clearGlobalFocusOwner(Window activeWindow) {} + }; + public HToolkit() { } @@ -152,15 +160,9 @@ public class HToolkit extends SunToolkit throw new HeadlessException(); } - public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) { + public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() { // See 6833019. - return - new KeyboardFocusManagerPeer() { - public Window getCurrentFocusedWindow() { return null; } - public void setCurrentFocusOwner(Component comp) {} - public Component getCurrentFocusOwner() { return null; } - public void clearGlobalFocusOwner(Window activeWindow) {} - }; + return kfmPeer; } public TrayIconPeer createTrayIcon(TrayIcon target) diff --git a/jdk/src/share/classes/sun/awt/HeadlessToolkit.java b/jdk/src/share/classes/sun/awt/HeadlessToolkit.java index 11926233ede..ab7197547d4 100644 --- a/jdk/src/share/classes/sun/awt/HeadlessToolkit.java +++ b/jdk/src/share/classes/sun/awt/HeadlessToolkit.java @@ -30,22 +30,25 @@ import java.awt.dnd.*; import java.awt.dnd.peer.DragSourceContextPeer; import java.awt.event.*; import java.awt.im.InputMethodHighlight; -import java.awt.im.spi.InputMethodDescriptor; import java.awt.image.*; import java.awt.datatransfer.Clipboard; import java.awt.peer.*; import java.beans.PropertyChangeListener; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.util.Map; import java.util.Properties; -import sun.awt.im.InputContext; -import sun.awt.image.ImageRepresentation; public class HeadlessToolkit extends Toolkit implements ComponentFactory, KeyboardFocusManagerPeerProvider { + private static final KeyboardFocusManagerPeer kfmPeer = new KeyboardFocusManagerPeer() { + public void setCurrentFocusedWindow(Window win) {} + public Window getCurrentFocusedWindow() { return null; } + public void setCurrentFocusOwner(Component comp) {} + public Component getCurrentFocusOwner() { return null; } + public void clearGlobalFocusOwner(Window activeWindow) {} + }; + private Toolkit tk; private ComponentFactory componentFactory; @@ -179,15 +182,9 @@ public class HeadlessToolkit extends Toolkit throw new HeadlessException(); } - public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) { + public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() { // See 6833019. - return - new KeyboardFocusManagerPeer() { - public Window getCurrentFocusedWindow() { return null; } - public void setCurrentFocusOwner(Component comp) {} - public Component getCurrentFocusOwner() { return null; } - public void clearGlobalFocusOwner(Window activeWindow) {} - }; + return kfmPeer; } public TrayIconPeer createTrayIcon(TrayIcon target) diff --git a/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java b/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java index 775a7677582..2e2350b1c4d 100644 --- a/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java +++ b/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java @@ -53,12 +53,6 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag public static final int SNFH_SUCCESS_HANDLED = 1; public static final int SNFH_SUCCESS_PROCEED = 2; - protected KeyboardFocusManager manager; - - public KeyboardFocusManagerPeerImpl(KeyboardFocusManager manager) { - this.manager = manager; - } - @Override public void clearGlobalFocusOwner(Window activeWindow) { if (activeWindow != null) { @@ -134,7 +128,7 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag if (focusLog.isLoggable(PlatformLogger.FINER)) focusLog.finer("Posting focus event: " + fl); - SunToolkit.postPriorityEvent(fl); + SunToolkit.postEvent(SunToolkit.targetToAppContext(currentOwner), fl); } FocusEvent fg = new CausedFocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED, @@ -142,7 +136,7 @@ public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManag if (focusLog.isLoggable(PlatformLogger.FINER)) focusLog.finer("Posting focus event: " + fg); - SunToolkit.postPriorityEvent(fg); + SunToolkit.postEvent(SunToolkit.targetToAppContext(lightweightChild), fg); return true; } diff --git a/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerProvider.java b/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerProvider.java index 3548eaf22f7..9d4ac6d48bd 100644 --- a/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerProvider.java +++ b/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerProvider.java @@ -25,20 +25,19 @@ package sun.awt; -import java.awt.KeyboardFocusManager; import java.awt.peer.KeyboardFocusManagerPeer; /** * {@link KeyboardFocusManagerPeerProvider} is required to be implemented by * the currently used {@link java.awt.Toolkit} instance. In order to initialize - * {@link java.awt.KeyboardFocusManager}, an instance of {@link KeyboardFocusManagerPeer} - * is needed. To create that instance, the {@link #createKeyboardFocusManagerPeer} + * {@link java.awt.KeyboardFocusManager}, a singleton instance of {@link KeyboardFocusManagerPeer} + * is needed. To obtain that instance, the {@link #getKeyboardFocusManagerPeer} * method of the current toolkit is called. */ public interface KeyboardFocusManagerPeerProvider { /** - * Creates a KeyboardFocusManagerPeer for the specified KeyboardFocusManager. + * Gets a singleton KeyboardFocusManagerPeer instance. */ - KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager); + KeyboardFocusManagerPeer getKeyboardFocusManagerPeer(); } diff --git a/jdk/src/share/classes/sun/awt/SunToolkit.java b/jdk/src/share/classes/sun/awt/SunToolkit.java index 701f01b0ca8..37c3700ef82 100644 --- a/jdk/src/share/classes/sun/awt/SunToolkit.java +++ b/jdk/src/share/classes/sun/awt/SunToolkit.java @@ -197,7 +197,7 @@ public abstract class SunToolkit extends Toolkit public abstract RobotPeer createRobot(Robot target, GraphicsDevice screen) throws AWTException; - public abstract KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) + public abstract KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() throws HeadlessException; /** @@ -463,6 +463,19 @@ public abstract class SunToolkit extends Toolkit if (event == null) { throw new NullPointerException(); } + + AWTAccessor.SequencedEventAccessor sea = AWTAccessor.getSequencedEventAccessor(); + if (sea != null && sea.isSequencedEvent(event)) { + AWTEvent nested = sea.getNested(event); + if (nested.getID() == WindowEvent.WINDOW_LOST_FOCUS && + nested instanceof TimedWindowEvent) + { + TimedWindowEvent twe = (TimedWindowEvent)nested; + ((SunToolkit)Toolkit.getDefaultToolkit()). + setWindowDeactivationTime((Window)twe.getSource(), twe.getWhen()); + } + } + // All events posted via this method are system-generated. // Placing the following call here reduces considerably the // number of places throughout the toolkit that would @@ -1863,6 +1876,28 @@ public abstract class SunToolkit extends Toolkit return false; } + private static final Object DEACTIVATION_TIMES_MAP_KEY = new Object(); + + public synchronized void setWindowDeactivationTime(Window w, long time) { + AppContext ctx = getAppContext(w); + WeakHashMap<Window, Long> map = (WeakHashMap<Window, Long>)ctx.get(DEACTIVATION_TIMES_MAP_KEY); + if (map == null) { + map = new WeakHashMap<Window, Long>(); + ctx.put(DEACTIVATION_TIMES_MAP_KEY, map); + } + map.put(w, time); + } + + public synchronized long getWindowDeactivationTime(Window w) { + AppContext ctx = getAppContext(w); + WeakHashMap<Window, Long> map = (WeakHashMap<Window, Long>)ctx.get(DEACTIVATION_TIMES_MAP_KEY); + if (map == null) { + return -1; + } + Long time = map.get(w); + return time == null ? -1 : time; + } + // Cosntant alpha public boolean isWindowOpacitySupported() { return false; diff --git a/jdk/src/share/classes/sun/awt/TimedWindowEvent.java b/jdk/src/share/classes/sun/awt/TimedWindowEvent.java new file mode 100644 index 00000000000..21353f789d7 --- /dev/null +++ b/jdk/src/share/classes/sun/awt/TimedWindowEvent.java @@ -0,0 +1,51 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.awt; + +import java.awt.event.WindowEvent; +import java.awt.Window; + +public class TimedWindowEvent extends WindowEvent { + + private long time; + + public long getWhen() { + return time; + } + + public TimedWindowEvent(Window source, int id, Window opposite, long time) { + super(source, id, opposite); + this.time = time; + } + + public TimedWindowEvent(Window source, int id, Window opposite, + int oldState, int newState, long time) + { + super(source, id, opposite, oldState, newState); + this.time = time; + } +} + diff --git a/jdk/src/share/classes/sun/invoke/util/ValueConversions.java b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java index a5e200f23b4..1533f4b2ad2 100644 --- a/jdk/src/share/classes/sun/invoke/util/ValueConversions.java +++ b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java @@ -44,6 +44,7 @@ public class ValueConversions { static { final Object[] values = { 255 }; AccessController.doPrivileged(new PrivilegedAction<Void>() { + @Override public Void run() { values[0] = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255); return null; @@ -182,7 +183,7 @@ public class ValueConversions { */ public static Number primitiveConversion(Wrapper wrap, Object x, boolean cast) { // Maybe merge this code with Wrapper.convert/cast. - Number res = null; + Number res; if (x == null) { if (!cast) return null; return ZERO_INT; @@ -322,11 +323,9 @@ public class ValueConversions { static void ignore(Object x) { // no value to return; this is an unbox of null - return; } static void empty() { - return; } static Object zeroObject() { @@ -389,24 +388,6 @@ public class ValueConversions { /// Converting references to references. - /** - * Value-killing function. - * @param x an arbitrary reference value - * @return a null - */ - static Object alwaysNull(Object x) { - return null; - } - - /** - * Value-killing function. - * @param x an arbitrary reference value - * @return a zero - */ - static int alwaysZero(Object x) { - return 0; - } - /** * Identity function. * @param x an arbitrary reference value @@ -416,6 +397,10 @@ public class ValueConversions { return x; } + static <T> T[] identity(T[] x) { + return x; + } + /** * Identity function on ints. * @param x an arbitrary int value @@ -468,29 +453,33 @@ public class ValueConversions { return t.cast(x); } - private static final MethodHandle IDENTITY, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY, NEW_ARRAY; + private static final MethodHandle IDENTITY, CAST_REFERENCE, ZERO_OBJECT, IGNORE, EMPTY, + ARRAY_IDENTITY, FILL_NEW_TYPED_ARRAY, FILL_NEW_ARRAY; static { try { MethodType idType = MethodType.genericMethodType(1); MethodType castType = idType.insertParameterTypes(0, Class.class); - MethodType alwaysZeroType = idType.changeReturnType(int.class); MethodType ignoreType = idType.changeReturnType(void.class); MethodType zeroObjectType = MethodType.genericMethodType(0); IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType); //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType); CAST_REFERENCE = IMPL_LOOKUP.findStatic(THIS_CLASS, "castReference", castType); - ALWAYS_NULL = IMPL_LOOKUP.findStatic(THIS_CLASS, "alwaysNull", idType); - ALWAYS_ZERO = IMPL_LOOKUP.findStatic(THIS_CLASS, "alwaysZero", alwaysZeroType); ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType); IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType); EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1)); - NEW_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "newArray", MethodType.methodType(Object[].class, int.class)); + ARRAY_IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", MethodType.methodType(Object[].class, Object[].class)); + FILL_NEW_ARRAY = IMPL_LOOKUP + .findStatic(THIS_CLASS, "fillNewArray", + MethodType.methodType(Object[].class, Integer.class, Object[].class)); + FILL_NEW_TYPED_ARRAY = IMPL_LOOKUP + .findStatic(THIS_CLASS, "fillNewTypedArray", + MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class)); } catch (NoSuchMethodException | IllegalAccessException ex) { throw new InternalError("uncaught exception", ex); } } - // Varargs methods need to be in a separately initialized class, to bootstrapping problems. + // Varargs methods need to be in a separately initialized class, to avoid bootstrapping problems. static class LazyStatics { private static final MethodHandle COPY_AS_REFERENCE_ARRAY, COPY_AS_PRIMITIVE_ARRAY, MAKE_LIST; static { @@ -505,34 +494,64 @@ public class ValueConversions { } } + static MethodHandle collectArguments(MethodHandle mh, int pos, MethodHandle collector) { + // FIXME: API needs public MHs.collectArguments. + // Should be: + // return MethodHandles.collectArguments(mh, 0, collector); + // The rest of this code is a workaround for not having that API. + if (COLLECT_ARGUMENTS != null) { + try { + return (MethodHandle) + COLLECT_ARGUMENTS.invokeExact(mh, pos, collector); + } catch (Throwable ex) { + if (ex instanceof RuntimeException) + throw (RuntimeException) ex; + if (ex instanceof Error) + throw (Error) ex; + throw new Error(ex.getMessage(), ex); + } + } + // Emulate MHs.collectArguments using fold + drop. + // This is slightly inefficient. + // More seriously, it can put a MH over the 255-argument limit. + mh = MethodHandles.dropArguments(mh, 1, collector.type().parameterList()); + mh = MethodHandles.foldArguments(mh, collector); + return mh; + } + private static final MethodHandle COLLECT_ARGUMENTS; + static { + MethodHandle mh = null; + try { + java.lang.reflect.Method m = MethodHandles.class + .getDeclaredMethod("collectArguments", + MethodHandle.class, int.class, MethodHandle.class); + m.setAccessible(true); + mh = IMPL_LOOKUP.unreflect(m); + + } catch (ReflectiveOperationException | SecurityException ex) { + throw new InternalError(ex); + } + COLLECT_ARGUMENTS = mh; + } + private static final EnumMap<Wrapper, MethodHandle>[] WRAPPER_CASTS - = newWrapperCaches(2); + = newWrapperCaches(1); /** Return a method that casts its sole argument (an Object) to the given type - * and returns it as the given type (if exact is true), or as plain Object (if erase is true). + * and returns it as the given type. */ public static MethodHandle cast(Class<?> type) { - boolean exact = false; if (type.isPrimitive()) throw new IllegalArgumentException("cannot cast primitive type "+type); - MethodHandle mh = null; + MethodHandle mh; Wrapper wrap = null; EnumMap<Wrapper, MethodHandle> cache = null; if (Wrapper.isWrapperType(type)) { wrap = Wrapper.forWrapperType(type); - cache = WRAPPER_CASTS[exact?1:0]; + cache = WRAPPER_CASTS[0]; mh = cache.get(wrap); if (mh != null) return mh; } - if (VerifyType.isNullReferenceConversion(Object.class, type)) - mh = IDENTITY; - else if (VerifyType.isNullType(type)) - mh = ALWAYS_NULL; - else - mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type); - if (exact) { - MethodType xmt = MethodType.methodType(type, Object.class); - mh = MethodHandles.explicitCastArguments(mh, xmt); - } + mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type); if (cache != null) cache.put(wrap, mh); return mh; @@ -920,37 +939,47 @@ public class ValueConversions { } private static final MethodHandle[] ARRAYS = makeArrays(); - // mh-fill versions of the above: - private static Object[] newArray(int len) { return new Object[len]; } + // filling versions of the above: + // using Integer len instead of int len and no varargs to avoid bootstrapping problems + private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) { + Object[] a = new Object[len]; + fillWithArguments(a, 0, args); + return a; + } + private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) { + Object[] a = Arrays.copyOf(example, len); + fillWithArguments(a, 0, args); + return a; + } private static void fillWithArguments(Object[] a, int pos, Object... args) { System.arraycopy(args, 0, a, pos, args.length); } // using Integer pos instead of int pos to avoid bootstrapping problems - private static Object[] fillArray(Object[] a, Integer pos, Object a0) + private static Object[] fillArray(Integer pos, Object[] a, Object a0) { fillWithArguments(a, pos, a0); return a; } - private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1) + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1) { fillWithArguments(a, pos, a0, a1); return a; } - private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2) + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2) { fillWithArguments(a, pos, a0, a1, a2); return a; } - private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3) + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3) { fillWithArguments(a, pos, a0, a1, a2, a3); return a; } - private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, Object a4) { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; } - private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; } - private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; } - private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; } - private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; } - private static Object[] fillArray(Object[] a, Integer pos, Object a0, Object a1, Object a2, Object a3, + private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; } @@ -958,7 +987,7 @@ public class ValueConversions { ArrayList<MethodHandle> mhs = new ArrayList<>(); mhs.add(null); // there is no empty fill; at least a0 is required for (;;) { - MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Object[].class, Integer.class); + MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class); if (mh == null) break; mhs.add(mh); } @@ -984,69 +1013,95 @@ public class ValueConversions { if (mh != null) return mh; mh = findCollector("array", nargs, Object[].class); if (mh != null) return ARRAYS[nargs] = mh; - MethodHandle producer = filler(0); // identity function produces result - return ARRAYS[nargs] = buildVarargsArray(producer, nargs); + mh = buildVarargsArray(FILL_NEW_ARRAY, ARRAY_IDENTITY, nargs); + assert(assertCorrectArity(mh, nargs)); + return ARRAYS[nargs] = mh; } - private static MethodHandle buildVarargsArray(MethodHandle producer, int nargs) { + private static boolean assertCorrectArity(MethodHandle mh, int arity) { + assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh; + return true; + } + + private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) { // Build up the result mh as a sequence of fills like this: - // producer(fill(fill(fill(newArray(23),0,x1..x10),10,x11..x20),20,x21..x23)) + // finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23)) // The various fill(_,10*I,___*[J]) are reusable. - MethodHandle filler = filler(nargs); - MethodHandle mh = producer; - mh = MethodHandles.dropArguments(mh, 1, filler.type().parameterList()); - mh = MethodHandles.foldArguments(mh, filler); - mh = MethodHandles.foldArguments(mh, buildNewArray(nargs)); + int leftLen = Math.min(nargs, LEFT_ARGS); // absorb some arguments immediately + int rightLen = nargs - leftLen; + MethodHandle leftCollector = newArray.bindTo(nargs); + leftCollector = leftCollector.asCollector(Object[].class, leftLen); + MethodHandle mh = finisher; + if (rightLen > 0) { + MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen); + if (mh == ARRAY_IDENTITY) + mh = rightFiller; + else + mh = collectArguments(mh, 0, rightFiller); + } + if (mh == ARRAY_IDENTITY) + mh = leftCollector; + else + mh = collectArguments(mh, 0, leftCollector); return mh; } - private static MethodHandle buildNewArray(int nargs) { - return MethodHandles.insertArguments(NEW_ARRAY, 0, nargs); - } - - private static final MethodHandle[] FILLERS = new MethodHandle[MAX_ARITY+1]; - // filler(N).invoke(a, arg0..arg[N-1]) fills a[0]..a[N-1] - private static MethodHandle filler(int nargs) { - MethodHandle filler = FILLERS[nargs]; + private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1); + private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1]; + /** fill_array_to_right(N).invoke(a, argL..arg[N-1]) + * fills a[L]..a[N-1] with corresponding arguments, + * and then returns a. The value L is a global constant (LEFT_ARGS). + */ + private static MethodHandle fillToRight(int nargs) { + MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs]; if (filler != null) return filler; - return FILLERS[nargs] = buildFiller(nargs); + filler = buildFiller(nargs); + assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1)); + return FILL_ARRAY_TO_RIGHT[nargs] = filler; } private static MethodHandle buildFiller(int nargs) { - if (nargs == 0) - return MethodHandles.identity(Object[].class); - final int CHUNK = (FILL_ARRAYS.length - 1); + if (nargs <= LEFT_ARGS) + return ARRAY_IDENTITY; // no args to fill; return the array unchanged + // we need room for both mh and a in mh.invoke(a, arg*[nargs]) + final int CHUNK = LEFT_ARGS; int rightLen = nargs % CHUNK; - int leftLen = nargs - rightLen; + int midLen = nargs - rightLen; if (rightLen == 0) { - leftLen = nargs - (rightLen = CHUNK); - if (FILLERS[leftLen] == null) { + midLen = nargs - (rightLen = CHUNK); + if (FILL_ARRAY_TO_RIGHT[midLen] == null) { // build some precursors from left to right - for (int j = 0; j < leftLen; j += CHUNK) filler(j); + for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK) + if (j > LEFT_ARGS) fillToRight(j); } } - MethodHandle leftFill = filler(leftLen); // recursive fill - MethodHandle rightFill = FILL_ARRAYS[rightLen]; - rightFill = MethodHandles.insertArguments(rightFill, 1, leftLen); // [leftLen..nargs-1] + if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS); + assert(rightLen > 0); + MethodHandle midFill = fillToRight(midLen); // recursive fill + MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen); // [midLen..nargs-1] + assert(midFill.type().parameterCount() == 1 + midLen - LEFT_ARGS); + assert(rightFill.type().parameterCount() == 1 + rightLen); - // Combine the two fills: right(left(newArray(nargs), x1..x20), x21..x23) - MethodHandle mh = filler(0); // identity function produces result - mh = MethodHandles.dropArguments(mh, 1, rightFill.type().parameterList()); - mh = MethodHandles.foldArguments(mh, rightFill); - if (leftLen > 0) { - mh = MethodHandles.dropArguments(mh, 1, leftFill.type().parameterList()); - mh = MethodHandles.foldArguments(mh, leftFill); - } - return mh; + // Combine the two fills: + // right(mid(a, x10..x19), x20..x23) + // The final product will look like this: + // right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23) + if (midLen == LEFT_ARGS) + return rightFill; + else + return collectArguments(rightFill, 0, midFill); } // Type-polymorphic version of varargs maker. private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS = new ClassValue<MethodHandle[]>() { + @Override protected MethodHandle[] computeValue(Class<?> type) { return new MethodHandle[256]; } }; + static final int MAX_JVM_ARITY = 255; // limit imposed by the JVM + /** Return a method handle that takes the indicated number of * typed arguments and returns an array of them. * The type argument is the array type. @@ -1055,16 +1110,36 @@ public class ValueConversions { Class<?> elemType = arrayType.getComponentType(); if (elemType == null) throw new IllegalArgumentException("not an array: "+arrayType); // FIXME: Need more special casing and caching here. + if (nargs >= MAX_JVM_ARITY/2 - 1) { + int slots = nargs; + final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1; // 1 for receiver MH + if (arrayType == double[].class || arrayType == long[].class) + slots *= 2; + if (slots > MAX_ARRAY_SLOTS) + throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs); + } if (elemType == Object.class) return varargsArray(nargs); // other cases: primitive arrays, subtypes of Object[] MethodHandle cache[] = TYPED_COLLECTORS.get(elemType); MethodHandle mh = nargs < cache.length ? cache[nargs] : null; if (mh != null) return mh; - MethodHandle producer = buildArrayProducer(arrayType); - mh = buildVarargsArray(producer, nargs); + if (elemType.isPrimitive()) { + MethodHandle builder = FILL_NEW_ARRAY; + MethodHandle producer = buildArrayProducer(arrayType); + mh = buildVarargsArray(builder, producer, nargs); + } else { + @SuppressWarnings("unchecked") + Class<? extends Object[]> objArrayType = (Class<? extends Object[]>) arrayType; + Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType); + MethodHandle builder = FILL_NEW_TYPED_ARRAY.bindTo(example); + MethodHandle producer = ARRAY_IDENTITY; + mh = buildVarargsArray(builder, producer, nargs); + } mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType))); - cache[nargs] = mh; + assert(assertCorrectArity(mh, nargs)); + if (nargs < cache.length) + cache[nargs] = mh; return mh; } diff --git a/jdk/src/share/demo/applets/CardTest/example1.html b/jdk/src/share/demo/applets/CardTest/example1.html index 930731c6fa9..c293b0f8491 100644 --- a/jdk/src/share/demo/applets/CardTest/example1.html +++ b/jdk/src/share/demo/applets/CardTest/example1.html @@ -5,7 +5,7 @@ <body> <h1>Card Test (1.1)</h1> <hr> - <applet code=CardTest.class width=400 height=300> + <applet code=CardTest.class width=455 height=300> alt="Your browser understands the <APPLET> tag but isn't running the applet, for some reason." Your browser is completely ignoring the <APPLET> tag! </applet> diff --git a/jdk/src/share/demo/applets/DitherTest/example1.html b/jdk/src/share/demo/applets/DitherTest/example1.html index 7cd4fff936d..9a4f041d2d2 100644 --- a/jdk/src/share/demo/applets/DitherTest/example1.html +++ b/jdk/src/share/demo/applets/DitherTest/example1.html @@ -5,7 +5,7 @@ <body> <h1>Dither Test (1.1)</h1> <hr> - <applet code=DitherTest.class width=425 height=400> + <applet code=DitherTest.class width=455 height=400> alt="Your browser understands the <APPLET> tag but isn't running the applet, for some reason." Your browser is completely ignoring the <APPLET> tag! </applet> diff --git a/jdk/src/share/demo/jvmti/hprof/debug_malloc.h b/jdk/src/share/demo/jvmti/hprof/debug_malloc.h index 6b6b4c6b733..d74ff608b2a 100644 --- a/jdk/src/share/demo/jvmti/hprof/debug_malloc.h +++ b/jdk/src/share/demo/jvmti/hprof/debug_malloc.h @@ -59,6 +59,11 @@ #include <stdlib.h> #include <string.h> +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + /* The real functions behind the macro curtains. */ void *debug_malloc(size_t, const char *, int); @@ -71,10 +76,10 @@ void debug_free(void *, const char *, int); void debug_malloc_verify(const char*, int); #undef malloc_verify -#define malloc_verify() debug_malloc_verify(__FILE__, __LINE__) +#define malloc_verify() debug_malloc_verify(THIS_FILE, __LINE__) void debug_malloc_police(const char*, int); #undef malloc_police -#define malloc_police() debug_malloc_police(__FILE__, __LINE__) +#define malloc_police() debug_malloc_police(THIS_FILE, __LINE__) #endif diff --git a/jdk/src/share/demo/jvmti/hprof/hprof_error.h b/jdk/src/share/demo/jvmti/hprof/hprof_error.h index c0d6aed0fea..b82d4ee6b90 100644 --- a/jdk/src/share/demo/jvmti/hprof/hprof_error.h +++ b/jdk/src/share/demo/jvmti/hprof/hprof_error.h @@ -41,20 +41,25 @@ #ifndef HPROF_ERROR_H #define HPROF_ERROR_H +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + /* Macros over assert and error functions so we can capture the source loc. */ #define HPROF_BOOL(x) ((jboolean)((x)==0?JNI_FALSE:JNI_TRUE)) #define HPROF_ERROR(fatal,msg) \ - error_handler(HPROF_BOOL(fatal), JVMTI_ERROR_NONE, msg, __FILE__, __LINE__) + error_handler(HPROF_BOOL(fatal), JVMTI_ERROR_NONE, msg, THIS_FILE, __LINE__) #define HPROF_JVMTI_ERROR(error,msg) \ error_handler(HPROF_BOOL(error!=JVMTI_ERROR_NONE), \ - error, msg, __FILE__, __LINE__) + error, msg, THIS_FILE, __LINE__) #if defined(DEBUG) || !defined(NDEBUG) #define HPROF_ASSERT(cond) \ - (((int)(cond))?(void)0:error_assert(#cond, __FILE__, __LINE__)) + (((int)(cond))?(void)0:error_assert(#cond, THIS_FILE, __LINE__)) #else #define HPROF_ASSERT(cond) #endif @@ -77,11 +82,11 @@ #define LOG_FORMAT(format) "HPROF LOG: " format " [%s:%d]\n" #define LOG1(str1) LOG_STDERR((stderr, LOG_FORMAT("%s"), \ - str1, __FILE__, __LINE__ )) + str1, THIS_FILE, __LINE__ )) #define LOG2(str1,str2) LOG_STDERR((stderr, LOG_FORMAT("%s %s"), \ - str1, str2, __FILE__, __LINE__ )) + str1, str2, THIS_FILE, __LINE__ )) #define LOG3(str1,str2,num) LOG_STDERR((stderr, LOG_FORMAT("%s %s 0x%x"), \ - str1, str2, num, __FILE__, __LINE__ )) + str1, str2, num, THIS_FILE, __LINE__ )) #define LOG(str) LOG1(str) diff --git a/jdk/src/share/demo/jvmti/hprof/hprof_util.h b/jdk/src/share/demo/jvmti/hprof/hprof_util.h index c052394f2b6..588570ce64b 100644 --- a/jdk/src/share/demo/jvmti/hprof/hprof_util.h +++ b/jdk/src/share/demo/jvmti/hprof/hprof_util.h @@ -41,6 +41,11 @@ #ifndef HPROF_UTIL_H #define HPROF_UTIL_H +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + /* Macros that protect code from accidently using a local ref improperly */ #define WITH_LOCAL_REFS(env, number) \ { \ @@ -184,8 +189,8 @@ void hprof_free(void *ptr); #ifdef DEBUG void * hprof_debug_malloc(int size, char *file, int line); void hprof_debug_free(void *ptr, char *file, int line); - #define HPROF_MALLOC(size) hprof_debug_malloc(size, __FILE__, __LINE__) - #define HPROF_FREE(ptr) hprof_debug_free(ptr, __FILE__, __LINE__) + #define HPROF_MALLOC(size) hprof_debug_malloc(size, THIS_FILE, __LINE__) + #define HPROF_FREE(ptr) hprof_debug_free(ptr, THIS_FILE, __LINE__) #else #define HPROF_MALLOC(size) hprof_malloc(size) #define HPROF_FREE(ptr) hprof_free(ptr) diff --git a/jdk/src/share/demo/jvmti/java_crw_demo/java_crw_demo.c b/jdk/src/share/demo/jvmti/java_crw_demo/java_crw_demo.c index 1da0e55d322..772548de165 100644 --- a/jdk/src/share/demo/jvmti/java_crw_demo/java_crw_demo.c +++ b/jdk/src/share/demo/jvmti/java_crw_demo/java_crw_demo.c @@ -70,12 +70,20 @@ /* Macros over error functions to capture line numbers */ -#define CRW_FATAL(ci, message) fatal_error(ci, message, __FILE__, __LINE__) +/* Fatal error used in all builds. */ + +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE "java_crw.demo.c" /* Never use __FILE__ */ +#endif + +#define CRW_FATAL(ci, message) fatal_error(ci, message, THIS_FILE, __LINE__) #if defined(DEBUG) || !defined(NDEBUG) + /* This assert macro is only used in the debug builds. */ #define CRW_ASSERT(ci, cond) \ - ((cond)?(void)0:assert_error(ci, #cond, __FILE__, __LINE__)) + ((cond)?(void)0:assert_error(ci, #cond, THIS_FILE, __LINE__)) #else diff --git a/jdk/src/share/instrument/JPLISAssert.h b/jdk/src/share/instrument/JPLISAssert.h index c2ef7eef124..a0446447e59 100644 --- a/jdk/src/share/instrument/JPLISAssert.h +++ b/jdk/src/share/instrument/JPLISAssert.h @@ -49,10 +49,14 @@ extern "C" { #define JPLISASSERT_ENABLEASSERTIONS (0) #endif +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif #if JPLISASSERT_ENABLEASSERTIONS -#define jplis_assert(x) JPLISAssertCondition((jboolean)(x), #x, __FILE__, __LINE__) -#define jplis_assert_msg(x, msg) JPLISAssertConditionWithMessage((jboolean)(x), #x, msg, __FILE__, __LINE__) +#define jplis_assert(x) JPLISAssertCondition((jboolean)(x), #x, THIS_FILE, __LINE__) +#define jplis_assert_msg(x, msg) JPLISAssertConditionWithMessage((jboolean)(x), #x, msg, THIS_FILE, __LINE__) #else #define jplis_assert(x) #define jplis_assert_msg(x, msg) diff --git a/jdk/src/share/native/sun/awt/debug/debug_assert.h b/jdk/src/share/native/sun/awt/debug/debug_assert.h index 22d804733e0..920f232ee50 100644 --- a/jdk/src/share/native/sun/awt/debug/debug_assert.h +++ b/jdk/src/share/native/sun/awt/debug/debug_assert.h @@ -32,17 +32,22 @@ extern "C" { #include "debug_util.h" +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + #if defined(DEBUG) #define DASSERT(_expr) \ if ( !(_expr) ) { \ - DAssert_Impl( #_expr, __FILE__, __LINE__); \ + DAssert_Impl( #_expr, THIS_FILE, __LINE__); \ } else { \ } #define DASSERTMSG(_expr, _msg) \ if ( !(_expr) ) { \ - DAssert_Impl( (_msg), __FILE__, __LINE__); \ + DAssert_Impl( (_msg), THIS_FILE, __LINE__); \ } else { \ } diff --git a/jdk/src/share/native/sun/awt/debug/debug_mem.c b/jdk/src/share/native/sun/awt/debug/debug_mem.c index 5a4690be8f1..bf91768e6d3 100644 --- a/jdk/src/share/native/sun/awt/debug/debug_mem.c +++ b/jdk/src/share/native/sun/awt/debug/debug_mem.c @@ -27,6 +27,11 @@ #include "debug_util.h" +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + #define DMEM_MIN(a,b) (a) < (b) ? (a) : (b) #define DMEM_MAX(a,b) (a) > (b) ? (a) : (b) @@ -291,7 +296,7 @@ void DMem_ReportLeaks() { DMutex_Enter(DMemMutex); /* Force memory leaks to be output regardless of trace settings */ - DTrace_EnableFile(__FILE__, TRUE); + DTrace_EnableFile(THIS_FILE, TRUE); DTRACE_PRINTLN("--------------------------"); DTRACE_PRINTLN("Debug Memory Manager Leaks"); DTRACE_PRINTLN("--------------------------"); diff --git a/jdk/src/share/native/sun/awt/debug/debug_trace.h b/jdk/src/share/native/sun/awt/debug/debug_trace.h index e91c556ac07..aad4677d111 100644 --- a/jdk/src/share/native/sun/awt/debug/debug_trace.h +++ b/jdk/src/share/native/sun/awt/debug/debug_trace.h @@ -34,6 +34,11 @@ extern "C" { #include "debug_util.h" +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + typedef int dtrace_id; enum { UNDEFINED_TRACE_ID = -1 /* indicates trace point has not been registered yet */ @@ -69,7 +74,7 @@ static dtrace_id _Dt_FileTraceId = UNDEFINED_TRACE_ID; #define _DTrace_Template(_func, _ac, _f, _a1, _a2, _a3, _a4, _a5, _a6, _a7, _a8) \ { \ static dtrace_id _dt_lineid_ = UNDEFINED_TRACE_ID; \ - DTrace_PrintFunction((_func), &_Dt_FileTraceId, &_dt_lineid_, __FILE__, __LINE__, (_ac), (_f), (_a1), (_a2), (_a3), (_a4), (_a5), (_a6), (_a7), (_a8) ); \ + DTrace_PrintFunction((_func), &_Dt_FileTraceId, &_dt_lineid_, THIS_FILE, __LINE__, (_ac), (_f), (_a1), (_a2), (_a3), (_a4), (_a5), (_a6), (_a7), (_a8) ); \ } /* printf style trace macros */ diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h b/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h index 81e79b9acd3..01aeb6fcaea 100644 --- a/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h +++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h @@ -452,7 +452,12 @@ extern CK_C_INITIALIZE_ARGS_PTR ckpGlobalInitArgs; void *p11malloc(size_t c, char *file, int line); void p11free(void *p, char *file, int line); -#define malloc(c) (p11malloc((c), __FILE__, __LINE__)) -#define free(c) (p11free((c), __FILE__, __LINE__)) +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + +#define malloc(c) (p11malloc((c), THIS_FILE, __LINE__)) +#define free(c) (p11free((c), THIS_FILE, __LINE__)) #endif diff --git a/jdk/src/share/npt/utf.h b/jdk/src/share/npt/utf.h index 8fbda735fa1..4345b606df1 100644 --- a/jdk/src/share/npt/utf.h +++ b/jdk/src/share/npt/utf.h @@ -33,8 +33,13 @@ #include "jni.h" #include "utf_md.h" +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + /* Error and assert macros */ -#define UTF_ERROR(m) utfError(__FILE__, __LINE__, m) +#define UTF_ERROR(m) utfError(THIS_FILE, __LINE__, m) #define UTF_ASSERT(x) ( (x)==0 ? UTF_ERROR("ASSERT ERROR " #x) : (void)0 ) void utfError(char *file, int line, char *message); diff --git a/jdk/src/share/transport/shmem/shmemBase.h b/jdk/src/share/transport/shmem/shmemBase.h index 661d9f076b8..0d5cec1f7b4 100644 --- a/jdk/src/share/transport/shmem/shmemBase.h +++ b/jdk/src/share/transport/shmem/shmemBase.h @@ -49,11 +49,16 @@ jint shmemBase_receivePacket(SharedMemoryConnection *, jdwpPacket *packet); jint shmemBase_name(SharedMemoryTransport *, char **name); jint shmemBase_getlasterror(char *msg, jint size); +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + #ifdef DEBUG #define SHMEM_ASSERT(expression) \ do { \ if (!(expression)) { \ - exitTransportWithError("assertion failed", __FILE__, __DATE__, __LINE__); \ + exitTransportWithError("assertion failed", THIS_FILE, __DATE__, __LINE__); \ } \ } while (0) #else @@ -63,7 +68,7 @@ do { \ #define SHMEM_GUARANTEE(expression) \ do { \ if (!(expression)) { \ - exitTransportWithError("assertion failed", __FILE__, __DATE__, __LINE__); \ + exitTransportWithError("assertion failed", THIS_FILE, __DATE__, __LINE__); \ } \ } while (0) diff --git a/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java b/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java index f053dc50ffe..ba4ed50b961 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java @@ -1001,6 +1001,13 @@ public class XBaseWindow { switch (xev.get_type()) { case XConstants.ButtonPress: if (buttonState == 0) { + XWindowPeer parent = getToplevelXWindow(); + // See 6385277, 6981400. + if (parent != null && parent.isFocusableWindow()) { + // A click in a client area drops the actual focused window retaining. + parent.setActualFocusedWindow(null); + parent.requestWindowFocus(xbe.get_time(), true); + } XAwtState.setAutoGrabWindow(this); } break; diff --git a/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java index 96e47213c46..906e9a862a0 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java @@ -588,33 +588,6 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget } - public void handleButtonPressRelease(XEvent xev) { - /* - * Fix for 6385277. - * We request focus on simple Window by click in order - * to make it behave like Frame/Dialog in this case and also to unify - * the behaviour with what we have on MS Windows. - * handleJavaMouseEvent() would be more suitable place to do this - * but we want Swing to have this functionality also. - */ - if (xev.get_type() == XConstants.ButtonPress) { - final XWindowPeer parentXWindow = getParentTopLevel(); - Window parentWindow = (Window)parentXWindow.getTarget(); - if (parentXWindow.isFocusableWindow() && parentXWindow.isSimpleWindow() && - XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() != parentWindow) - { - postEvent(new InvocationEvent(parentWindow, new Runnable() { - public void run() { - // Request focus on the EDT of 'parentWindow' because - // XDecoratedPeer.requestWindowFocus() calls client code. - parentXWindow.requestXFocus(); - } - })); - } - } - super.handleButtonPressRelease(xev); - } - public Dimension getMinimumSize() { return target.getSize(); } diff --git a/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java index bbebbf5988f..b4617a8d3fa 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java @@ -1108,7 +1108,7 @@ abstract class XDecoratedPeer extends XWindowPeer { focusLog.fine("Request for decorated window focus"); // If this is Frame or Dialog we can't assure focus request success - but we still can try // If this is Window and its owner Frame is active we can be sure request succedded. - Window focusedWindow = XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow(); + Window focusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow(); Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow); focusLog.finer("Current window is: active={0}, focused={1}", @@ -1201,7 +1201,7 @@ abstract class XDecoratedPeer extends XWindowPeer { } public void handleWindowFocusOut(Window oppositeWindow, long serial) { - Window actualFocusedWindow = XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow(); + Window actualFocusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow(); // If the actual focused window is not this decorated window then retain it. if (actualFocusedWindow != null && actualFocusedWindow != target) { diff --git a/jdk/src/solaris/classes/sun/awt/X11/XDialogPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XDialogPeer.java index e76effbeff8..fc0a0b7d44f 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XDialogPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XDialogPeer.java @@ -135,7 +135,7 @@ class XDialogPeer extends XDecoratedPeer implements DialogPeer { * Thus we don't have to perform any transitive (a blocker of a blocker) checks. */ boolean isFocusedWindowModalBlocker() { - Window focusedWindow = XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow(); + Window focusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow(); XWindowPeer focusedWindowPeer = null; if (focusedWindow != null) { diff --git a/jdk/src/solaris/classes/sun/awt/X11/XEmbedChildProxyPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XEmbedChildProxyPeer.java index 4d75d211040..f087b1a9fc4 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XEmbedChildProxyPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbedChildProxyPeer.java @@ -96,11 +96,11 @@ public class XEmbedChildProxyPeer implements ComponentPeer, XEventDispatcher{ public void handleEvent(AWTEvent e) { switch (e.getID()) { case FocusEvent.FOCUS_GAINED: - XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(proxy); + XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(proxy); container.focusGained(handle); break; case FocusEvent.FOCUS_LOST: - XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(null); + XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(null); container.focusLost(handle); break; case KeyEvent.KEY_PRESSED: @@ -172,7 +172,7 @@ public class XEmbedChildProxyPeer implements ComponentPeer, XEventDispatcher{ if (lightweightChild == null) { lightweightChild = (Component)proxy; } - Component currentOwner = XKeyboardFocusManagerPeer.getCurrentNativeFocusOwner(); + Component currentOwner = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusOwner(); if (currentOwner != null && currentOwner.getPeer() == null) { currentOwner = null; } @@ -224,7 +224,8 @@ public class XEmbedChildProxyPeer implements ComponentPeer, XEventDispatcher{ if (parent != null) { Window parentWindow = (Window)parent; // and check that it is focused - if (!parentWindow.isFocused() && XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() == parentWindow) { + if (!parentWindow.isFocused() && + XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() == parentWindow) { // if it is not - skip requesting focus on Solaris // but return true for compatibility. return true; diff --git a/jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java b/jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java index c5384a2d52b..026209e048d 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java @@ -204,7 +204,7 @@ public class XEmbedClientHelper extends XEmbedHelper implements XEventDispatcher // XEMBED_FOCUS_OUT client messages), so we first need to check if // embedded is an active window before sending WINDOW_LOST_FOCUS // to shared code - if (XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() == embedded.target) { + if (XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() == embedded.target) { embedded.handleWindowFocusOut(null, 0); } } diff --git a/jdk/src/solaris/classes/sun/awt/X11/XKeyboardFocusManagerPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XKeyboardFocusManagerPeer.java index 304023bd97d..79041cbbb96 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XKeyboardFocusManagerPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XKeyboardFocusManagerPeer.java @@ -25,66 +25,48 @@ package sun.awt.X11; import java.awt.Component; -import java.awt.KeyboardFocusManager; import java.awt.Window; - -import java.awt.event.FocusEvent; - -import java.awt.peer.KeyboardFocusManagerPeer; -import java.awt.peer.ComponentPeer; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - import sun.util.logging.PlatformLogger; - import sun.awt.CausedFocusEvent; -import sun.awt.SunToolkit; import sun.awt.KeyboardFocusManagerPeerImpl; public class XKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl { private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.X11.focus.XKeyboardFocusManagerPeer"); + private static final XKeyboardFocusManagerPeer inst = new XKeyboardFocusManagerPeer(); - private static Object lock = new Object() {}; - private static Component currentFocusOwner; - private static Window currentFocusedWindow; + private Component currentFocusOwner; + private Window currentFocusedWindow; - XKeyboardFocusManagerPeer(KeyboardFocusManager manager) { - super(manager); + public static XKeyboardFocusManagerPeer getInstance() { + return inst; + } + + private XKeyboardFocusManagerPeer() { } @Override public void setCurrentFocusOwner(Component comp) { - setCurrentNativeFocusOwner(comp); - } - - @Override - public Component getCurrentFocusOwner() { - return getCurrentNativeFocusOwner(); - } - - @Override - public Window getCurrentFocusedWindow() { - return getCurrentNativeFocusedWindow(); - } - - public static void setCurrentNativeFocusOwner(Component comp) { - synchronized (lock) { + synchronized (this) { currentFocusOwner = comp; } } - public static Component getCurrentNativeFocusOwner() { - synchronized(lock) { + @Override + public Component getCurrentFocusOwner() { + synchronized(this) { return currentFocusOwner; } } - public static void setCurrentNativeFocusedWindow(Window win) { - if (focusLog.isLoggable(PlatformLogger.FINER)) focusLog.finer("Setting current native focused window " + win); + @Override + public void setCurrentFocusedWindow(Window win) { + if (focusLog.isLoggable(PlatformLogger.FINER)) { + focusLog.finer("Setting current focused window " + win); + } + XWindowPeer from = null, to = null; - synchronized(lock) { + synchronized(this) { if (currentFocusedWindow != null) { from = (XWindowPeer)currentFocusedWindow.getPeer(); } @@ -104,8 +86,9 @@ public class XKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl { } } - public static Window getCurrentNativeFocusedWindow() { - synchronized(lock) { + @Override + public Window getCurrentFocusedWindow() { + synchronized(this) { return currentFocusedWindow; } } @@ -124,6 +107,6 @@ public class XKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl { focusedWindowChangeAllowed, time, cause, - getCurrentNativeFocusOwner()); + getInstance().getCurrentFocusOwner()); } } diff --git a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java index 9db352d0cb2..23939a572b6 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java @@ -663,7 +663,7 @@ public final class XToolkit extends UNIXToolkit implements Runnable { long w = 0; if (windowToXWindow(ev.get_xany().get_window()) != null) { Component owner = - XKeyboardFocusManagerPeer.getCurrentNativeFocusOwner(); + XKeyboardFocusManagerPeer.getInstance().getCurrentFocusOwner(); if (owner != null) { XWindow ownerWindow = (XWindow) AWTAccessor.getComponentAccessor().getPeer(owner); if (ownerWindow != null) { @@ -1155,9 +1155,8 @@ public final class XToolkit extends UNIXToolkit implements Runnable { return peer; } - public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) throws HeadlessException { - XKeyboardFocusManagerPeer peer = new XKeyboardFocusManagerPeer(manager); - return peer; + public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() throws HeadlessException { + return XKeyboardFocusManagerPeer.getInstance(); } /** diff --git a/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java index 9ce07cdbb34..a6af2e776d2 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java @@ -617,7 +617,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, public void handleWindowFocusIn_Dispatch() { if (EventQueue.isDispatchThread()) { - XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow((Window) target); + XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow((Window) target); WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS); SunToolkit.setSystemGenerated(we); target.dispatchEvent(we); @@ -626,7 +626,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, public void handleWindowFocusInSync(long serial) { WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS); - XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow((Window) target); + XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow((Window) target); sendEvent(we); } // NOTE: This method may be called by privileged threads. @@ -634,7 +634,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, public void handleWindowFocusIn(long serial) { WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS); /* wrap in Sequenced, then post*/ - XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow((Window) target); + XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow((Window) target); postEvent(wrapInSequenced((AWTEvent) we)); } @@ -642,15 +642,15 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, // DO NOT INVOKE CLIENT CODE ON THIS THREAD! public void handleWindowFocusOut(Window oppositeWindow, long serial) { WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow); - XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow(null); - XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(null); + XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow(null); + XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(null); /* wrap in Sequenced, then post*/ postEvent(wrapInSequenced((AWTEvent) we)); } public void handleWindowFocusOutSync(Window oppositeWindow, long serial) { WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow); - XKeyboardFocusManagerPeer.setCurrentNativeFocusedWindow(null); - XKeyboardFocusManagerPeer.setCurrentNativeFocusOwner(null); + XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow(null); + XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(null); sendEvent(we); } @@ -1138,7 +1138,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, // getWMState() always returns 0 (Withdrawn) for simple windows. Hence // we ignore the state for such windows. if (isVisible() && (state == XUtilConstants.NormalState || isSimpleWindow())) { - if (XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() == + if (XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() == getTarget()) { show = true; @@ -1165,15 +1165,25 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, } public void dispose() { + if (isGrabbed()) { + if (grabLog.isLoggable(PlatformLogger.FINE)) { + grabLog.fine("Generating UngrabEvent on {0} because of the window disposal", this); + } + postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource())); + } + SunToolkit.awtLock(); + try { windows.remove(this); } finally { SunToolkit.awtUnlock(); } + if (warningWindow != null) { warningWindow.destroy(); } + removeRootPropertyEventDispatcher(); mustControlStackPosition = false; super.dispose(); @@ -1185,12 +1195,13 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, * receive WM_TAKE_FOCUS. */ if (isSimpleWindow()) { - if (target == XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow()) { + if (target == XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow()) { Window owner = getDecoratedOwner((Window)target); ((XWindowPeer)AWTAccessor.getComponentAccessor().getPeer(owner)).requestWindowFocus(); } } } + boolean isResizable() { return winAttr.isResizable; } @@ -1825,7 +1836,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, // If this is Frame or Dialog we can't assure focus request success - but we still can try // If this is Window and its owner Frame is active we can be sure request succedded. Window ownerWindow = XWindowPeer.getDecoratedOwner((Window)target); - Window focusedWindow = XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow(); + Window focusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow(); Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow); if (isWMStateNetHidden()) { diff --git a/jdk/src/solaris/instrument/EncodingSupport_md.c b/jdk/src/solaris/instrument/EncodingSupport_md.c index 35ba4502891..456916e2882 100644 --- a/jdk/src/solaris/instrument/EncodingSupport_md.c +++ b/jdk/src/solaris/instrument/EncodingSupport_md.c @@ -33,8 +33,13 @@ /* Routines to convert back and forth between Platform Encoding and UTF-8 */ +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + /* Error and assert macros */ -#define UTF_ERROR(m) utfError(__FILE__, __LINE__, m) +#define UTF_ERROR(m) utfError(THIS_FILE, __LINE__, m) #define UTF_ASSERT(x) ( (x)==0 ? UTF_ERROR("ASSERT ERROR " #x) : (void)0 ) #define UTF_DEBUG(x) diff --git a/jdk/src/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java b/jdk/src/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java index ddaf929fd38..fdd15d29153 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java @@ -25,7 +25,6 @@ package sun.awt.windows; -import java.awt.KeyboardFocusManager; import java.awt.Window; import java.awt.Component; import java.awt.peer.ComponentPeer; @@ -37,8 +36,13 @@ class WKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl { static native Component getNativeFocusOwner(); static native Window getNativeFocusedWindow(); - WKeyboardFocusManagerPeer(KeyboardFocusManager manager) { - super(manager); + private static final WKeyboardFocusManagerPeer inst = new WKeyboardFocusManagerPeer(); + + public static WKeyboardFocusManagerPeer getInstance() { + return inst; + } + + private WKeyboardFocusManagerPeer() { } @Override @@ -51,6 +55,12 @@ class WKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl { return getNativeFocusOwner(); } + @Override + public void setCurrentFocusedWindow(Window win) { + // Not used on Windows + throw new RuntimeException("not implemented"); + } + @Override public Window getCurrentFocusedWindow() { return getNativeFocusedWindow(); diff --git a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java index 515a8230bf3..afbdfa6c1f9 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java +++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java @@ -506,10 +506,10 @@ public class WToolkit extends SunToolkit implements Runnable { return true; } - public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) + public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() throws HeadlessException { - return new WKeyboardFocusManagerPeer(manager); + return WKeyboardFocusManagerPeer.getInstance(); } protected native void setDynamicLayoutNative(boolean b); diff --git a/jdk/src/windows/native/com/sun/media/sound/PLATFORM_API_WinOS_MidiIn.cpp b/jdk/src/windows/native/com/sun/media/sound/PLATFORM_API_WinOS_MidiIn.cpp index 996e70fbb26..1435f6d10c0 100644 --- a/jdk/src/windows/native/com/sun/media/sound/PLATFORM_API_WinOS_MidiIn.cpp +++ b/jdk/src/windows/native/com/sun/media/sound/PLATFORM_API_WinOS_MidiIn.cpp @@ -35,9 +35,15 @@ extern "C" { #ifdef USE_ERROR #include <stdio.h> + +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + #define MIDIIN_CHECK_ERROR { \ if (err != MMSYSERR_NOERROR) \ - ERROR3("MIDI IN Error in %s:%d : %s\n", __FILE__, __LINE__, MIDI_IN_GetErrorStr((INT32) err)); \ + ERROR3("MIDI IN Error in %s:%d : %s\n", THIS_FILE, __LINE__, MIDI_IN_GetErrorStr((INT32) err)); \ } #else #define MIDIIN_CHECK_ERROR diff --git a/jdk/src/windows/native/com/sun/media/sound/PLATFORM_API_WinOS_MidiOut.c b/jdk/src/windows/native/com/sun/media/sound/PLATFORM_API_WinOS_MidiOut.c index e4e68b76754..f3e573e892d 100644 --- a/jdk/src/windows/native/com/sun/media/sound/PLATFORM_API_WinOS_MidiOut.c +++ b/jdk/src/windows/native/com/sun/media/sound/PLATFORM_API_WinOS_MidiOut.c @@ -33,9 +33,15 @@ #ifdef USE_ERROR #include <stdio.h> + +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + #define MIDIOUT_CHECK_ERROR { \ if (err != MMSYSERR_NOERROR) \ - ERROR3("MIDI OUT Error in %s:%d : %s\n", __FILE__, __LINE__, MIDI_OUT_GetErrorStr((INT32) err)); \ + ERROR3("MIDI OUT Error in %s:%d : %s\n", THIS_FILE, __LINE__, MIDI_OUT_GetErrorStr((INT32) err)); \ } #else #define MIDIOUT_CHECK_ERROR diff --git a/jdk/src/windows/native/sun/java2d/d3d/D3DPipeline.h b/jdk/src/windows/native/sun/java2d/d3d/D3DPipeline.h index bcaf4d70198..7eda48f8d62 100644 --- a/jdk/src/windows/native/sun/java2d/d3d/D3DPipeline.h +++ b/jdk/src/windows/native/sun/java2d/d3d/D3DPipeline.h @@ -28,6 +28,11 @@ #define D3D_DEBUG_INFO #endif // DEBUG +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE THIS_FILE +#endif + #ifdef D3D_PPL_DLL @@ -104,7 +109,7 @@ do { \ #define ACT_IF_NULL(ACTION, value) \ if ((value) == NULL) { \ J2dTraceLn3(J2D_TRACE_ERROR, \ - "%s is null in %s:%d", #value, __FILE__, __LINE__); \ + "%s is null in %s:%d", #value, THIS_FILE, __LINE__); \ ACTION; \ } else do { } while (0) #define RETURN_IF_NULL(value) ACT_IF_NULL(return, value) @@ -114,12 +119,12 @@ do { \ #define RETURN_STATUS_IF_EXP_FAILED(EXPR) \ if (FAILED(res = (EXPR))) { \ - DebugPrintD3DError(res, " " ## #EXPR ## " failed in " ## __FILE__); \ + DebugPrintD3DError(res, " " ## #EXPR ## " failed in " ## THIS_FILE); \ return res; \ } else do { } while (0) #define RETURN_STATUS_IF_FAILED(status) \ if (FAILED((status))) { \ - DebugPrintD3DError((status), " failed in " ## __FILE__ ## ", return;");\ + DebugPrintD3DError((status), " failed in " ## THIS_FILE ## ", return;");\ return (status); \ } else do { } while (0) diff --git a/jdk/src/windows/native/sun/windows/alloc.h b/jdk/src/windows/native/sun/windows/alloc.h index fdd0cd6eb72..527da4227c8 100644 --- a/jdk/src/windows/native/sun/windows/alloc.h +++ b/jdk/src/windows/native/sun/windows/alloc.h @@ -26,6 +26,11 @@ #ifndef _ALLOC_H_ #define _ALLOC_H_ +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + #include "stdhdrs.h" // By defining std::bad_alloc in a local header file instead of including @@ -127,12 +132,12 @@ void handle_bad_alloc(void); throw (std::bad_alloc); #define safe_Malloc(size) \ - safe_Malloc_outofmem(size, __FILE__, __LINE__) + safe_Malloc_outofmem(size, THIS_FILE, __LINE__) #define safe_Calloc(num, size) \ - safe_Calloc_outofmem(num, size, __FILE__, __LINE__) + safe_Calloc_outofmem(num, size, THIS_FILE, __LINE__) #define safe_Realloc(memblock, size) \ - safe_Realloc_outofmem(memblock, size, __FILE__, __LINE__) - #define new new(__FILE__, __LINE__) + safe_Realloc_outofmem(memblock, size, THIS_FILE, __LINE__) + #define new new(THIS_FILE, __LINE__) #endif /* OUTOFMEM_TEST */ #define TRY \ diff --git a/jdk/src/windows/native/sun/windows/awt_Debug.h b/jdk/src/windows/native/sun/windows/awt_Debug.h index 9f7c0c08a8b..468b99135f7 100644 --- a/jdk/src/windows/native/sun/windows/awt_Debug.h +++ b/jdk/src/windows/native/sun/windows/awt_Debug.h @@ -65,7 +65,12 @@ #define AWT_DUMP_CLIP_RECTANGLE(_msg, _hwnd) \ _DTrace_Template(DumpClipRectangle, 2, "", (_msg), (_hwnd), 0, 0, 0, 0, 0, 0) - #define new new(__FILE__, __LINE__) + /* Use THIS_FILE when it is available. */ + #ifndef THIS_FILE + #define THIS_FILE __FILE__ + #endif + + #define new new(THIS_FILE, __LINE__) #define VERIFY(exp) DASSERT(exp) #define UNIMPLEMENTED() DASSERT(FALSE) diff --git a/jdk/src/windows/native/sun/windows/awt_Toolkit.h b/jdk/src/windows/native/sun/windows/awt_Toolkit.h index f3e7e74138b..e640d805002 100644 --- a/jdk/src/windows/native/sun/windows/awt_Toolkit.h +++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.h @@ -132,24 +132,30 @@ class CriticalSection { // Macros for using CriticalSection objects that help trace // lock/unlock actions + +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + #define CRITICAL_SECTION_ENTER(cs) { \ J2dTraceLn4(J2D_TRACE_VERBOSE2, \ "CS.Wait: tid, cs, file, line = 0x%x, 0x%x, %s, %d", \ - GetCurrentThreadId(), &(cs), __FILE__, __LINE__); \ + GetCurrentThreadId(), &(cs), THIS_FILE, __LINE__); \ (cs).Enter(); \ J2dTraceLn4(J2D_TRACE_VERBOSE2, \ "CS.Enter: tid, cs, file, line = 0x%x, 0x%x, %s, %d", \ - GetCurrentThreadId(), &(cs), __FILE__, __LINE__); \ + GetCurrentThreadId(), &(cs), THIS_FILE, __LINE__); \ } #define CRITICAL_SECTION_LEAVE(cs) { \ J2dTraceLn4(J2D_TRACE_VERBOSE2, \ "CS.Leave: tid, cs, file, line = 0x%x, 0x%x, %s, %d", \ - GetCurrentThreadId(), &(cs), __FILE__, __LINE__); \ + GetCurrentThreadId(), &(cs), THIS_FILE, __LINE__); \ (cs).Leave(); \ J2dTraceLn4(J2D_TRACE_VERBOSE2, \ "CS.Left: tid, cs, file, line = 0x%x, 0x%x, %s, %d", \ - GetCurrentThreadId(), &(cs), __FILE__, __LINE__); \ + GetCurrentThreadId(), &(cs), THIS_FILE, __LINE__); \ } /************************************************************************ diff --git a/jdk/src/windows/native/sun/windows/awt_Window.cpp b/jdk/src/windows/native/sun/windows/awt_Window.cpp index 83f6f0b9b1c..5c5f53dba40 100644 --- a/jdk/src/windows/native/sun/windows/awt_Window.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Window.cpp @@ -1477,7 +1477,7 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite, if (wClassEvent == NULL) { if (env->PushLocalFrame(1) < 0) return; - wClassEvent = env->FindClass("java/awt/event/WindowEvent"); + wClassEvent = env->FindClass("sun/awt/TimedWindowEvent"); if (wClassEvent != NULL) { wClassEvent = (jclass)env->NewGlobalRef(wClassEvent); } @@ -1491,7 +1491,7 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite, if (wEventInitMID == NULL) { wEventInitMID = env->GetMethodID(wClassEvent, "<init>", - "(Ljava/awt/Window;ILjava/awt/Window;II)V"); + "(Ljava/awt/Window;ILjava/awt/Window;IIJ)V"); DASSERT(wEventInitMID); if (wEventInitMID == NULL) { return; @@ -1532,7 +1532,7 @@ void AwtWindow::SendWindowEvent(jint id, HWND opposite, } } jobject event = env->NewObject(wClassEvent, wEventInitMID, target, id, - jOpposite, oldState, newState); + jOpposite, oldState, newState, TimeHelper::getMessageTimeUTC()); DASSERT(!safe_ExceptionOccurred(env)); DASSERT(event != NULL); if (jOpposite != NULL) { diff --git a/jdk/src/windows/transport/shmem/shmem_md.c b/jdk/src/windows/transport/shmem/shmem_md.c index fe659b03b43..83e9349574b 100644 --- a/jdk/src/windows/transport/shmem/shmem_md.c +++ b/jdk/src/windows/transport/shmem/shmem_md.c @@ -30,6 +30,11 @@ #include "sysShmem.h" #include "shmemBase.h" /* for exitTransportWithError */ +/* Use THIS_FILE when it is available. */ +#ifndef THIS_FILE + #define THIS_FILE __FILE__ +#endif + /* * These functions are not completely universal. For now, they are used * exclusively for Jbug's shared memory transport mechanism. They have @@ -44,7 +49,7 @@ static HANDLE memHandle = NULL; if (!(expression)) { \ exitTransportWithError \ ("\"%s\", line %d: assertion failure\n", \ - __FILE__, __DATE__, __LINE__); \ + THIS_FILE, __DATE__, __LINE__); \ } \ } #else diff --git a/jdk/test/java/awt/Focus/6981400/Test1.java b/jdk/test/java/awt/Focus/6981400/Test1.java new file mode 100644 index 00000000000..2be6e978883 --- /dev/null +++ b/jdk/test/java/awt/Focus/6981400/Test1.java @@ -0,0 +1,222 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 6981400 + * @summary Tabbing between textfiled do not work properly when ALT+TAB + * @author anton.tarasov + * @library ../../regtesthelpers + * @build Util + * @run main Test1 + */ + +// This test shows a frame with four focusable components: b0, b1, b2, b3. +// Then it presses Tab three times. EDT is freezed for a while on the first FOCUS_LOST event. +// Meantime, the test clicks in a component of another frame and then clicks in the title +// of the original frame. When EDT awakes and all the queued events get processed, +// the other frame should ones gain focus and then pass it to the original frame. +// The b3 component of the orinial frame should finally become a focus owner. +// The FOCUS_LOST/FOCUS_GAINED events order in the original frame is tracked and should be: +// b0 -> b1 -> b2 -> b3. + +import java.awt.*; +import java.awt.event.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.swing.*; +import test.java.awt.regtesthelpers.Util; + +public class Test1 { + static JFrame f0 = new JFrame("base_frame") { public String getName() {return "base_frame";} }; + static JButton f0b0 = new JB("b0"); + static JButton f0b1 = new JB("b1"); + static JButton f0b2 = new JB("b2"); + static JButton f0b3 = new JB("b3"); + + static JFrame f1 = new JFrame("swing_frame") { public String getName() {return "swing_frame";} }; + static JButton f1b0 = new JButton("button"); + + static Frame f2 = new Frame("awt_frame") { public String getName() {return "awt_frame";} }; + static Button f2b0 = new Button("button"); + + static Robot robot; + + static List<Component> gainedList = new ArrayList<Component>(); + static List<Component> lostList = new ArrayList<Component>(); + + static Component[] refGainedList = new Component[] {f0b1, f0b2, f0b3, f0b3}; + static Component[] refLostList = new Component[] {f0b0, f0b1, f0b2, f0b3}; + + static boolean tracking; + + public static void main(String[] args) { + Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { + public void eventDispatched(AWTEvent e) { + System.out.println(e); + } + }, FocusEvent.FOCUS_EVENT_MASK | WindowEvent.WINDOW_EVENT_MASK); + + try { + robot = new Robot(); + } catch (AWTException ex) { + throw new RuntimeException("Error: can't create Robot"); + } + + f0.add(f0b0); + f0.add(f0b1); + f0.add(f0b2); + f0.add(f0b3); + f0.setLayout(new FlowLayout()); + f0.setBounds(0, 100, 400, 200); + + f1.add(f1b0); + f1.setBounds(0, 400, 400, 200); + + f2.add(f2b0); + f2.setBounds(0, 400, 400, 200); + + f0b0.addFocusListener(new FocusAdapter() { + @Override + public void focusLost(FocusEvent e) { + try { + Thread.sleep(1000); + } catch (Exception ex) {} + } + }); + + // + // Case 1. Test against swing JFrame. + // + + f1.setVisible(true); + f0.setVisible(true); + + Util.waitForIdle(robot); + + if (!f0b0.isFocusOwner()) { + Util.clickOnComp(f0b0, robot); + Util.waitForIdle(robot); + if (!f0b0.isFocusOwner()) { + throw new RuntimeException("Error: can't focus the component " + f0b0); + } + } + + System.out.println("\nTest case 1: swing frame\n"); + test(f1b0); + + // + // Case 2. Test against awt Frame. + // + + tracking = false; + gainedList.clear(); + lostList.clear(); + + f1.dispose(); + f2.setAutoRequestFocus(false); + f2.setVisible(true); + Util.waitForIdle(robot); + + Util.clickOnComp(f0b0, robot); + Util.waitForIdle(robot); + if (!f0b0.isFocusOwner()) { + throw new RuntimeException("Error: can't focus the component " + f0b0); + } + + System.out.println("\nTest case 2: awt frame\n"); + test(f2b0); + + System.out.println("\nTest passed."); + } + + public static void test(Component compToClick) { + tracking = true; + + robot.keyPress(KeyEvent.VK_TAB); + robot.delay(50); + robot.keyRelease(KeyEvent.VK_TAB); + robot.delay(50); + + robot.keyPress(KeyEvent.VK_TAB); + robot.delay(50); + robot.keyRelease(KeyEvent.VK_TAB); + robot.delay(50); + + robot.keyPress(KeyEvent.VK_TAB); + robot.delay(50); + robot.keyRelease(KeyEvent.VK_TAB); + + robot.delay(50); + Util.clickOnComp(compToClick, robot); + + robot.delay(50); + Util.clickOnTitle(f0, robot); + + Util.waitForIdle(robot); + + if (!f0b3.isFocusOwner()) { + throw new RuntimeException("Test failed: f0b3 is not a focus owner"); + } + + if (!"sun.awt.X11.XToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { + + if (!Arrays.asList(refGainedList).equals(gainedList)) { + System.out.println("gained list: " + gainedList); + throw new RuntimeException("Test failed: wrong FOCUS_GAINED events order"); + } + if (!Arrays.asList(refLostList).equals(lostList)) { + System.out.println("lost list: " + lostList); + throw new RuntimeException("Test failed: wrong FOCUS_LOST events order"); + } + } + } +} + +class JB extends JButton { + String name; + + public JB(String name) { + super(name); + this.name = name; + + addFocusListener(new FocusListener() { + public void focusGained(FocusEvent e) { + if (Test1.tracking) + Test1.gainedList.add(e.getComponent()); + } + + public void focusLost(FocusEvent e) { + if (Test1.tracking) + Test1.lostList.add(e.getComponent()); + } + }); + } + + public String toString() { + return "[" + name + "]"; + } +} diff --git a/jdk/test/java/awt/Focus/6981400/Test2.java b/jdk/test/java/awt/Focus/6981400/Test2.java new file mode 100644 index 00000000000..c41fbbd6b82 --- /dev/null +++ b/jdk/test/java/awt/Focus/6981400/Test2.java @@ -0,0 +1,118 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 6981400 + * @summary Tabbing between textfiled do not work properly when ALT+TAB + * @author anton.tarasov + * @library ../../regtesthelpers + * @build Util + * @run main Test2 + */ + +// A focus request made after a char is typed ahead shouldn't affect the char's target component. + +import java.awt.*; +import java.awt.event.*; +import test.java.awt.regtesthelpers.Util; + +public class Test2 { + static Frame f = new Frame("frame"); + static TextArea t0 = new TextArea(1, 10) { public String toString() { return "[TA-0]";} }; + static TextArea t1 = new TextArea(1, 10) { public String toString() { return "[TA-1]";} }; + static TextArea t2 = new TextArea(1, 10) { public String toString() { return "[TA-2]";} }; + + static volatile boolean passed = true; + + static Robot robot; + + public static void main(String[] args) { + Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { + public void eventDispatched(AWTEvent e) { + System.out.println(e); + if (e.getID() == KeyEvent.KEY_TYPED) { + if (e.getSource() != t1) { + passed = false; + throw new RuntimeException("Test failed: the key event has wrong source: " + e); + } + } + } + }, FocusEvent.FOCUS_EVENT_MASK | KeyEvent.KEY_EVENT_MASK); + + try { + robot = new Robot(); + } catch (AWTException ex) { + throw new RuntimeException("Error: can't create Robot"); + } + + f.add(t0); + f.add(t1); + f.add(t2); + + f.setLayout(new FlowLayout()); + f.pack(); + + t0.addFocusListener(new FocusAdapter() { + public void focusLost(FocusEvent e) { + try { + Thread.sleep(3000); + } catch (Exception ex) {} + } + }); + + // The request shouldn't affect the key event delivery. + new Thread(new Runnable() { + public void run() { + try { + Thread.sleep(2000); + } catch (Exception ex) {} + System.out.println("requesting focus to " + t2); + t2.requestFocus(); + } + }).start(); + + + f.setVisible(true); + Util.waitForIdle(robot); + + test(); + + if (passed) System.out.println("\nTest passed."); + } + + static void test() { + Util.clickOnComp(t1, robot); + + // The key event should be eventually delivered to t1. + robot.delay(50); + robot.keyPress(KeyEvent.VK_A); + robot.delay(50); + robot.keyRelease(KeyEvent.VK_A); + + Util.waitForIdle(robot); + } +} + diff --git a/jdk/test/java/awt/Focus/6981400/Test3.java b/jdk/test/java/awt/Focus/6981400/Test3.java new file mode 100644 index 00000000000..268cbdf4dd6 --- /dev/null +++ b/jdk/test/java/awt/Focus/6981400/Test3.java @@ -0,0 +1,141 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 6981400 + * @summary Tabbing between textfiled do not work properly when ALT+TAB + * @author anton.tarasov + * @library ../../regtesthelpers + * @build Util + * @run main Test3 + */ + +// A menu item in a frame should not be auto-selected when switching by Alt+TAB back and forth. + +import java.awt.*; +import javax.swing.*; +import java.awt.event.*; +import test.java.awt.regtesthelpers.Util; + +public class Test3 { + static JFrame f = new JFrame("Frame"); + static JMenuBar bar = new JMenuBar(); + static JMenu menu = new JMenu("File"); + static JMenuItem item = new JMenuItem("Save"); + + static JButton b0 = new JButton("b0"); + static JButton b1 = new JButton("b1"); + + static Robot robot; + + public static void main(String[] args) { + Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { + public void eventDispatched(AWTEvent e) { + System.err.println(e); + } + }, KeyEvent.KEY_EVENT_MASK); + + try { + robot = new Robot(); + } catch (AWTException ex) { + throw new RuntimeException("Error: can't create Robot"); + } + + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + } catch (Exception e) {} + + b0.addFocusListener(new FocusAdapter() { + public void focusLost(FocusEvent f) { + try { + Thread.sleep(2000); + } catch (Exception e) {} + } + }); + + menu.add(item); + bar.add(menu); + f.setJMenuBar(bar); + + f.add(b0); + f.add(b1); + + f.setLayout(new FlowLayout()); + f.setSize(400, 100); + f.setVisible(true); + Util.waitForIdle(robot); + + if (!b0.hasFocus()) { + Util.clickOnComp(b0, robot); + Util.waitForIdle(robot); + if (!b0.hasFocus()) { + throw new RuntimeException("Error: can't focus " + b0); + } + } + + test(); + + System.out.println("Test passed."); + } + + public static void test() { + robot.keyPress(KeyEvent.VK_TAB); + robot.delay(50); + robot.keyRelease(KeyEvent.VK_TAB); + robot.delay(50); + + robot.keyPress(KeyEvent.VK_ALT); + robot.delay(50); + robot.keyPress(KeyEvent.VK_TAB); + robot.delay(50); + robot.keyRelease(KeyEvent.VK_ALT); + robot.delay(50); + robot.keyRelease(KeyEvent.VK_TAB); + + robot.delay(500); + + robot.keyPress(KeyEvent.VK_ALT); + robot.delay(50); + robot.keyPress(KeyEvent.VK_TAB); + robot.delay(50); + robot.keyRelease(KeyEvent.VK_ALT); + robot.delay(50); + robot.keyRelease(KeyEvent.VK_TAB); + + // Control shot. + Util.clickOnTitle(f, robot); + Util.waitForIdle(robot); + + if (menu.isSelected()) { + throw new RuntimeException("Test failed: the menu gets selected"); + } + if (!b1.hasFocus()) { + throw new RuntimeException("Test failed: the button is not a focus owner " + b1); + } + } +} + + diff --git a/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java b/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java index 6d685350412..f38debc7566 100644 --- a/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java +++ b/jdk/test/java/beans/Introspector/6380849/TestBeanInfo.java @@ -38,8 +38,7 @@ import infos.ThirdBeanBeanInfo; import java.beans.BeanInfo; import java.beans.Introspector; -import java.lang.ref.Reference; -import java.lang.reflect.Field; +import java.lang.reflect.Method; public class TestBeanInfo implements Runnable { @@ -60,10 +59,9 @@ public class TestBeanInfo implements Runnable { try { actual = Introspector.getBeanInfo(type); type = actual.getClass(); - Field field = type.getDeclaredField("targetBeanInfoRef"); // NON-NLS: field name - field.setAccessible(true); - Reference ref = (Reference) field.get(actual); - actual = (BeanInfo) ref.get(); + Method method = type.getDeclaredMethod("getTargetBeanInfo"); // NON-NLS: method name + method.setAccessible(true); + actual = (BeanInfo) method.invoke(actual); } catch (Exception exception) { throw new Error("unexpected error", exception); diff --git a/jdk/test/java/beans/Introspector/Test7186794.java b/jdk/test/java/beans/Introspector/Test7186794.java new file mode 100644 index 00000000000..5ee13bae490 --- /dev/null +++ b/jdk/test/java/beans/Introspector/Test7186794.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7186794 + * @summary Tests setter in the super class + * @author Sergey Malenkov + */ + +import java.util.List; + +public class Test7186794 { + + public static void main(String[] args) { + if (null == BeanUtils.findPropertyDescriptor(MyBean.class, "value").getWriteMethod()) { + throw new Error("The property setter is not found"); + } + } + + public static class BaseBean { + + protected List<String> value; + + public void setValue(List<String> value) { + this.value = value; + } + } + + public static class MyBean extends BaseBean { + public List<String> getValue() { + return super.value; + } + } +} diff --git a/jdk/test/java/beans/Introspector/Test7189112.java b/jdk/test/java/beans/Introspector/Test7189112.java index 61042f9467e..938731ac2dc 100644 --- a/jdk/test/java/beans/Introspector/Test7189112.java +++ b/jdk/test/java/beans/Introspector/Test7189112.java @@ -28,17 +28,11 @@ * @author Sergey Malenkov */ -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; - public class Test7189112 { - public static void main(String[] args) throws IntrospectionException { - for (PropertyDescriptor pd : Introspector.getBeanInfo(MyBean.class).getPropertyDescriptors()) { - if (pd.getName().equals("value") && (null == pd.getWriteMethod())) { - throw new Error("The property setter is not found"); - } + public static void main(String[] args) { + if (null == BeanUtils.findPropertyDescriptor(MyBean.class, "value").getWriteMethod()) { + throw new Error("The property setter is not found"); } } diff --git a/jdk/test/java/beans/Introspector/Test7192955.java b/jdk/test/java/beans/Introspector/Test7192955.java new file mode 100644 index 00000000000..13e874ba719 --- /dev/null +++ b/jdk/test/java/beans/Introspector/Test7192955.java @@ -0,0 +1,83 @@ +/* + * 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 7192955 + * @summary Tests that all properties are bound + * @author Sergey Malenkov + */ + +import java.beans.PropertyChangeListener; +import java.util.List; + +public class Test7192955 { + + public static void main(String[] args) { + if (!BeanUtils.findPropertyDescriptor(MyBean.class, "test").isBound()) { + throw new Error("a simple property is not bound"); + } + if (!BeanUtils.findPropertyDescriptor(MyBean.class, "list").isBound()) { + throw new Error("a generic property is not bound"); + } + if (!BeanUtils.findPropertyDescriptor(MyBean.class, "readOnly").isBound()) { + throw new Error("a read-only property is not bound"); + } + } + + public static class BaseBean { + + private List<String> list; + + public List<String> getList() { + return this.list; + } + + public void setList(List<String> list) { + this.list = list; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + } + + public List<String> getReadOnly() { + return this.list; + } + } + + public static class MyBean extends BaseBean { + + private String test; + + public String getTest() { + return this.test; + } + + public void setTest(String test) { + this.test = test; + } + } +} diff --git a/jdk/test/java/beans/Introspector/Test7195106.java b/jdk/test/java/beans/Introspector/Test7195106.java new file mode 100644 index 00000000000..e47512a91b0 --- /dev/null +++ b/jdk/test/java/beans/Introspector/Test7195106.java @@ -0,0 +1,67 @@ +/* + * 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 7195106 + * @summary Tests that explicit BeanInfo is not collected + * @author Sergey Malenkov + */ + +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.SimpleBeanInfo; + +public class Test7195106 { + + public static void main(String[] arg) throws Exception { + BeanInfo info = Introspector.getBeanInfo(My.class); + if (null == info.getIcon(BeanInfo.ICON_COLOR_16x16)) { + throw new Error("Unexpected behavior"); + } + try { + int[] array = new int[1024]; + while (true) { + array = new int[array.length << 1]; + } + } + catch (OutOfMemoryError error) { + System.gc(); + } + if (null == info.getIcon(BeanInfo.ICON_COLOR_16x16)) { + throw new Error("Explicit BeanInfo is collected"); + } + } + + public static class My { + } + + public static class MyBeanInfo extends SimpleBeanInfo { + @Override + public Image getIcon(int type) { + return new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB); + } + } +} diff --git a/jdk/test/java/beans/XMLEncoder/Test7169395.java b/jdk/test/java/beans/XMLEncoder/Test7169395.java new file mode 100644 index 00000000000..42257f512cd --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/Test7169395.java @@ -0,0 +1,101 @@ +/* + * 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 7169395 + * @summary Tests that array list initialized correctly + * @author Sergey Malenkov + */ + +import java.beans.ConstructorProperties; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; +import java.util.TreeMap; + +public class Test7169395 extends AbstractTest { + + public static void main(String[] args) { + new Test7169395().test(true); + } + + protected Object getObject() { + Container container = new Container(); + container.add("test-null", null); + container.add("test-value", "value"); + container.add("test-other", "other"); + return container; + } + + public static class Component { + + private final Container container; + private final String name; + private String value; + + @ConstructorProperties({ "container", "name" }) + public Component(Container container, String name) { + this.container = container; + this.name = name; + } + + public Container getContainer() { + return this.container; + } + + public String getName() { + return this.name; + } + + public String getValue() { + return this.value; + } + + public void setValue(String value) { + this.value = value; + } + } + + public static class Container { + + private final Map<String, Component> map = new TreeMap<String, Component>(); + + public Collection<Component> getComponents() { + return new ArrayList<Component>(this.map.values()); + } + + public void setComponents(Collection<Component> components) { + this.map.clear(); + for (Component component : components){ + this.map.put(component.getName(), component); + } + } + + public void add(String name, String value) { + Component list = new Component(this, name); + list.setValue(value); + this.map.put(name, list); + } + } +} diff --git a/jdk/test/java/lang/invoke/BigArityTest.java b/jdk/test/java/lang/invoke/BigArityTest.java new file mode 100644 index 00000000000..9aeaa79af0b --- /dev/null +++ b/jdk/test/java/lang/invoke/BigArityTest.java @@ -0,0 +1,1044 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 + * @summary High arity invocations, up to the maximum of 255 arguments + * @compile BigArityTest.java + * @run junit/othervm -DBigArityTest.ITERATION_COUNT=1 test.java.lang.invoke.BigArityTest + */ + +package test.java.lang.invoke; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.WrongMethodTypeException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Objects; +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class BigArityTest { + + static MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); + + static final int MAX_JVM_ARITY = 255; + static final int ITERATION_COUNT = getProperty("ITERATION_COUNT", 40000); + static final int MIN_ARITY = getProperty("MIN_ARITY", 250); + static final int SLOW_ARITY = getProperty("SLOW_ARITY", MAX_JVM_ARITY-3); + static final int MAX_ARITY = getProperty("MAX_ARITY", MAX_JVM_ARITY-1); // always -1 for the MH reciever itself + private static int getProperty(String name, int dflt) { + return Integer.parseInt(getProperty(name, ""+dflt)); + } + private static String getProperty(String name, String dflt) { + String x = System.getProperty(BigArityTest.class.getSimpleName() + "." + name); + if (x == null) x = System.getProperty(BigArityTest.class.getName() + "." + name); + return x == null ? dflt : x; + } + + static Object hashArguments(Object... args) { + return Objects.hash(args); + } + static final MethodHandle MH_hashArguments_VA; + static { + try { + MH_hashArguments_VA = + MethodHandles.lookup().unreflect( + BigArityTest.class.getDeclaredMethod("hashArguments", Object[].class)); + } catch (ReflectiveOperationException ex) { + throw new InternalError(ex); + } + } + static MethodHandle MH_hashArguments(int arity) { + MethodType mt = MethodType.genericMethodType(arity); + return MH_hashArguments_VA.asType(mt); + } + static MethodHandle MH_hashArguments(Class<? extends Object[]> arrayClass, int arity) { + if (arrayClass == Object[].class) + return MH_hashArguments(arity); + ArrayList<Class<?>> ptypes = new ArrayList<>(Collections.<Class<?>>nCopies(arity, arrayClass.getComponentType())); + MethodType mt = MethodType.methodType(Object.class, ptypes); + return MH_hashArguments_VA.asType(mt); + } + + static Object[] testArgs(int arity) { + Object args[] = new Object[arity]; + for (int i = 0; i < arity; i++) + args[i] = i * (i + 1) / 2; + return args; + } + + @Test + public void testBoundaryValues() throws Throwable { + for (int badArity : new int[]{ -1, MAX_JVM_ARITY+1, MAX_JVM_ARITY }) { + try { + MethodHandle badmh = MH_hashArguments(badArity); + throw new AssertionError("should not be able to build a 255-arity MH: "+badmh); + } catch (IllegalArgumentException | WrongMethodTypeException ex) { + System.out.println("OK: "+ex); + } + } + } + + // Make sure the basic argument spreading and varargs mechanisms are working. + // Exercise arity 3 thoroughly. + @Test + public void testSpreads() throws Throwable { + System.out.println("testing asSpreader on arity=3"); + Object[] args = testArgs(3); + int r0 = Objects.hash(args); + MethodHandle mh = MH_hashArguments(3); + Object r; + r = mh.invokeExact(args[0], args[1], args[2]); + assertEquals(r0, r); + r = mh.invoke(args[0], args[1], args[2]); + assertEquals(r0, r); + r = mh.invoke((Comparable) args[0], (Integer) args[1], (Number) args[2]); + assertEquals(r0, r); + r = mh.invokeWithArguments(args); + assertEquals(r0, r); + for (Class<?> cls0 : new Class<?>[] { + Object[].class, Number[].class, Integer[].class, Comparable[].class + }) { + @SuppressWarnings("unchecked") + Class<? extends Object[]> cls = (Class<? extends Object[]>) cls0; + //Class<? extends Object[]> cls = Object[].class.asSubclass(cls0); + int nargs = args.length, skip; + MethodHandle smh = mh.asSpreader(cls, nargs - (skip = 0)); + Object[] tail = Arrays.copyOfRange(args, skip, nargs, cls); + if (cls == Object[].class) + r = smh.invokeExact(tail); + else if (cls == Integer[].class) + r = smh.invokeExact((Integer[]) tail); + else + r = smh.invoke(tail); + assertEquals(r0, r); + smh = mh.asSpreader(cls, nargs - (skip = 1)); + tail = Arrays.copyOfRange(args, skip, nargs, cls); + if (cls == Object[].class) + r = smh.invokeExact(args[0], tail); + else if (cls == Integer[].class) + r = smh.invokeExact(args[0], (Integer[]) tail); + else + r = smh.invoke(args[0], tail); + assertEquals(r0, r); + smh = mh.asSpreader(cls, nargs - (skip = 2)); + tail = Arrays.copyOfRange(args, skip, nargs, cls); + if (cls == Object[].class) + r = smh.invokeExact(args[0], args[1], tail); + else if (cls == Integer[].class) + r = smh.invokeExact(args[0], args[1], (Integer[]) tail); + else + r = smh.invoke(args[0], args[1], tail); + assertEquals(r0, r); + smh = mh.asSpreader(cls, nargs - (skip = 3)); + tail = Arrays.copyOfRange(args, skip, nargs, cls); + if (cls == Object[].class) + r = smh.invokeExact(args[0], args[1], args[2], tail); + else if (cls == Integer[].class) + r = smh.invokeExact(args[0], args[1], args[2], (Integer[]) tail); + else + r = smh.invoke(args[0], args[1], args[2], tail); + assertEquals(r0, r); + // Try null array in addition to zero-length array: + tail = null; + if (cls == Object[].class) + r = smh.invokeExact(args[0], args[1], args[2], tail); + else if (cls == Integer[].class) + r = smh.invokeExact(args[0], args[1], args[2], (Integer[]) tail); + else + r = smh.invoke(args[0], args[1], args[2], tail); + assertEquals(r0, r); + } + } + + @Test + public void testInvokeWithArguments() throws Throwable { + System.out.println("testing invokeWithArguments on all arities"); + for (int arity = 0; arity < MAX_ARITY; arity++) { + Object[] args = testArgs(arity); + Object r0 = Objects.hash(args); + Object r = MH_hashArguments(arity).invokeWithArguments(args); + assertEquals("arity="+arity, r0, r); + } + // The next one is the most likely to fail: + int arity = MAX_ARITY; + Object[] args = testArgs(arity); + Object r0 = Objects.hash(args); + Object r = MH_hashArguments(arity).invokeWithArguments(args); + assertEquals("arity=MAX_ARITY", r0, r); + } + + static Object[] cat(Object a, Object[] b) { + int alen = 1, blen = b.length; + Object[] c = new Object[alen + blen]; + c[0] = a; + System.arraycopy(b, 0, c, alen, blen); + return c; + } + + @Test + public void testArities() throws Throwable { + System.out.println("testing spreaders and collectors on high arities..."); + int iterations = ITERATION_COUNT; + testArities(Object[].class, MIN_ARITY-10, MIN_ARITY-1, iterations / 1000); + testArities(Object[].class, MIN_ARITY, SLOW_ARITY-1, iterations); + testArities(Object[].class, SLOW_ARITY, MAX_ARITY, iterations / 1000); + } + + @Test + public void testAritiesOnTypedArrays() throws Throwable { + for (Class<?> cls0 : new Class<?>[] { + Number[].class, Integer[].class, Comparable[].class + }) { + @SuppressWarnings("unchecked") + Class<? extends Object[]> cls = (Class<? extends Object[]>) cls0; + System.out.println("array class: "+cls.getSimpleName()); + int iterations = ITERATION_COUNT / 1000; + testArities(cls, MIN_ARITY, SLOW_ARITY-1, iterations); + testArities(cls, SLOW_ARITY, MAX_ARITY, iterations / 100); + } + } + + private void testArities(Class<? extends Object[]> cls, + int minArity, + int maxArity, + int iterations) throws Throwable { + boolean verbose = (cls == Object[].class); + for (int arity = minArity; arity <= maxArity; arity++) { + if (verbose) System.out.println("arity="+arity); + MethodHandle mh = MH_hashArguments(cls, arity); + MethodHandle mh_VA = mh.asSpreader(cls, arity); + assert(mh_VA.type().parameterType(0) == cls); + testArities(cls, arity, iterations, verbose, mh, mh_VA); + if (cls != Object[].class) { + // mh_CA will collect arguments of a particular type and pass them to mh_VA + MethodHandle mh_CA = mh_VA.asCollector(cls, arity); + MethodHandle mh_VA2 = mh_CA.asSpreader(cls, arity); + try { + mh_VA2.invokeWithArguments(new Object[arity]); + throw new AssertionError("should not reach"); + } catch (ClassCastException | WrongMethodTypeException ex) { + } + assert(mh_CA.type().equals(mh.type())); + assert(mh_VA2.type().equals(mh_VA.type())); + testArities(cls, arity, iterations, false, mh_CA, mh_VA2); + } + } + } + private void testArities(Class<? extends Object[]> cls, + int arity, + int iterations, + boolean verbose, + MethodHandle mh, + MethodHandle mh_VA + ) throws Throwable { + if (iterations < 4) iterations = 4; + final int MAX_MH_ARITY = MAX_JVM_ARITY - 1; // mh.invoke(arg*[N]) + final int MAX_INVOKER_ARITY = MAX_MH_ARITY - 1; // inv.invoke(mh, arg*[N]) + Object[] args = testArgs(arity); + if (cls != Object[].class) + args = Arrays.copyOf(args, arity, cls); + Object r0 = Objects.hash(args); + Object r; + MethodHandle ximh = null; + MethodHandle gimh = null; + if (arity <= MAX_INVOKER_ARITY) { + ximh = MethodHandles.exactInvoker(mh.type()); + gimh = MethodHandles.invoker(mh.type()); + } else { + try { + ximh = MethodHandles.exactInvoker(mh.type()); + throw new AssertionError("should fail to create ximh of arity "+arity); + } catch (IllegalArgumentException ex) { + if (verbose) + System.out.println("OK: xmih["+arity+"] => "+ex); + } + try { + gimh = MethodHandles.invoker(mh.type()); + throw new AssertionError("should fail to create gimh of arity "+arity); + } catch (IllegalArgumentException ex) { + if (verbose) + System.out.println("OK: gmih["+arity+"] => "+ex); + } + } + Object[] mh_args = cat(mh, args); + assert(arity <= MAX_MH_ARITY); + for (int i = 0; i < iterations; ++i) { + if (cls == Object[].class) + r = mh_VA.invokeExact(args); + else if (cls == Integer[].class) + r = mh_VA.invokeExact((Integer[])args); + else + r = mh_VA.invoke(args); + assertEquals(r0, r); + r = mh.invokeWithArguments(args); + assertEquals(r0, r); + if (ximh != null) { + r = ximh.invokeWithArguments(mh_args); + assertEquals(r0, r); + } + if (gimh != null) { + r = gimh.invokeWithArguments(mh_args); + assertEquals(r0, r); + } + } + } + + static Object hashArguments_252( + // <editor-fold defaultstate="collapsed" desc="Object x00, Object x01, Object x02, Object x03, Object x04, ..."> + Object x00, Object x01, Object x02, Object x03, Object x04, Object x05, Object x06, Object x07, + Object x08, Object x09, Object x0A, Object x0B, Object x0C, Object x0D, Object x0E, Object x0F, + Object x10, Object x11, Object x12, Object x13, Object x14, Object x15, Object x16, Object x17, + Object x18, Object x19, Object x1A, Object x1B, Object x1C, Object x1D, Object x1E, Object x1F, + Object x20, Object x21, Object x22, Object x23, Object x24, Object x25, Object x26, Object x27, + Object x28, Object x29, Object x2A, Object x2B, Object x2C, Object x2D, Object x2E, Object x2F, + Object x30, Object x31, Object x32, Object x33, Object x34, Object x35, Object x36, Object x37, + Object x38, Object x39, Object x3A, Object x3B, Object x3C, Object x3D, Object x3E, Object x3F, + Object x40, Object x41, Object x42, Object x43, Object x44, Object x45, Object x46, Object x47, + Object x48, Object x49, Object x4A, Object x4B, Object x4C, Object x4D, Object x4E, Object x4F, + Object x50, Object x51, Object x52, Object x53, Object x54, Object x55, Object x56, Object x57, + Object x58, Object x59, Object x5A, Object x5B, Object x5C, Object x5D, Object x5E, Object x5F, + Object x60, Object x61, Object x62, Object x63, Object x64, Object x65, Object x66, Object x67, + Object x68, Object x69, Object x6A, Object x6B, Object x6C, Object x6D, Object x6E, Object x6F, + Object x70, Object x71, Object x72, Object x73, Object x74, Object x75, Object x76, Object x77, + Object x78, Object x79, Object x7A, Object x7B, Object x7C, Object x7D, Object x7E, Object x7F, + Object x80, Object x81, Object x82, Object x83, Object x84, Object x85, Object x86, Object x87, + Object x88, Object x89, Object x8A, Object x8B, Object x8C, Object x8D, Object x8E, Object x8F, + Object x90, Object x91, Object x92, Object x93, Object x94, Object x95, Object x96, Object x97, + Object x98, Object x99, Object x9A, Object x9B, Object x9C, Object x9D, Object x9E, Object x9F, + Object xA0, Object xA1, Object xA2, Object xA3, Object xA4, Object xA5, Object xA6, Object xA7, + Object xA8, Object xA9, Object xAA, Object xAB, Object xAC, Object xAD, Object xAE, Object xAF, + Object xB0, Object xB1, Object xB2, Object xB3, Object xB4, Object xB5, Object xB6, Object xB7, + Object xB8, Object xB9, Object xBA, Object xBB, Object xBC, Object xBD, Object xBE, Object xBF, + Object xC0, Object xC1, Object xC2, Object xC3, Object xC4, Object xC5, Object xC6, Object xC7, + Object xC8, Object xC9, Object xCA, Object xCB, Object xCC, Object xCD, Object xCE, Object xCF, + Object xD0, Object xD1, Object xD2, Object xD3, Object xD4, Object xD5, Object xD6, Object xD7, + Object xD8, Object xD9, Object xDA, Object xDB, Object xDC, Object xDD, Object xDE, Object xDF, + Object xE0, Object xE1, Object xE2, Object xE3, Object xE4, Object xE5, Object xE6, Object xE7, + Object xE8, Object xE9, Object xEA, Object xEB, Object xEC, Object xED, Object xEE, Object xEF, + Object xF0, Object xF1, Object xF2, Object xF3, Object xF4, Object xF5, Object xF6, Object xF7, + // </editor-fold> + Object xF8, Object xF9, Object xFA, Object xFB) { + return Objects.hash( + // <editor-fold defaultstate="collapsed" desc="x00, x01, x02, x03, x04, ..."> + x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x0A, x0B, x0C, x0D, x0E, x0F, + x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x1A, x1B, x1C, x1D, x1E, x1F, + x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x2A, x2B, x2C, x2D, x2E, x2F, + x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x3A, x3B, x3C, x3D, x3E, x3F, + x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x4A, x4B, x4C, x4D, x4E, x4F, + x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x5A, x5B, x5C, x5D, x5E, x5F, + x60, x61, x62, x63, x64, x65, x66, x67, x68, x69, x6A, x6B, x6C, x6D, x6E, x6F, + x70, x71, x72, x73, x74, x75, x76, x77, x78, x79, x7A, x7B, x7C, x7D, x7E, x7F, + x80, x81, x82, x83, x84, x85, x86, x87, x88, x89, x8A, x8B, x8C, x8D, x8E, x8F, + x90, x91, x92, x93, x94, x95, x96, x97, x98, x99, x9A, x9B, x9C, x9D, x9E, x9F, + xA0, xA1, xA2, xA3, xA4, xA5, xA6, xA7, xA8, xA9, xAA, xAB, xAC, xAD, xAE, xAF, + xB0, xB1, xB2, xB3, xB4, xB5, xB6, xB7, xB8, xB9, xBA, xBB, xBC, xBD, xBE, xBF, + xC0, xC1, xC2, xC3, xC4, xC5, xC6, xC7, xC8, xC9, xCA, xCB, xCC, xCD, xCE, xCF, + xD0, xD1, xD2, xD3, xD4, xD5, xD6, xD7, xD8, xD9, xDA, xDB, xDC, xDD, xDE, xDF, + xE0, xE1, xE2, xE3, xE4, xE5, xE6, xE7, xE8, xE9, xEA, xEB, xEC, xED, xEE, xEF, + xF0, xF1, xF2, xF3, xF4, xF5, xF6, xF7, + // </editor-fold> + xF8, xF9, xFA, xFB); + } + + @Test + public void test252() throws Throwable { + final int ARITY = 252; + System.out.println("test"+ARITY); + Object[] a = testArgs(ARITY); + Object r0 = hashArguments(a); + Object r; + r = hashArguments_252( + // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB]); + assertEquals(r0, r); + MethodType mt = MethodType.genericMethodType(ARITY); + MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt); + r = mh.invokeExact( + // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB]); + assertEquals(r0, r); + r = mh.invokeWithArguments(a); + assertEquals(r0, r); + MethodHandle ximh = MethodHandles.exactInvoker(mh.type()); + r = ximh.invokeExact(mh, + // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB]); + assertEquals(r0, r); + r = ximh.invokeWithArguments(cat(mh,a)); + assertEquals(r0, r); + MethodHandle gimh = MethodHandles.invoker(mh.type()); + r = gimh.invoke(mh, + // <editor-fold defaultstate="collapsed" desc="(Number) a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> + (Number) + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB]); + assertEquals(r0, r); + r = gimh.invokeWithArguments(cat(mh,a)); + assertEquals(r0, r); + mh = mh.asType(mh.type().changeParameterType(0x10, Integer.class)); + //System.out.println("type="+mh.type().toString().replaceAll("Object", "")); + r = mh.invokeExact( + // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ... (Integer) a[0x10], ..."> + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + (Integer) + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB]); + assertEquals(r0, r); + r = mh.invoke( + // <editor-fold defaultstate="collapsed" desc="(Comparable) a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> + (Comparable<?>) + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB]); + assertEquals(r0, r); + } + + static Object hashArguments_253( + // <editor-fold defaultstate="collapsed" desc="Object x00, Object x01, Object x02, Object x03, Object x04, ..."> + Object x00, Object x01, Object x02, Object x03, Object x04, Object x05, Object x06, Object x07, + Object x08, Object x09, Object x0A, Object x0B, Object x0C, Object x0D, Object x0E, Object x0F, + Object x10, Object x11, Object x12, Object x13, Object x14, Object x15, Object x16, Object x17, + Object x18, Object x19, Object x1A, Object x1B, Object x1C, Object x1D, Object x1E, Object x1F, + Object x20, Object x21, Object x22, Object x23, Object x24, Object x25, Object x26, Object x27, + Object x28, Object x29, Object x2A, Object x2B, Object x2C, Object x2D, Object x2E, Object x2F, + Object x30, Object x31, Object x32, Object x33, Object x34, Object x35, Object x36, Object x37, + Object x38, Object x39, Object x3A, Object x3B, Object x3C, Object x3D, Object x3E, Object x3F, + Object x40, Object x41, Object x42, Object x43, Object x44, Object x45, Object x46, Object x47, + Object x48, Object x49, Object x4A, Object x4B, Object x4C, Object x4D, Object x4E, Object x4F, + Object x50, Object x51, Object x52, Object x53, Object x54, Object x55, Object x56, Object x57, + Object x58, Object x59, Object x5A, Object x5B, Object x5C, Object x5D, Object x5E, Object x5F, + Object x60, Object x61, Object x62, Object x63, Object x64, Object x65, Object x66, Object x67, + Object x68, Object x69, Object x6A, Object x6B, Object x6C, Object x6D, Object x6E, Object x6F, + Object x70, Object x71, Object x72, Object x73, Object x74, Object x75, Object x76, Object x77, + Object x78, Object x79, Object x7A, Object x7B, Object x7C, Object x7D, Object x7E, Object x7F, + Object x80, Object x81, Object x82, Object x83, Object x84, Object x85, Object x86, Object x87, + Object x88, Object x89, Object x8A, Object x8B, Object x8C, Object x8D, Object x8E, Object x8F, + Object x90, Object x91, Object x92, Object x93, Object x94, Object x95, Object x96, Object x97, + Object x98, Object x99, Object x9A, Object x9B, Object x9C, Object x9D, Object x9E, Object x9F, + Object xA0, Object xA1, Object xA2, Object xA3, Object xA4, Object xA5, Object xA6, Object xA7, + Object xA8, Object xA9, Object xAA, Object xAB, Object xAC, Object xAD, Object xAE, Object xAF, + Object xB0, Object xB1, Object xB2, Object xB3, Object xB4, Object xB5, Object xB6, Object xB7, + Object xB8, Object xB9, Object xBA, Object xBB, Object xBC, Object xBD, Object xBE, Object xBF, + Object xC0, Object xC1, Object xC2, Object xC3, Object xC4, Object xC5, Object xC6, Object xC7, + Object xC8, Object xC9, Object xCA, Object xCB, Object xCC, Object xCD, Object xCE, Object xCF, + Object xD0, Object xD1, Object xD2, Object xD3, Object xD4, Object xD5, Object xD6, Object xD7, + Object xD8, Object xD9, Object xDA, Object xDB, Object xDC, Object xDD, Object xDE, Object xDF, + Object xE0, Object xE1, Object xE2, Object xE3, Object xE4, Object xE5, Object xE6, Object xE7, + Object xE8, Object xE9, Object xEA, Object xEB, Object xEC, Object xED, Object xEE, Object xEF, + Object xF0, Object xF1, Object xF2, Object xF3, Object xF4, Object xF5, Object xF6, Object xF7, + // </editor-fold> + Object xF8, Object xF9, Object xFA, Object xFB, Object xFC) { + return Objects.hash( + // <editor-fold defaultstate="collapsed" desc="x00, x01, x02, x03, x04, ..."> + x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x0A, x0B, x0C, x0D, x0E, x0F, + x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x1A, x1B, x1C, x1D, x1E, x1F, + x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x2A, x2B, x2C, x2D, x2E, x2F, + x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x3A, x3B, x3C, x3D, x3E, x3F, + x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x4A, x4B, x4C, x4D, x4E, x4F, + x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x5A, x5B, x5C, x5D, x5E, x5F, + x60, x61, x62, x63, x64, x65, x66, x67, x68, x69, x6A, x6B, x6C, x6D, x6E, x6F, + x70, x71, x72, x73, x74, x75, x76, x77, x78, x79, x7A, x7B, x7C, x7D, x7E, x7F, + x80, x81, x82, x83, x84, x85, x86, x87, x88, x89, x8A, x8B, x8C, x8D, x8E, x8F, + x90, x91, x92, x93, x94, x95, x96, x97, x98, x99, x9A, x9B, x9C, x9D, x9E, x9F, + xA0, xA1, xA2, xA3, xA4, xA5, xA6, xA7, xA8, xA9, xAA, xAB, xAC, xAD, xAE, xAF, + xB0, xB1, xB2, xB3, xB4, xB5, xB6, xB7, xB8, xB9, xBA, xBB, xBC, xBD, xBE, xBF, + xC0, xC1, xC2, xC3, xC4, xC5, xC6, xC7, xC8, xC9, xCA, xCB, xCC, xCD, xCE, xCF, + xD0, xD1, xD2, xD3, xD4, xD5, xD6, xD7, xD8, xD9, xDA, xDB, xDC, xDD, xDE, xDF, + xE0, xE1, xE2, xE3, xE4, xE5, xE6, xE7, xE8, xE9, xEA, xEB, xEC, xED, xEE, xEF, + xF0, xF1, xF2, xF3, xF4, xF5, xF6, xF7, + // </editor-fold> + xF8, xF9, xFA, xFB, xFC); + } + + @Test + public void test253() throws Throwable { + final int ARITY = 253; + System.out.println("test"+ARITY); + Object[] a = testArgs(ARITY); + Object r0 = hashArguments(a); + Object r; + r = hashArguments_253( + // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); + assertEquals(r0, r); + MethodType mt = MethodType.genericMethodType(ARITY); + MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt); + r = mh.invokeExact( + // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); + assertEquals(r0, r); + r = mh.invokeWithArguments(a); + assertEquals(r0, r); + MethodHandle ximh = MethodHandles.exactInvoker(mh.type()); + r = ximh.invokeExact(mh, + // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); + assertEquals(r0, r); + // FIXME: This next one fails, because it uses an internal invoker of arity 255. + r = ximh.invokeWithArguments(cat(mh,a)); + assertEquals(r0, r); + MethodHandle gimh = MethodHandles.invoker(mh.type()); + r = gimh.invoke(mh, + // <editor-fold defaultstate="collapsed" desc="(Number) a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> + (Number) + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); + assertEquals(r0, r); + // FIXME: This next one fails, because it uses an internal invoker of arity 255. + r = gimh.invokeWithArguments(cat(mh,a)); + assertEquals(r0, r); + mh = mh.asType(mh.type().changeParameterType(0x10, Integer.class)); + //System.out.println("type="+mh.type().toString().replaceAll("Object", "")); + r = mh.invokeExact( + // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ... (Integer) a[0x10], ..."> + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + (Integer) + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); + assertEquals(r0, r); + r = mh.invoke( + // <editor-fold defaultstate="collapsed" desc="(Comparable) a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> + (Comparable<?>) + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); + assertEquals(r0, r); + } + + static Object hashArguments_254( + // <editor-fold defaultstate="collapsed" desc="Object x00, Object x01, Object x02, Object x03, Object x04, ..."> + Object x00, Object x01, Object x02, Object x03, Object x04, Object x05, Object x06, Object x07, + Object x08, Object x09, Object x0A, Object x0B, Object x0C, Object x0D, Object x0E, Object x0F, + Object x10, Object x11, Object x12, Object x13, Object x14, Object x15, Object x16, Object x17, + Object x18, Object x19, Object x1A, Object x1B, Object x1C, Object x1D, Object x1E, Object x1F, + Object x20, Object x21, Object x22, Object x23, Object x24, Object x25, Object x26, Object x27, + Object x28, Object x29, Object x2A, Object x2B, Object x2C, Object x2D, Object x2E, Object x2F, + Object x30, Object x31, Object x32, Object x33, Object x34, Object x35, Object x36, Object x37, + Object x38, Object x39, Object x3A, Object x3B, Object x3C, Object x3D, Object x3E, Object x3F, + Object x40, Object x41, Object x42, Object x43, Object x44, Object x45, Object x46, Object x47, + Object x48, Object x49, Object x4A, Object x4B, Object x4C, Object x4D, Object x4E, Object x4F, + Object x50, Object x51, Object x52, Object x53, Object x54, Object x55, Object x56, Object x57, + Object x58, Object x59, Object x5A, Object x5B, Object x5C, Object x5D, Object x5E, Object x5F, + Object x60, Object x61, Object x62, Object x63, Object x64, Object x65, Object x66, Object x67, + Object x68, Object x69, Object x6A, Object x6B, Object x6C, Object x6D, Object x6E, Object x6F, + Object x70, Object x71, Object x72, Object x73, Object x74, Object x75, Object x76, Object x77, + Object x78, Object x79, Object x7A, Object x7B, Object x7C, Object x7D, Object x7E, Object x7F, + Object x80, Object x81, Object x82, Object x83, Object x84, Object x85, Object x86, Object x87, + Object x88, Object x89, Object x8A, Object x8B, Object x8C, Object x8D, Object x8E, Object x8F, + Object x90, Object x91, Object x92, Object x93, Object x94, Object x95, Object x96, Object x97, + Object x98, Object x99, Object x9A, Object x9B, Object x9C, Object x9D, Object x9E, Object x9F, + Object xA0, Object xA1, Object xA2, Object xA3, Object xA4, Object xA5, Object xA6, Object xA7, + Object xA8, Object xA9, Object xAA, Object xAB, Object xAC, Object xAD, Object xAE, Object xAF, + Object xB0, Object xB1, Object xB2, Object xB3, Object xB4, Object xB5, Object xB6, Object xB7, + Object xB8, Object xB9, Object xBA, Object xBB, Object xBC, Object xBD, Object xBE, Object xBF, + Object xC0, Object xC1, Object xC2, Object xC3, Object xC4, Object xC5, Object xC6, Object xC7, + Object xC8, Object xC9, Object xCA, Object xCB, Object xCC, Object xCD, Object xCE, Object xCF, + Object xD0, Object xD1, Object xD2, Object xD3, Object xD4, Object xD5, Object xD6, Object xD7, + Object xD8, Object xD9, Object xDA, Object xDB, Object xDC, Object xDD, Object xDE, Object xDF, + Object xE0, Object xE1, Object xE2, Object xE3, Object xE4, Object xE5, Object xE6, Object xE7, + Object xE8, Object xE9, Object xEA, Object xEB, Object xEC, Object xED, Object xEE, Object xEF, + Object xF0, Object xF1, Object xF2, Object xF3, Object xF4, Object xF5, Object xF6, Object xF7, + // </editor-fold> + Object xF8, Object xF9, Object xFA, Object xFB, Object xFC, Object xFD) { + return Objects.hash( + // <editor-fold defaultstate="collapsed" desc="x00, x01, x02, x03, x04, ..."> + x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x0A, x0B, x0C, x0D, x0E, x0F, + x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x1A, x1B, x1C, x1D, x1E, x1F, + x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x2A, x2B, x2C, x2D, x2E, x2F, + x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x3A, x3B, x3C, x3D, x3E, x3F, + x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x4A, x4B, x4C, x4D, x4E, x4F, + x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x5A, x5B, x5C, x5D, x5E, x5F, + x60, x61, x62, x63, x64, x65, x66, x67, x68, x69, x6A, x6B, x6C, x6D, x6E, x6F, + x70, x71, x72, x73, x74, x75, x76, x77, x78, x79, x7A, x7B, x7C, x7D, x7E, x7F, + x80, x81, x82, x83, x84, x85, x86, x87, x88, x89, x8A, x8B, x8C, x8D, x8E, x8F, + x90, x91, x92, x93, x94, x95, x96, x97, x98, x99, x9A, x9B, x9C, x9D, x9E, x9F, + xA0, xA1, xA2, xA3, xA4, xA5, xA6, xA7, xA8, xA9, xAA, xAB, xAC, xAD, xAE, xAF, + xB0, xB1, xB2, xB3, xB4, xB5, xB6, xB7, xB8, xB9, xBA, xBB, xBC, xBD, xBE, xBF, + xC0, xC1, xC2, xC3, xC4, xC5, xC6, xC7, xC8, xC9, xCA, xCB, xCC, xCD, xCE, xCF, + xD0, xD1, xD2, xD3, xD4, xD5, xD6, xD7, xD8, xD9, xDA, xDB, xDC, xDD, xDE, xDF, + xE0, xE1, xE2, xE3, xE4, xE5, xE6, xE7, xE8, xE9, xEA, xEB, xEC, xED, xEE, xEF, + xF0, xF1, xF2, xF3, xF4, xF5, xF6, xF7, + // </editor-fold> + xF8, xF9, xFA, xFB, xFC, xFD); + } + + @Test + public void test254() throws Throwable { + final int ARITY = 254; + System.out.println("test"+ARITY); + Object[] a = testArgs(ARITY); + Object r0 = hashArguments(a); + Object r; + r = hashArguments_254( + // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); + assertEquals(r0, r); + MethodType mt = MethodType.genericMethodType(ARITY); + MethodHandle mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt); + r = mh.invokeExact( + // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); + assertEquals(r0, r); + // FIXME: This next one fails, because it uses an internal invoker of arity 255. + r = mh.invokeWithArguments(a); + assertEquals(r0, r); + try { + MethodHandle ximh = MethodHandles.exactInvoker(mh.type()); + throw new AssertionError("should have thrown IAE; cannot have 1+1+254 arguments"); + } catch (IllegalArgumentException ex) { + System.out.println("OK: "+ex); + } + mh = mh.asType(mh.type().changeParameterType(0x10, Integer.class)); + //System.out.println("type="+mh.type().toString().replaceAll("Object", "")); + r = mh.invokeExact( + // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ... (Integer) a[0x10], ..."> + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + (Integer) + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); + assertEquals(r0, r); + mh = mh.asType(mh.type().changeParameterType(0xE0, Number.class)); + //System.out.println("type="+mh.type().toString().replaceAll("Object", "")); + r = mh.invokeExact( + // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ... (Integer) a[0x10], ... (Number) a[0xE0], ..."> + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + (Integer) + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + (Number) + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); + assertEquals(r0, r); + r = mh.invoke( + // <editor-fold defaultstate="collapsed" desc="(Comparable) a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> + (Comparable<?>) + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); + assertEquals(r0, r); + } + + static Object hashArguments_255( + // <editor-fold defaultstate="collapsed" desc="Object x00, Object x01, Object x02, Object x03, Object x04, ..."> + Object x00, Object x01, Object x02, Object x03, Object x04, Object x05, Object x06, Object x07, + Object x08, Object x09, Object x0A, Object x0B, Object x0C, Object x0D, Object x0E, Object x0F, + Object x10, Object x11, Object x12, Object x13, Object x14, Object x15, Object x16, Object x17, + Object x18, Object x19, Object x1A, Object x1B, Object x1C, Object x1D, Object x1E, Object x1F, + Object x20, Object x21, Object x22, Object x23, Object x24, Object x25, Object x26, Object x27, + Object x28, Object x29, Object x2A, Object x2B, Object x2C, Object x2D, Object x2E, Object x2F, + Object x30, Object x31, Object x32, Object x33, Object x34, Object x35, Object x36, Object x37, + Object x38, Object x39, Object x3A, Object x3B, Object x3C, Object x3D, Object x3E, Object x3F, + Object x40, Object x41, Object x42, Object x43, Object x44, Object x45, Object x46, Object x47, + Object x48, Object x49, Object x4A, Object x4B, Object x4C, Object x4D, Object x4E, Object x4F, + Object x50, Object x51, Object x52, Object x53, Object x54, Object x55, Object x56, Object x57, + Object x58, Object x59, Object x5A, Object x5B, Object x5C, Object x5D, Object x5E, Object x5F, + Object x60, Object x61, Object x62, Object x63, Object x64, Object x65, Object x66, Object x67, + Object x68, Object x69, Object x6A, Object x6B, Object x6C, Object x6D, Object x6E, Object x6F, + Object x70, Object x71, Object x72, Object x73, Object x74, Object x75, Object x76, Object x77, + Object x78, Object x79, Object x7A, Object x7B, Object x7C, Object x7D, Object x7E, Object x7F, + Object x80, Object x81, Object x82, Object x83, Object x84, Object x85, Object x86, Object x87, + Object x88, Object x89, Object x8A, Object x8B, Object x8C, Object x8D, Object x8E, Object x8F, + Object x90, Object x91, Object x92, Object x93, Object x94, Object x95, Object x96, Object x97, + Object x98, Object x99, Object x9A, Object x9B, Object x9C, Object x9D, Object x9E, Object x9F, + Object xA0, Object xA1, Object xA2, Object xA3, Object xA4, Object xA5, Object xA6, Object xA7, + Object xA8, Object xA9, Object xAA, Object xAB, Object xAC, Object xAD, Object xAE, Object xAF, + Object xB0, Object xB1, Object xB2, Object xB3, Object xB4, Object xB5, Object xB6, Object xB7, + Object xB8, Object xB9, Object xBA, Object xBB, Object xBC, Object xBD, Object xBE, Object xBF, + Object xC0, Object xC1, Object xC2, Object xC3, Object xC4, Object xC5, Object xC6, Object xC7, + Object xC8, Object xC9, Object xCA, Object xCB, Object xCC, Object xCD, Object xCE, Object xCF, + Object xD0, Object xD1, Object xD2, Object xD3, Object xD4, Object xD5, Object xD6, Object xD7, + Object xD8, Object xD9, Object xDA, Object xDB, Object xDC, Object xDD, Object xDE, Object xDF, + Object xE0, Object xE1, Object xE2, Object xE3, Object xE4, Object xE5, Object xE6, Object xE7, + Object xE8, Object xE9, Object xEA, Object xEB, Object xEC, Object xED, Object xEE, Object xEF, + Object xF0, Object xF1, Object xF2, Object xF3, Object xF4, Object xF5, Object xF6, Object xF7, + // </editor-fold> + Object xF8, Object xF9, Object xFA, Object xFB, Object xFC, Object xFD, Object xFE) { + return Objects.hash( + // <editor-fold defaultstate="collapsed" desc="x00, x01, x02, x03, x04, ..."> + x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x0A, x0B, x0C, x0D, x0E, x0F, + x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x1A, x1B, x1C, x1D, x1E, x1F, + x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x2A, x2B, x2C, x2D, x2E, x2F, + x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x3A, x3B, x3C, x3D, x3E, x3F, + x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x4A, x4B, x4C, x4D, x4E, x4F, + x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x5A, x5B, x5C, x5D, x5E, x5F, + x60, x61, x62, x63, x64, x65, x66, x67, x68, x69, x6A, x6B, x6C, x6D, x6E, x6F, + x70, x71, x72, x73, x74, x75, x76, x77, x78, x79, x7A, x7B, x7C, x7D, x7E, x7F, + x80, x81, x82, x83, x84, x85, x86, x87, x88, x89, x8A, x8B, x8C, x8D, x8E, x8F, + x90, x91, x92, x93, x94, x95, x96, x97, x98, x99, x9A, x9B, x9C, x9D, x9E, x9F, + xA0, xA1, xA2, xA3, xA4, xA5, xA6, xA7, xA8, xA9, xAA, xAB, xAC, xAD, xAE, xAF, + xB0, xB1, xB2, xB3, xB4, xB5, xB6, xB7, xB8, xB9, xBA, xBB, xBC, xBD, xBE, xBF, + xC0, xC1, xC2, xC3, xC4, xC5, xC6, xC7, xC8, xC9, xCA, xCB, xCC, xCD, xCE, xCF, + xD0, xD1, xD2, xD3, xD4, xD5, xD6, xD7, xD8, xD9, xDA, xDB, xDC, xDD, xDE, xDF, + xE0, xE1, xE2, xE3, xE4, xE5, xE6, xE7, xE8, xE9, xEA, xEB, xEC, xED, xEE, xEF, + xF0, xF1, xF2, xF3, xF4, xF5, xF6, xF7, + // </editor-fold> + xF8, xF9, xFA, xFB, xFC, xFD, xFE); + } + + @Test + public void test255() throws Throwable { + final int ARITY = 255; + System.out.println("test"+ARITY); + Object[] a = testArgs(ARITY); + Object r0 = hashArguments(a); + Object r; + r = hashArguments_255( + // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD], a[0xFE]); + assertEquals(r0, r); + MethodType mt = MethodType.genericMethodType(ARITY); + MethodHandle mh; + try { + mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+ARITY, mt); + throw new AssertionError("should not create an arity 255 method handle"); + } catch (IllegalArgumentException ex) { + System.out.println("OK: "+ex); + mh = MethodHandles.lookup().findStatic(BigArityTest.class, "hashArguments_"+(ARITY-1), mt.dropParameterTypes(ARITY-1, ARITY)); + } + try { + r = mh.invokeExact( + // <editor-fold defaultstate="collapsed" desc="a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], ..."> + a[0x00], a[0x01], a[0x02], a[0x03], a[0x04], a[0x05], a[0x06], a[0x07], a[0x08], a[0x09], a[0x0A], a[0x0B], a[0x0C], a[0x0D], a[0x0E], a[0x0F], + a[0x10], a[0x11], a[0x12], a[0x13], a[0x14], a[0x15], a[0x16], a[0x17], a[0x18], a[0x19], a[0x1A], a[0x1B], a[0x1C], a[0x1D], a[0x1E], a[0x1F], + a[0x20], a[0x21], a[0x22], a[0x23], a[0x24], a[0x25], a[0x26], a[0x27], a[0x28], a[0x29], a[0x2A], a[0x2B], a[0x2C], a[0x2D], a[0x2E], a[0x2F], + a[0x30], a[0x31], a[0x32], a[0x33], a[0x34], a[0x35], a[0x36], a[0x37], a[0x38], a[0x39], a[0x3A], a[0x3B], a[0x3C], a[0x3D], a[0x3E], a[0x3F], + a[0x40], a[0x41], a[0x42], a[0x43], a[0x44], a[0x45], a[0x46], a[0x47], a[0x48], a[0x49], a[0x4A], a[0x4B], a[0x4C], a[0x4D], a[0x4E], a[0x4F], + a[0x50], a[0x51], a[0x52], a[0x53], a[0x54], a[0x55], a[0x56], a[0x57], a[0x58], a[0x59], a[0x5A], a[0x5B], a[0x5C], a[0x5D], a[0x5E], a[0x5F], + a[0x60], a[0x61], a[0x62], a[0x63], a[0x64], a[0x65], a[0x66], a[0x67], a[0x68], a[0x69], a[0x6A], a[0x6B], a[0x6C], a[0x6D], a[0x6E], a[0x6F], + a[0x70], a[0x71], a[0x72], a[0x73], a[0x74], a[0x75], a[0x76], a[0x77], a[0x78], a[0x79], a[0x7A], a[0x7B], a[0x7C], a[0x7D], a[0x7E], a[0x7F], + a[0x80], a[0x81], a[0x82], a[0x83], a[0x84], a[0x85], a[0x86], a[0x87], a[0x88], a[0x89], a[0x8A], a[0x8B], a[0x8C], a[0x8D], a[0x8E], a[0x8F], + a[0x90], a[0x91], a[0x92], a[0x93], a[0x94], a[0x95], a[0x96], a[0x97], a[0x98], a[0x99], a[0x9A], a[0x9B], a[0x9C], a[0x9D], a[0x9E], a[0x9F], + a[0xA0], a[0xA1], a[0xA2], a[0xA3], a[0xA4], a[0xA5], a[0xA6], a[0xA7], a[0xA8], a[0xA9], a[0xAA], a[0xAB], a[0xAC], a[0xAD], a[0xAE], a[0xAF], + a[0xB0], a[0xB1], a[0xB2], a[0xB3], a[0xB4], a[0xB5], a[0xB6], a[0xB7], a[0xB8], a[0xB9], a[0xBA], a[0xBB], a[0xBC], a[0xBD], a[0xBE], a[0xBF], + a[0xC0], a[0xC1], a[0xC2], a[0xC3], a[0xC4], a[0xC5], a[0xC6], a[0xC7], a[0xC8], a[0xC9], a[0xCA], a[0xCB], a[0xCC], a[0xCD], a[0xCE], a[0xCF], + a[0xD0], a[0xD1], a[0xD2], a[0xD3], a[0xD4], a[0xD5], a[0xD6], a[0xD7], a[0xD8], a[0xD9], a[0xDA], a[0xDB], a[0xDC], a[0xDD], a[0xDE], a[0xDF], + a[0xE0], a[0xE1], a[0xE2], a[0xE3], a[0xE4], a[0xE5], a[0xE6], a[0xE7], a[0xE8], a[0xE9], a[0xEA], a[0xEB], a[0xEC], a[0xED], a[0xEE], a[0xEF], + a[0xF0], a[0xF1], a[0xF2], a[0xF3], a[0xF4], a[0xF5], a[0xF6], a[0xF7], + // </editor-fold> + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD], a[0xFE]); + throw new AssertionError("should not call an arity 255 method handle"); + } catch (LinkageError ex) { + System.out.println("OK: "+ex); + } + try { + MethodHandle ximh = MethodHandles.exactInvoker(mt); + throw new AssertionError("should have thrown IAE; cannot have 1+1+255 arguments"); + } catch (IllegalArgumentException ex) { + System.out.println("OK: "+ex); + } + } +} diff --git a/jdk/test/java/lang/invoke/MaxTest.java b/jdk/test/java/lang/invoke/MaxTest.java deleted file mode 100644 index e9078571392..00000000000 --- a/jdk/test/java/lang/invoke/MaxTest.java +++ /dev/null @@ -1,143 +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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 - * @summary BoundMethodHandle tests with primitive types - * @compile MaxTest.java - * @run junit/othervm test.java.lang.invoke.MaxTest - */ - -package test.java.lang.invoke; - -import static org.junit.Assert.assertEquals; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import org.junit.Test; - -public class MaxTest { - - static MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); - - private MethodHandle getMax(Class<?> t) throws Throwable { - return LOOKUP.findStatic(Math.class, "max", MethodType.methodType(t, t, t)); - } - - static int ITERATION_COUNT = 40000; - static { - String iterations = System.getProperty(MaxTest.class.getSimpleName() + ".ITERATION_COUNT"); - if (iterations == null) { - iterations = System.getProperty(MaxTest.class.getName() + ".ITERATION_COUNT"); - } - if (iterations != null) { - ITERATION_COUNT = Integer.parseInt(iterations); - } - } - - @Test - public void testMaxLong() throws Throwable { - final Class<?> C = long.class; - final long P = 23L; - final long Q = 42L; - final long R = Math.max(P, Q); - for (int i = 0; i < ITERATION_COUNT; ++i) { - MethodHandle h = getMax(C); - assertEquals((long) h.invokeExact(P, Q), R); - MethodHandle bh = MethodHandles.insertArguments(h, 0, P); - assertEquals((long) bh.invokeExact(Q), R); - MethodHandle bbh = MethodHandles.insertArguments(bh, 0, Q); - assertEquals((long) bbh.invokeExact(), R); - MethodHandle b2h = MethodHandles.insertArguments(h, 1, Q); - assertEquals((long) b2h.invokeExact(P), R); - MethodHandle bb2h = MethodHandles.insertArguments(b2h, 0, P); - assertEquals((long) bb2h.invokeExact(), R); - } - } - - @Test - public void testMaxInt() throws Throwable { - final Class<?> C = int.class; - final int P = 23; - final int Q = 42; - final int R = Math.max(P, Q); - for (int i = 0; i < ITERATION_COUNT; ++i) { - MethodHandle h = getMax(C); - assertEquals((int) h.invokeExact(P, Q), R); - MethodHandle bh = MethodHandles.insertArguments(h, 0, P); - assertEquals((int) bh.invokeExact(Q), R); - MethodHandle bbh = MethodHandles.insertArguments(bh, 0, Q); - assertEquals((int) bbh.invokeExact(), R); - MethodHandle b2h = MethodHandles.insertArguments(h, 1, Q); - assertEquals((int) b2h.invokeExact(P), R); - MethodHandle bb2h = MethodHandles.insertArguments(b2h, 0, P); - assertEquals((int) bb2h.invokeExact(), R); - } - } - - @Test - public void testMaxFloat() throws Throwable { - final Class<?> C = float.class; - final float P = 23F; - final float Q = 42F; - final float R = Math.max(P, Q); - final float D = 0.1F; - for (int i = 0; i < ITERATION_COUNT; ++i) { - MethodHandle h = getMax(C); - assertEquals((float) h.invokeExact(P, Q), R, D); - MethodHandle bh = MethodHandles.insertArguments(h, 0, P); - assertEquals((float) bh.invokeExact(Q), R, D); - MethodHandle bbh = MethodHandles.insertArguments(bh, 0, Q); - assertEquals((float) bbh.invokeExact(), R, D); - MethodHandle b2h = MethodHandles.insertArguments(h, 1, Q); - assertEquals((float) b2h.invokeExact(P), R, D); - MethodHandle bb2h = MethodHandles.insertArguments(b2h, 0, P); - assertEquals((float) bb2h.invokeExact(), R, D); - } - } - - @Test - public void testMaxDouble() throws Throwable { - final Class<?> C = double.class; - final double P = 23F; - final double Q = 42F; - final double R = Math.max(P, Q); - final double D = 0.1; - for (int i = 0; i < ITERATION_COUNT; ++i) { - MethodHandle h = getMax(C); - assertEquals((double) h.invokeExact(P, Q), R, D); - MethodHandle bh = MethodHandles.insertArguments(h, 0, P); - assertEquals((double) bh.invokeExact(Q), R, D); - MethodHandle bbh = MethodHandles.insertArguments(bh, 0, Q); - assertEquals((double) bbh.invokeExact(), R, D); - MethodHandle b2h = MethodHandles.insertArguments(h, 1, Q); - assertEquals((double) b2h.invokeExact(P), R, D); - MethodHandle bb2h = MethodHandles.insertArguments(b2h, 0, P); - assertEquals((double) bb2h.invokeExact(), R, D); - } - } - -} diff --git a/jdk/test/java/lang/invoke/MethodHandlesTest.java b/jdk/test/java/lang/invoke/MethodHandlesTest.java index 21485726ce3..aaa41a8f0db 100644 --- a/jdk/test/java/lang/invoke/MethodHandlesTest.java +++ b/jdk/test/java/lang/invoke/MethodHandlesTest.java @@ -1485,7 +1485,7 @@ public class MethodHandlesTest { RuntimeException error = null; try { target = id.asType(newType); - } catch (RuntimeException ex) { + } catch (WrongMethodTypeException ex) { error = ex; } if (verbosity >= 3) @@ -2381,47 +2381,100 @@ public class MethodHandlesTest { assertSame(thrown, caught); } - //@Test + @Test public void testInterfaceCast() throws Throwable { //if (CAN_SKIP_WORKING) return; startTest("interfaceCast"); - for (Class<?> ctype : new Class<?>[]{ Object.class, String.class, CharSequence.class, Number.class, Iterable.class}) { - testInterfaceCast(ctype, false, false); - testInterfaceCast(ctype, true, false); - testInterfaceCast(ctype, false, true); - testInterfaceCast(ctype, true, true); + assert( (((Object)"foo") instanceof CharSequence)); + assert(!(((Object)"foo") instanceof Iterable)); + for (MethodHandle mh : new MethodHandle[]{ + MethodHandles.identity(String.class), + MethodHandles.identity(CharSequence.class), + MethodHandles.identity(Iterable.class) + }) { + if (verbosity > 0) System.out.println("-- mh = "+mh); + for (Class<?> ctype : new Class<?>[]{ + Object.class, String.class, CharSequence.class, + Number.class, Iterable.class + }) { + if (verbosity > 0) System.out.println("---- ctype = "+ctype.getName()); + // doret docast + testInterfaceCast(mh, ctype, false, false); + testInterfaceCast(mh, ctype, true, false); + testInterfaceCast(mh, ctype, false, true); + testInterfaceCast(mh, ctype, true, true); + } } } - public void testInterfaceCast(Class<?> ctype, boolean doret, boolean docast) throws Throwable { - String str = "normal return value"; - MethodHandle mh = MethodHandles.identity(String.class); + private static Class<?> i2o(Class<?> c) { + return (c.isInterface() ? Object.class : c); + } + public void testInterfaceCast(MethodHandle mh, Class<?> ctype, + boolean doret, boolean docast) throws Throwable { + MethodHandle mh0 = mh; + if (verbosity > 1) + System.out.println("mh="+mh+", ctype="+ctype.getName()+", doret="+doret+", docast="+docast); + String normalRetVal = "normal return value"; MethodType mt = mh.type(); + MethodType mt0 = mt; if (doret) mt = mt.changeReturnType(ctype); else mt = mt.changeParameterType(0, ctype); if (docast) mh = MethodHandles.explicitCastArguments(mh, mt); else mh = mh.asType(mt); + assertEquals(mt, mh.type()); + MethodType mt1 = mt; // this bit is needed to make the interface types disappear for invokeWithArguments: mh = MethodHandles.explicitCastArguments(mh, mt.generic()); - boolean expectFail = !ctype.isInstance(str); - if (ctype.isInterface()) { - // special rules: interfaces slide by more frequently - if (docast || !doret) expectFail = false; + Class<?>[] step = { + mt1.parameterType(0), // param as passed to mh at first + mt0.parameterType(0), // param after incoming cast + mt0.returnType(), // return value before cast + mt1.returnType(), // return value after outgoing cast + }; + // where might a checkCast occur? + boolean[] checkCast = new boolean[step.length]; + // the string value must pass each step without causing an exception + if (!docast) { + if (!doret) { + if (step[0] != step[1]) + checkCast[1] = true; // incoming value is cast + } else { + if (step[2] != step[3]) + checkCast[3] = true; // outgoing value is cast + } } + boolean expectFail = false; + for (int i = 0; i < step.length; i++) { + Class<?> c = step[i]; + if (!checkCast[i]) c = i2o(c); + if (!c.isInstance(normalRetVal)) { + if (verbosity > 3) + System.out.println("expect failure at step "+i+" in "+Arrays.toString(step)+Arrays.toString(checkCast)); + expectFail = true; + break; + } + } + countTest(!expectFail); + if (verbosity > 2) + System.out.println("expectFail="+expectFail+", mt="+mt); Object res; try { - res = mh.invokeWithArguments(str); + res = mh.invokeWithArguments(normalRetVal); } catch (Exception ex) { res = ex; } boolean sawFail = !(res instanceof String); if (sawFail != expectFail) { - System.out.println("*** testInterfaceCast: "+mh+" was "+mt+" => "+res+(docast ? " (explicitCastArguments)" : "")); + System.out.println("*** testInterfaceCast: mh0 = "+mh0); + System.out.println(" retype using "+(docast ? "explicitCastArguments" : "asType")+" to "+mt+" => "+mh); + System.out.println(" call returned "+res); + System.out.println(" expected "+(expectFail ? "an exception" : normalRetVal)); } - if (!sawFail) { - assertFalse(res.toString(), expectFail); - assertEquals(str, res); + if (!expectFail) { + assertFalse(res.toString(), sawFail); + assertEquals(normalRetVal, res); } else { - assertTrue(res.toString(), expectFail); + assertTrue(res.toString(), sawFail); } } diff --git a/jdk/test/java/lang/invoke/PermuteArgsTest.java b/jdk/test/java/lang/invoke/PermuteArgsTest.java index 07cbbe59ec9..2e319210148 100644 --- a/jdk/test/java/lang/invoke/PermuteArgsTest.java +++ b/jdk/test/java/lang/invoke/PermuteArgsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ /* @test * @summary unit tests for method handles which permute their arguments - * @run junit/othervm -ea -esa -DPermuteArgsTest.MAX_ARITY=8 test.java.lang.invoke.PermuteArgsTest + * @run junit/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies -ea -esa -DPermuteArgsTest.MAX_ARITY=8 test.java.lang.invoke.PermuteArgsTest */ /* Examples of manual runs: * java -DPermuteArgsTest.{DRY_RUN=true,MAX_ARITY=253} test.java.lang.invoke.PermuteArgsTest @@ -191,7 +191,11 @@ public class PermuteArgsTest { pt = mt1.parameterType(mt1.parameterCount() - posArgs); mt1 = mt1.appendParameterTypes(pt); } - return mh.asType(mt1); + try { + return mh.asType(mt1); + } catch (WrongMethodTypeException | IllegalArgumentException ex) { + throw new IllegalArgumentException("cannot convert to type "+mt1+" from "+mh, ex); + } } static MethodHandle findTestMH(String name, int[] perm) throws ReflectiveOperationException { int arity = perm.length; diff --git a/jdk/test/java/lang/invoke/RicochetTest.java b/jdk/test/java/lang/invoke/RicochetTest.java index d260375ec61..342cffbbe5f 100644 --- a/jdk/test/java/lang/invoke/RicochetTest.java +++ b/jdk/test/java/lang/invoke/RicochetTest.java @@ -256,7 +256,7 @@ public class RicochetTest { //System.out.println(" expect="+expect); // now use the combined MH, and test the output: - MethodHandle mh = collectArguments(lister, pos, INT_COLLECTORS[collects]); + MethodHandle mh = collectArguments(lister, pos, int[].class, INT_COLLECTORS[collects]); if (mh == null) continue; // no infix collection, yet assert(mh.type().parameterCount() == inputs); Object observe = mh.asSpreader(int[].class, args.length).invokeExact(args); @@ -266,13 +266,53 @@ public class RicochetTest { } } - private static MethodHandle collectArguments(MethodHandle lister, int pos, MethodHandle collector) { + @Test + public void testByteCollects() throws Throwable { + if (!startTest("testByteCollects")) return; + for (MethodHandle lister : BYTE_LISTERS) { + int outputs = lister.type().parameterCount(); + for (int collects = 0; collects <= Math.min(outputs, BYTE_COLLECTORS.length-1); collects++) { + int inputs = outputs - 1 + collects; + if (inputs < 0) continue; + for (int pos = 0; pos + collects <= inputs; pos++) { + MethodHandle collector = BYTE_COLLECTORS[collects]; + byte[] args = new byte[inputs]; + int ap = 0, arg = 31; + for (int i = 0; i < pos; i++) + args[ap++] = (byte)(arg++ + 0); + for (int i = 0; i < collects; i++) + args[ap++] = (byte)(arg++ + 10); + while (ap < args.length) + args[ap++] = (byte)(arg++ + 20); + // calculate piecemeal: + //System.out.println("testIntCollects "+Arrays.asList(lister, pos, collector)+" on "+Arrays.toString(args)); + byte[] collargs = Arrays.copyOfRange(args, pos, pos+collects); + byte coll = (byte) collector.asSpreader(byte[].class, collargs.length).invokeExact(collargs); + byte[] listargs = Arrays.copyOfRange(args, 0, outputs); + System.arraycopy(args, pos+collects, listargs, pos+1, outputs - (pos+1)); + listargs[pos] = coll; + //System.out.println(" coll="+coll+" listargs="+Arrays.toString(listargs)); + Object expect = lister.asSpreader(byte[].class, listargs.length).invokeExact(listargs); + //System.out.println(" expect="+expect); + + // now use the combined MH, and test the output: + MethodHandle mh = collectArguments(lister, pos, byte[].class, BYTE_COLLECTORS[collects]); + if (mh == null) continue; // no infix collection, yet + assert(mh.type().parameterCount() == inputs); + Object observe = mh.asSpreader(byte[].class, args.length).invokeExact(args); + assertEquals(expect, observe); + } + } + } + } + + private static MethodHandle collectArguments(MethodHandle lister, int pos, Class<?> array, MethodHandle collector) { int collects = collector.type().parameterCount(); int outputs = lister.type().parameterCount(); if (pos == outputs - 1) return MethodHandles.filterArguments(lister, pos, - collector.asSpreader(int[].class, collects)) - .asCollector(int[].class, collects); + collector.asSpreader(array, collects)) + .asCollector(array, collects); //return MethodHandles.collectArguments(lister, pos, collector); //no such animal return null; } @@ -537,6 +577,9 @@ public class RicochetTest { private static final MethodHandle[] INT_COLLECTORS = { constant(int.class, 42), opI, opI2, opI3, opI4 }; + private static final MethodHandle[] BYTE_COLLECTORS = { + constant(byte.class, (byte)42), i2b(opI), i2b(opI2), i2b(opI3), i2b(opI4) + }; private static final MethodHandle[] LONG_COLLECTORS = { constant(long.class, 42), opJ, opJ2, opJ3 }; @@ -559,21 +602,36 @@ public class RicochetTest { Collections.nCopies(8, int.class)); private static final MethodHandle list8longs = findStatic("list8longs", Object.class, Collections.nCopies(8, long.class)); - private static final MethodHandle[] INT_LISTERS, LONG_LISTERS; + private static final MethodHandle[] INT_LISTERS, LONG_LISTERS, BYTE_LISTERS; static { int listerCount = list8ints.type().parameterCount() + 1; INT_LISTERS = new MethodHandle[listerCount]; LONG_LISTERS = new MethodHandle[listerCount]; + BYTE_LISTERS = new MethodHandle[listerCount]; MethodHandle lister = list8ints; MethodHandle llister = list8longs; for (int i = listerCount - 1; ; i--) { INT_LISTERS[i] = lister; LONG_LISTERS[i] = llister; + BYTE_LISTERS[i] = i2b(lister); if (i == 0) break; lister = insertArguments(lister, i-1, 0); llister = insertArguments(llister, i-1, 0L); } } + private static MethodHandle i2b(MethodHandle mh) { + return MethodHandles.explicitCastArguments(mh, subst(mh.type(), int.class, byte.class)); + } + private static MethodType subst(MethodType mt, Class<?> from, Class<?> to) { + for (int i = 0; i < mt.parameterCount(); i++) { + if (mt.parameterType(i) == from) + mt = mt.changeParameterType(i, to); + } + if (mt.returnType() == from) + mt = mt.changeReturnType(to); + return mt; + } + private static Object convI_L(int x) { stress(); return (Object) x; } private static int convL_I(Object x) { stress(); return (int) x; } diff --git a/jdk/test/sun/invoke/util/ValueConversionsTest.java b/jdk/test/sun/invoke/util/ValueConversionsTest.java index 55e40ca5388..5b6d1bd0173 100644 --- a/jdk/test/sun/invoke/util/ValueConversionsTest.java +++ b/jdk/test/sun/invoke/util/ValueConversionsTest.java @@ -159,14 +159,8 @@ public class ValueConversionsTest { assertEquals(caster.type(), ValueConversions.identity().type()); for (Object obj : objects) { Class<?> src = obj.getClass(); - boolean canCast; - if (dst.isInterface()) { - canCast = true; - } else { - canCast = dst.isAssignableFrom(src); - assertEquals(canCast, dst.isInstance(obj)); - } - //System.out.println("obj="+obj+" <: dst="+dst); + boolean canCast = dst.isAssignableFrom(src); + //System.out.println("obj="+obj+" <: dst="+dst+(canCast ? " (OK)" : " (will fail)")); try { Object result = caster.invokeExact(obj); if (canCast) diff --git a/langtools/.hgtags b/langtools/.hgtags index 7447046d6b3..653073cff9c 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -175,3 +175,5 @@ b2d8a270f5f2144e14a1fe97fbda9e4391a5332e jdk8-b50 c4cd4cab2220817c88c8c139c9bfc91c36b48826 jdk8-b51 1d2db0e5eabc2eaf865986f7b7ffbf7b14b00232 jdk8-b52 d3d0b9cd76e04bf9e381b402630ac3cfe464bb38 jdk8-b53 +9cf72631baf5cb1ebd8736c5efeab7746977ea68 jdk8-b54 +e48e7e1f026b82d921433150180799898c088890 jdk8-b55 diff --git a/langtools/make/jprt.properties b/langtools/make/jprt.properties index a45932110d6..c0399ed7083 100644 --- a/langtools/make/jprt.properties +++ b/langtools/make/jprt.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 diff --git a/langtools/make/tools/anttasks/CompilePropertiesTask.java b/langtools/make/tools/anttasks/CompilePropertiesTask.java index 4615bd4bd2b..7541c9f4764 100644 --- a/langtools/make/tools/anttasks/CompilePropertiesTask.java +++ b/langtools/make/tools/anttasks/CompilePropertiesTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 diff --git a/langtools/make/tools/anttasks/GenStubsTask.java b/langtools/make/tools/anttasks/GenStubsTask.java index 7212dc1edf4..66e41394704 100644 --- a/langtools/make/tools/anttasks/GenStubsTask.java +++ b/langtools/make/tools/anttasks/GenStubsTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/make/tools/anttasks/SelectToolTask.java b/langtools/make/tools/anttasks/SelectToolTask.java index 1fe21c46f76..fb2cf49e312 100644 --- a/langtools/make/tools/anttasks/SelectToolTask.java +++ b/langtools/make/tools/anttasks/SelectToolTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/langtools/make/tools/compileproperties/CompileProperties.java b/langtools/make/tools/compileproperties/CompileProperties.java index 9a4059288a6..7ee8b88d57f 100644 --- a/langtools/make/tools/compileproperties/CompileProperties.java +++ b/langtools/make/tools/compileproperties/CompileProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, 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 diff --git a/langtools/make/tools/genstubs/GenStubs.java b/langtools/make/tools/genstubs/GenStubs.java index 95ffa021b39..ff7cbbbf7df 100644 --- a/langtools/make/tools/genstubs/GenStubs.java +++ b/langtools/make/tools/genstubs/GenStubs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java b/langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java new file mode 100644 index 00000000000..486e9b6a4a4 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java @@ -0,0 +1,294 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.sun.tools.javac.code; + +import java.util.Map; +import javax.tools.JavaFileObject; + +import com.sun.tools.javac.comp.Annotate; +import com.sun.tools.javac.comp.AttrContext; +import com.sun.tools.javac.comp.Env; +import com.sun.tools.javac.util.Assert; +import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.Log; +import com.sun.tools.javac.util.Pair; + +import static com.sun.tools.javac.code.Kinds.PCK; +import com.sun.tools.javac.util.*; + +/** + * Container for all annotations (attributes in javac) on a Symbol. + * + * This class is explicitly mutable. Its contents will change when attributes + * are annotated onto the Symbol. However this class depends on the facts that + * List (in javac) is immutable. + * + * An instance of this class can be in one of three states: + * + * NOT_STARTED indicates that the Symbol this instance belongs to have not been + * annotated (yet). Specifically if the declaration is not annotated this + * instance will never move past NOT_STARTED. You can never go back to + * NOT_STARTED. + * + * IN_PROGRESS annotations have been found on the declaration. Will be processed + * later. You can reset to IN_PROGRESS. While IN_PROGRESS you can set the list + * of attributes (and this moves out of the IN_PROGRESS state). + * + * "unnamed" this Annotations contains some attributes, possibly the final set. + * While in this state you can only prepend or append to the attributes not set + * it directly. You can also move back to the IN_PROGRESS sate using reset(). + * + * <p><b>This is NOT part of any supported API. If you write code that depends + * on this, you do so at your own risk. This code and its internal interfaces + * are subject to change or deletion without notice.</b> + */ +public class Annotations { + + private static final List<Attribute.Compound> NOT_STARTED = List.of(null); + private static final List<Attribute.Compound> IN_PROGRESS = List.of(null); + /* + * This field should never be null + */ + private List<Attribute.Compound> attributes = NOT_STARTED; + /* + * The Symbol this Annotatios belong to + */ + private final Symbol s; + + public Annotations(Symbol s) { + this.s = s; + } + + public List<Attribute.Compound> getAttributes() { + return filterSentinels(attributes); + } + + public void setAttributes(List<Attribute.Compound> a) { + Assert.check(pendingCompletion() || !isStarted()); + if (a == null) { + throw new NullPointerException(); + } + attributes = a; + } + + public void setAttributes(Annotations other) { + if (other == null) { + throw new NullPointerException(); + } + setAttributes(other.getAttributes()); + } + + public void setAttributesWithCompletion(final Annotate.AnnotateRepeatedContext ctx) { + Assert.check(pendingCompletion() || (!isStarted() && s.kind == PCK)); + + Map<Symbol.TypeSymbol, ListBuffer<Attribute.Compound>> annotated = ctx.annotated; + boolean atLeastOneRepeated = false; + List<Attribute.Compound> buf = List.<Attribute.Compound>nil(); + for (ListBuffer<Attribute.Compound> lb : annotated.values()) { + if (lb.size() == 1) { + buf = buf.prepend(lb.first()); + } else { // repeated + buf = buf.prepend(new Placeholder(lb.toList(), s)); + atLeastOneRepeated = true; + } + } + + // Add non-repeating attributes + setAttributes(buf.reverse()); + + if (atLeastOneRepeated) { + // The Symbol s is now annotated with a combination of + // finished non-repeating annotations and placeholders for + // repeating annotations. + // + // We need to do this in two passes because when creating + // a container for a repeating annotation we must + // guarantee that the @ContainedBy on the + // contained annotation is fully annotated + // + // The way we force this order is to do all repeating + // annotations in a pass after all non-repeating are + // finished. This will work because @ContainedBy + // is non-repeating and therefore will be annotated in the + // fist pass. + + // Queue a pass that will replace Attribute.Placeholders + // with Attribute.Compound (made from synthesized containers). + ctx.annotateRepeated(new Annotate.Annotator() { + + @Override + public String toString() { + return "repeated annotation pass of: " + s + " in: " + s.owner; + } + + @Override + public void enterAnnotation() { + complete(ctx); + } + }); + } + } + + public Annotations reset() { + attributes = IN_PROGRESS; + return this; + } + + public boolean isEmpty() { + return !isStarted() + || pendingCompletion() + || attributes.isEmpty(); + } + + public boolean pendingCompletion() { + return attributes == IN_PROGRESS; + } + + public Annotations append(List<Attribute.Compound> l) { + attributes = filterSentinels(attributes); + + if (l.isEmpty()) { + ; // no-op + } else if (attributes.isEmpty()) { + attributes = l; + } else { + attributes = attributes.appendList(l); + } + return this; + } + + public Annotations prepend(List<Attribute.Compound> l) { + attributes = filterSentinels(attributes); + + if (l.isEmpty()) { + ; // no-op + } else if (attributes.isEmpty()) { + attributes = l; + } else { + attributes = attributes.prependList(l); + } + return this; + } + + private List<Attribute.Compound> filterSentinels(List<Attribute.Compound> a) { + return (a == IN_PROGRESS || a == NOT_STARTED) + ? List.<Attribute.Compound>nil() + : a; + } + + private boolean isStarted() { + return attributes != NOT_STARTED; + } + + private List<Attribute.Compound> getPlaceholders() { + List<Attribute.Compound> res = List.<Attribute.Compound>nil(); + for (Attribute.Compound a : filterSentinels(attributes)) { + if (a instanceof Placeholder) { + res = res.prepend(a); + } + } + return res.reverse(); + } + + /* + * Replace Placeholders for repeating annotations with their containers + */ + private void complete(Annotate.AnnotateRepeatedContext ctx) { + Assert.check(!pendingCompletion()); + Log log = ctx.log; + Env<AttrContext> env = ctx.env; + JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile); + try { + + if (isEmpty()) { + return; + } + + List<Attribute.Compound> result = List.nil(); + for (Attribute.Compound a : getAttributes()) { + if (a instanceof Placeholder) { + Attribute.Compound replacement = replaceOne((Placeholder) a, ctx); + + if (null != replacement) { + result = result.prepend(replacement); + } + } else { + result = result.prepend(a); + } + } + + attributes = result.reverse(); + + Assert.check(Annotations.this.getPlaceholders().isEmpty()); + } finally { + log.useSource(oldSource); + } + } + + private Attribute.Compound replaceOne(Placeholder placeholder, Annotate.AnnotateRepeatedContext ctx) { + Log log = ctx.log; + + // Process repeated annotations + Attribute.Compound validRepeated = + ctx.processRepeatedAnnotations(placeholder.getPlaceholderFor()); + + if (validRepeated != null) { + // Check that the container isn't manually + // present along with repeated instances of + // its contained annotation. + ListBuffer<Attribute.Compound> manualContainer = ctx.annotated.get(validRepeated.type.tsym); + if (manualContainer != null) { + log.error(ctx.pos.get(manualContainer.first()), "invalid.containedby.annotation.repeated.and.container.present", + manualContainer.first().type.tsym); + } + } + + // A null return will delete the Placeholder + return validRepeated; + + } + + private static class Placeholder extends Attribute.Compound { + + private List<Attribute.Compound> placeholderFor; + private Symbol on; + + public Placeholder(List<Attribute.Compound> placeholderFor, Symbol on) { + super(Type.noType, List.<Pair<Symbol.MethodSymbol, Attribute>>nil()); + this.placeholderFor = placeholderFor; + this.on = on; + } + + @Override + public String toString() { + return "<placeholder: " + placeholderFor + " on: " + on + ">"; + } + + public List<Attribute.Compound> getPlaceholderFor() { + return placeholderFor; + } + } +} diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java b/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java index 37bb6eebe72..0460ac9aa1e 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java @@ -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 @@ -103,11 +103,11 @@ public abstract class Attribute implements AnnotationValue { * represented as a ClassSymbol. */ public static class Class extends Attribute { - public final Type type; + public final Type classType; public void accept(Visitor v) { v.visitClass(this); } public Class(Types types, Type type) { super(makeClassType(types, type)); - this.type = type; + this.classType = type; } static Type makeClassType(Types types, Type type) { Type arg = type.isPrimitive() @@ -118,13 +118,13 @@ public abstract class Attribute implements AnnotationValue { types.syms.classType.tsym); } public String toString() { - return type + ".class"; + return classType + ".class"; } public Type getValue() { - return type; + return classType; } public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { - return v.visitType(type, p); + return v.visitType(classType, p); } } @@ -212,6 +212,12 @@ public abstract class Attribute implements AnnotationValue { super(type); this.values = values; } + + public Array(Type type, List<Attribute> values) { + super(type); + this.values = values.toArray(new Attribute[values.size()]); + } + public void accept(Visitor v) { v.visitArray(this); } public String toString() { StringBuilder buf = new StringBuilder(); diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java b/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java index 46f7bddb4be..e3ed0f35983 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, 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 @@ -70,16 +70,16 @@ public class Lint * Returns the result of combining the values in this object with * the given annotations. */ - public Lint augment(List<Attribute.Compound> attrs) { - return augmentor.augment(this, attrs); + public Lint augment(Annotations annots) { + return augmentor.augment(this, annots.getAttributes()); } /** * Returns the result of combining the values in this object with * the given annotations and flags. */ - public Lint augment(List<Attribute.Compound> attrs, long flags) { - Lint l = augmentor.augment(this, attrs); + public Lint augment(Annotations annots, long flags) { + Lint l = augmentor.augment(this, annots.getAttributes()); if ((flags & DEPRECATED) != 0) { if (l == this) l = new Lint(this); diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java index 5abee40481a..e17d1a1fa81 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java @@ -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 @@ -203,6 +203,9 @@ public enum Source { public boolean allowEffectivelyFinalInInnerClasses() { return compareTo(JDK1_8) >= 0; } + public boolean allowRepeatedAnnotations() { + return compareTo(JDK1_8) >= 0; + } public static SourceVersion toSourceVersion(Source source) { switch(source) { case JDK1_2: diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java index 238b25d09b2..fc651b4a1f3 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java @@ -72,22 +72,24 @@ public abstract class Symbol implements Element { */ public long flags() { return flags_field; } - /** The attributes of this symbol. + /** The attributes of this symbol are contained in this + * Annotations. The Annotations instance is NOT immutable. */ - public List<Attribute.Compound> attributes_field; + public final Annotations annotations = new Annotations(this); /** An accessor method for the attributes of this symbol. * Attributes of class symbols should be accessed through the accessor * method to make sure that the class symbol is loaded. */ public List<Attribute.Compound> getAnnotationMirrors() { - return Assert.checkNonNull(attributes_field); + return Assert.checkNonNull(annotations.getAttributes()); } /** Fetch a particular annotation from a symbol. */ public Attribute.Compound attribute(Symbol anno) { - for (Attribute.Compound a : getAnnotationMirrors()) + for (Attribute.Compound a : getAnnotationMirrors()) { if (a.type.tsym == anno) return a; + } return null; } @@ -120,7 +122,6 @@ public abstract class Symbol implements Element { this.owner = owner; this.completer = null; this.erasure_field = null; - this.attributes_field = List.nil(); this.name = name; } @@ -657,10 +658,11 @@ public abstract class Symbol implements Element { if (completer != null) complete(); if (package_info != null && package_info.completer != null) { package_info.complete(); - if (attributes_field.isEmpty()) - attributes_field = package_info.attributes_field; + if (annotations.isEmpty()) { + annotations.setAttributes(package_info.annotations); } - return Assert.checkNonNull(attributes_field); + } + return Assert.checkNonNull(annotations.getAttributes()); } /** A package "exists" if a type or package that exists has @@ -762,7 +764,7 @@ public abstract class Symbol implements Element { public List<Attribute.Compound> getAnnotationMirrors() { if (completer != null) complete(); - return Assert.checkNonNull(attributes_field); + return Assert.checkNonNull(annotations.getAttributes()); } public Type erasure(Types types) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java index 31cb45e9622..7b35ad53784 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java @@ -156,6 +156,10 @@ public class Symtab { public final Type systemType; public final Type autoCloseableType; public final Type trustMeType; + public final Type containedByType; + public final Type containerForType; + public final Type documentedType; + public final Type elementTypeType; /** The symbol representing the length field of an array. */ @@ -468,6 +472,10 @@ public class Symtab { deprecatedType = enterClass("java.lang.Deprecated"); suppressWarningsType = enterClass("java.lang.SuppressWarnings"); inheritedType = enterClass("java.lang.annotation.Inherited"); + containedByType = enterClass("java.lang.annotation.ContainedBy"); + containerForType = enterClass("java.lang.annotation.ContainerFor"); + documentedType = enterClass("java.lang.annotation.Documented"); + elementTypeType = enterClass("java.lang.annotation.ElementType"); systemType = enterClass("java.lang.System"); autoCloseableType = enterClass("java.lang.AutoCloseable"); autoCloseableClose = new MethodSymbol(PUBLIC, diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java index a9cda5fe855..b4094d41acc 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java @@ -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 diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java index 1039a287104..4fdfd4d1ef8 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java @@ -1358,6 +1358,20 @@ public class Types { } return result; } + + /** + * Returns an ArrayType with the component type t + * + * @param t The component type of the ArrayType + * @return the ArrayType for the given component + */ + public ArrayType makeArrayType(Type t) { + if (t.tag == VOID || + t.tag >= PACKAGE) { + Assert.error("Type t must not be a a VOID or PACKAGE type, " + t.toString()); + } + return new ArrayType(t, syms.arrayClass); + } // </editor-fold> // <editor-fold defaultstate="collapsed" desc="asSuper"> @@ -1589,9 +1603,16 @@ public class Types { * type parameters in t are deleted. */ public Type erasure(Type t) { - return erasure(t, false); + return eraseNotNeeded(t)? t : erasure(t, false); } //where + private boolean eraseNotNeeded(Type t) { + // We don't want to erase primitive types and String type as that + // operation is idempotent. Also, erasing these could result in loss + // of information such as constant values attached to such types. + return (t.tag <= lastBaseTag) || (syms.stringType.tsym == t.tsym); + } + private Type erasure(Type t, boolean recurse) { if (t.tag <= lastBaseTag) return t; /* fast special case */ @@ -3804,8 +3825,12 @@ public class Types { // <editor-fold defaultstate="collapsed" desc="Annotation support"> public RetentionPolicy getRetention(Attribute.Compound a) { + return getRetention(a.type.tsym); + } + + public RetentionPolicy getRetention(Symbol sym) { RetentionPolicy vis = RetentionPolicy.CLASS; // the default - Attribute.Compound c = a.type.tsym.attribute(syms.retentionType.tsym); + Attribute.Compound c = sym.attribute(syms.retentionType.tsym); if (c != null) { Attribute value = c.member(names.value); if (value != null && value instanceof Attribute.Enum) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java index 724481e54ae..eae5e943c23 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Annotate.java @@ -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 @@ -25,7 +25,11 @@ package com.sun.tools.javac.comp; +import java.util.Map; +import java.util.Objects; + import com.sun.tools.javac.util.*; +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.tree.*; @@ -83,8 +87,9 @@ public class Annotate { private int enterCount = 0; ListBuffer<Annotator> q = new ListBuffer<Annotator>(); + ListBuffer<Annotator> repeatedQ = new ListBuffer<Annotator>(); - public void later(Annotator a) { + public void normal(Annotator a) { q.append(a); } @@ -92,6 +97,10 @@ public class Annotate { q.prepend(a); } + public void repeated(Annotator a) { + repeatedQ.append(a); + } + /** Called when the Enter phase starts. */ public void enterStart() { enterCount++; @@ -109,6 +118,10 @@ public class Annotate { try { while (q.nonEmpty()) q.next().enterAnnotation(); + + while (repeatedQ.nonEmpty()) { + repeatedQ.next().enterAnnotation(); + } } finally { enterCount--; } @@ -124,6 +137,53 @@ public class Annotate { String toString(); } + /** + * This context contains all the information needed to synthesize new + * annotations trees by the completer for repeating annotations. + */ + public class AnnotateRepeatedContext { + public final Env<AttrContext> env; + public final Map<Symbol.TypeSymbol, ListBuffer<Attribute.Compound>> annotated; + public final Map<Attribute.Compound, JCDiagnostic.DiagnosticPosition> pos; + public final Log log; + + public AnnotateRepeatedContext(Env<AttrContext> env, + Map<Symbol.TypeSymbol, ListBuffer<Attribute.Compound>> annotated, + Map<Attribute.Compound, JCDiagnostic.DiagnosticPosition> pos, + Log log) { + Objects.requireNonNull(env); + Objects.requireNonNull(annotated); + Objects.requireNonNull(pos); + Objects.requireNonNull(log); + + this.env = env; + this.annotated = annotated; + this.pos = pos; + this.log = log; + } + + /** + * Process a list of repeating annotations returning a new + * Attribute.Compound that is the attribute for the synthesized tree + * for the container. + * + * @param repeatingAnnotations a List of repeating annotations + * @return a new Attribute.Compound that is the container for the repeatingAnnotations + */ + public Attribute.Compound processRepeatedAnnotations(List<Attribute.Compound> repeatingAnnotations) { + return Annotate.this.processRepeatedAnnotations(repeatingAnnotations, this); + } + + /** + * Queue the Annotator a on the repeating annotations queue of the + * Annotate instance this context belongs to. + * + * @param a the Annotator to enqueue for repeating annotation annotating + */ + public void annotateRepeated(Annotator a) { + Annotate.this.repeated(a); + } + } /* ******************************************************************** * Compute an attribute from its annotation. @@ -268,4 +328,219 @@ public class Annotate { log.error(tree.pos(), "annotation.value.not.allowable.type"); return new Attribute.Error(attr.attribExpr(tree, env, expected)); } + + /* ********************************* + * Support for repeating annotations + ***********************************/ + + /* Process repeated annotations. This method returns the + * synthesized container annotation or null IFF all repeating + * annotation are invalid. This method reports errors/warnings. + */ + private Attribute.Compound processRepeatedAnnotations(List<Attribute.Compound> annotations, + AnnotateRepeatedContext ctx) { + Attribute.Compound firstOccurrence = annotations.head; + List<Attribute> repeated = List.nil(); + Type origAnnoType; + Type arrayOfOrigAnnoType = null; + Type targetContainerType = null; + MethodSymbol containerValueSymbol = null; + + Assert.check(!annotations.isEmpty() && + !annotations.tail.isEmpty()); // i.e. size() > 1 + + for (List<Attribute.Compound> al = annotations; + !al.isEmpty(); + al = al.tail) + { + Attribute.Compound currentAnno = al.head; + + origAnnoType = currentAnno.type; + if (arrayOfOrigAnnoType == null) { + arrayOfOrigAnnoType = types.makeArrayType(origAnnoType); +} + + Type currentContainerType = getContainingType(currentAnno, ctx.pos.get(currentAnno)); + if (currentContainerType == null) { + continue; + } + // Assert that the target Container is == for all repeated + // annos of the same annotation type, the types should + // come from the same Symbol, i.e. be '==' + Assert.check(targetContainerType == null || currentContainerType == targetContainerType); + targetContainerType = currentContainerType; + + containerValueSymbol = validateContainer(targetContainerType, origAnnoType, ctx.pos.get(currentAnno)); + + if (containerValueSymbol == null) { // Check of CA type failed + // errors are already reported + continue; + } + + repeated = repeated.prepend(currentAnno); + } + + if (!repeated.isEmpty()) { + repeated = repeated.reverse(); + JCAnnotation annoTree; + TreeMaker m = make.at(ctx.pos.get(firstOccurrence)); + Pair<MethodSymbol, Attribute> p = + new Pair<MethodSymbol, Attribute>(containerValueSymbol, + new Attribute.Array(arrayOfOrigAnnoType, repeated)); + annoTree = m.Annotation(new Attribute.Compound(targetContainerType, + List.of(p))); + Attribute.Compound c = enterAnnotation(annoTree, + targetContainerType, + ctx.env); + return c; + } else { + return null; // errors should have been reported elsewhere + } + } + + /** Fetches the actual Type that should be the containing annotation. */ + private Type getContainingType(Attribute.Compound currentAnno, + DiagnosticPosition pos) + { + Type origAnnoType = currentAnno.type; + TypeSymbol origAnnoDecl = origAnnoType.tsym; + + // Fetch the ContainedBy annotation from the current + // annotation's declaration, or null if it has none + Attribute.Compound ca = origAnnoDecl.attribute(syms.containedByType.tsym); + if (ca == null) { // has no ContainedBy annotation + log.error(pos, "duplicate.annotation.missing.container", origAnnoType); + return null; + } + + return filterSame(extractContainingType(ca, pos, origAnnoDecl), + origAnnoType); + } + + // returns null if t is same as 's', returns 't' otherwise + private Type filterSame(Type t, Type s) { + if (t == null || s == null) { + return t; + } + + return types.isSameType(t, s) ? null : t; + } + + /** Extract the actual Type to be used for a containing annotation. */ + private Type extractContainingType(Attribute.Compound ca, + DiagnosticPosition pos, + TypeSymbol annoDecl) + { + // The next three checks check that the ContainedBy annotation + // on the declaration of the annotation type that is repeating is + // valid. + + // ContainedBy must have at least one element + if (ca.values.isEmpty()) { + log.error(pos, "invalid.containedby.annotation", annoDecl); + return null; + } + Pair<MethodSymbol,Attribute> p = ca.values.head; + Name name = p.fst.name; + if (name != names.value) { // should contain only one element, named "value" + log.error(pos, "invalid.containedby.annotation", annoDecl); + return null; + } + if (!(p.snd instanceof Attribute.Class)) { // check that the value of "value" is an Attribute.Class + log.error(pos, "invalid.containedby.annotation", annoDecl); + return null; + } + + return ((Attribute.Class)p.snd).getValue(); + } + + /* Validate that the suggested targetContainerType Type is a valid + * container type for repeated instances of originalAnnoType + * annotations. Return null and report errors if this is not the + * case, return the MethodSymbol of the value element in + * targetContainerType if it is suitable (this is needed to + * synthesize the container). */ + private MethodSymbol validateContainer(Type targetContainerType, + Type originalAnnoType, + DiagnosticPosition pos) { + MethodSymbol containerValueSymbol = null; + boolean fatalError = false; + + // Validate that there is a (and only 1) value method + Scope scope = targetContainerType.tsym.members(); + int nr_value_elems = 0; + boolean error = false; + for(Symbol elm : scope.getElementsByName(names.value)) { + nr_value_elems++; + + if (nr_value_elems == 1 && + elm.kind == Kinds.MTH) { + containerValueSymbol = (MethodSymbol)elm; + } else { + error = true; + } + } + if (error) { + log.error(pos, + "invalid.containedby.annotation.multiple.values", + targetContainerType, + nr_value_elems); + return null; + } else if (nr_value_elems == 0) { + log.error(pos, + "invalid.containedby.annotation.no.value", + targetContainerType); + return null; + } + + // validate that the 'value' element is a method + // probably "impossible" to fail this + if (containerValueSymbol.kind != Kinds.MTH) { + log.error(pos, + "invalid.containedby.annotation.invalid.value", + targetContainerType); + fatalError = true; + } + + // validate that the 'value' element has the correct return type + // i.e. array of original anno + Type valueRetType = containerValueSymbol.type.getReturnType(); + Type expectedType = types.makeArrayType(originalAnnoType); + if (!(types.isArray(valueRetType) && + types.isSameType(expectedType, valueRetType))) { + log.error(pos, + "invalid.containedby.annotation.value.return", + targetContainerType, + valueRetType, + expectedType); + fatalError = true; + } + + // validate that all other elements of containing type has defaults + scope = targetContainerType.tsym.members(); + error = false; + for(Symbol elm : scope.getElements()) { + if (elm.name != names.value && + elm.kind == Kinds.MTH && + ((MethodSymbol)elm).defaultValue == null) { + log.error(pos, + "invalid.containedby.annotation.elem.nondefault", + targetContainerType, + elm); + containerValueSymbol = null; + error = true; + } + } + if (error) { + fatalError = true; + } + + // Explicitly no check for/validity of @ContainerFor. That is + // done on declaration of the container, and at reflect time. + + // The rest of the conditions for a valid containing annotation are made + // in Check.validateRepeatedAnnotaton(); + + return fatalError ? null : containerValueSymbol; + } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index 180966dffaf..b9613fa31c1 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -662,10 +662,12 @@ public class Attr extends JCTree.Visitor { // env.info.enclVar.attributes_field might not yet have been evaluated, and so might be // null. In that case, calling augment will throw an NPE. To avoid this, for now we // revert to the jdk 6 behavior and ignore the (unevaluated) attributes. - if (env.info.enclVar.attributes_field == null) + if (env.info.enclVar.annotations.pendingCompletion()) { env.info.lint = lintEnv.info.lint; - else - env.info.lint = lintEnv.info.lint.augment(env.info.enclVar.attributes_field, env.info.enclVar.flags()); + } else { + env.info.lint = lintEnv.info.lint.augment(env.info.enclVar.annotations, + env.info.enclVar.flags()); + } Lint prevLint = chk.setLint(env.info.lint); JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile); @@ -776,7 +778,7 @@ public class Attr extends JCTree.Visitor { public void visitMethodDef(JCMethodDecl tree) { MethodSymbol m = tree.sym; - Lint lint = env.info.lint.augment(m.attributes_field, m.flags()); + Lint lint = env.info.lint.augment(m.annotations, m.flags()); Lint prevLint = chk.setLint(lint); MethodSymbol prevMethod = chk.setMethod(m); try { @@ -921,7 +923,7 @@ public class Attr extends JCTree.Visitor { } VarSymbol v = tree.sym; - Lint lint = env.info.lint.augment(v.attributes_field, v.flags()); + Lint lint = env.info.lint.augment(v.annotations, v.flags()); Lint prevLint = chk.setLint(lint); // Check that the variable's declared type is well-formed. @@ -3069,7 +3071,7 @@ public class Attr extends JCTree.Visitor { lintEnv = lintEnv.next; // Having found the enclosing lint value, we can initialize the lint value for this class - env.info.lint = lintEnv.info.lint.augment(c.attributes_field, c.flags()); + env.info.lint = lintEnv.info.lint.augment(c.annotations, c.flags()); Lint prevLint = chk.setLint(env.info.lint); JavaFileObject prev = log.useSource(c.sourcefile); @@ -3133,6 +3135,26 @@ public class Attr extends JCTree.Visitor { if (tree.typarams.nonEmpty()) log.error(tree.typarams.head.pos(), "intf.annotation.cant.have.type.params"); + + // If this annotation has a @ContainedBy, validate + Attribute.Compound containedBy = c.attribute(syms.containedByType.tsym); + if (containedBy != null) { + // get diagnositc position for error reporting + DiagnosticPosition cbPos = getDiagnosticPosition(tree, containedBy.type); + Assert.checkNonNull(cbPos); + + chk.validateContainedBy(c, containedBy, cbPos); + } + + // If this annotation has a @ContainerFor, validate + Attribute.Compound containerFor = c.attribute(syms.containerForType.tsym); + if (containerFor != null) { + // get diagnositc position for error reporting + DiagnosticPosition cfPos = getDiagnosticPosition(tree, containerFor.type); + Assert.checkNonNull(cfPos); + + chk.validateContainerFor(c, containerFor, cfPos); + } } else { // Check that all extended classes and interfaces // are compatible (i.e. no two define methods with same arguments @@ -3194,6 +3216,16 @@ public class Attr extends JCTree.Visitor { } } // where + /** get a diagnostic position for an attribute of Type t, or null if attribute missing */ + private DiagnosticPosition getDiagnosticPosition(JCClassDecl tree, Type t) { + for(List<JCAnnotation> al = tree.mods.annotations; !al.isEmpty(); al = al.tail) { + if (types.isSameType(al.head.annotationType.type, t)) + return al.head.pos(); + } + + return null; + } + /** check if a class is a subtype of Serializable, if that is available. */ private boolean isSerializable(ClassSymbol c) { try { diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/AttrContext.java b/langtools/src/share/classes/com/sun/tools/javac/comp/AttrContext.java index 15c426ed89f..017d6bcf2c0 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/AttrContext.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/AttrContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2008, 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 diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index ac18d9f0b42..627258727c1 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -69,7 +69,6 @@ public class Check { private final Infer infer; private final Types types; private final JCDiagnostic.Factory diags; - private final boolean skipAnnotations; private boolean warnOnSyntheticConflicts; private boolean suppressAbortOnBadClassFile; private boolean enableSunApiLintControl; @@ -113,7 +112,6 @@ public class Check { allowCovariantReturns = source.allowCovariantReturns(); allowSimplifiedVarargs = source.allowSimplifiedVarargs(); complexInference = options.isSet("complexinference"); - skipAnnotations = options.isSet("skipAnnotations"); warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts"); suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile"); enableSunApiLintControl = options.isSet("enableSunApiLintControl"); @@ -2422,14 +2420,13 @@ public class Check { /** Check the annotations of a symbol. */ public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) { - if (skipAnnotations) return; for (JCAnnotation a : annotations) validateAnnotation(a, s); } /** Check an annotation of a symbol. */ - public void validateAnnotation(JCAnnotation a, Symbol s) { + private void validateAnnotation(JCAnnotation a, Symbol s) { validateAnnotationTree(a); if (!annotationApplicable(a, s)) @@ -2441,6 +2438,215 @@ public class Check { } } + /** + * Validate the proposed container 'containedBy' on the + * annotation type symbol 's'. Report errors at position + * 'pos'. + * + * @param s The (annotation)type declaration annotated with a @ContainedBy + * @param containerAnno the @ContainedBy on 's' + * @param pos where to report errors + */ + public void validateContainedBy(TypeSymbol s, Attribute.Compound containedBy, DiagnosticPosition pos) { + Assert.check(types.isSameType(containedBy.type, syms.containedByType)); + + Type t = null; + List<Pair<MethodSymbol,Attribute>> l = containedBy.values; + if (!l.isEmpty()) { + Assert.check(l.head.fst.name == names.value); + t = ((Attribute.Class)l.head.snd).getValue(); + } + + if (t == null) { + log.error(pos, "invalid.container.wrong.containedby", s, containedBy); + return; + } + + validateHasContainerFor(t.tsym, s, pos); + validateRetention(t.tsym, s, pos); + validateDocumented(t.tsym, s, pos); + validateInherited(t.tsym, s, pos); + validateTarget(t.tsym, s, pos); + } + + /** + * Validate the proposed container 'containerFor' on the + * annotation type symbol 's'. Report errors at position + * 'pos'. + * + * @param s The (annotation)type declaration annotated with a @ContainerFor + * @param containerFor the @ContainedFor on 's' + * @param pos where to report errors + */ + public void validateContainerFor(TypeSymbol s, Attribute.Compound containerFor, DiagnosticPosition pos) { + Assert.check(types.isSameType(containerFor.type, syms.containerForType)); + + Type t = null; + List<Pair<MethodSymbol,Attribute>> l = containerFor.values; + if (!l.isEmpty()) { + Assert.check(l.head.fst.name == names.value); + t = ((Attribute.Class)l.head.snd).getValue(); + } + + if (t == null) { + log.error(pos, "invalid.container.wrong.containerfor", s, containerFor); + return; + } + + validateHasContainedBy(t.tsym, s, pos); + } + + private void validateHasContainedBy(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { + Attribute.Compound containedBy = container.attribute(syms.containedByType.tsym); + + if (containedBy == null) { + log.error(pos, "invalid.container.no.containedby", container, syms.containedByType.tsym); + return; + } + + Type t = null; + List<Pair<MethodSymbol,Attribute>> l = containedBy.values; + if (!l.isEmpty()) { + Assert.check(l.head.fst.name == names.value); + t = ((Attribute.Class)l.head.snd).getValue(); + } + + if (t == null) { + log.error(pos, "invalid.container.wrong.containedby", container, contained); + return; + } + + if (!types.isSameType(t, contained.type)) + log.error(pos, "invalid.container.wrong.containedby", t.tsym, contained); + } + + private void validateHasContainerFor(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) { + Attribute.Compound containerFor = container.attribute(syms.containerForType.tsym); + + if (containerFor == null) { + log.error(pos, "invalid.container.no.containerfor", container, syms.containerForType.tsym); + return; + } + + Type t = null; + List<Pair<MethodSymbol,Attribute>> l = containerFor.values; + if (!l.isEmpty()) { + Assert.check(l.head.fst.name == names.value); + t = ((Attribute.Class)l.head.snd).getValue(); + } + + if (t == null) { + log.error(pos, "invalid.container.wrong.containerfor", container, contained); + return; + } + + if (!types.isSameType(t, contained.type)) + log.error(pos, "invalid.container.wrong.containerfor", t.tsym, contained); + } + + private void validateRetention(Symbol container, Symbol contained, DiagnosticPosition pos) { + Attribute.RetentionPolicy containerRetention = types.getRetention(container); + Attribute.RetentionPolicy containedRetention = types.getRetention(contained); + + boolean error = false; + switch (containedRetention) { + case RUNTIME: + if (containerRetention != Attribute.RetentionPolicy.RUNTIME) { + error = true; + } + break; + case CLASS: + if (containerRetention == Attribute.RetentionPolicy.SOURCE) { + error = true; + } + } + if (error ) { + log.error(pos, "invalid.containedby.annotation.retention", + container, containerRetention, + contained, containedRetention); + } + } + + private void validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos) { + if (contained.attribute(syms.documentedType.tsym) != null) { + if (container.attribute(syms.documentedType.tsym) == null) { + log.error(pos, "invalid.containedby.annotation.not.documented", container, contained); + } + } + } + + private void validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos) { + if (contained.attribute(syms.inheritedType.tsym) != null) { + if (container.attribute(syms.inheritedType.tsym) == null) { + log.error(pos, "invalid.containedby.annotation.not.inherited", container, contained); + } + } + } + + private void validateTarget(Symbol container, Symbol contained, DiagnosticPosition pos) { + Attribute.Array containedTarget = getAttributeTargetAttribute(contained); + + // If contained has no Target, we are done + if (containedTarget == null) { + return; + } + + // If contained has Target m1, container must have a Target + // annotation, m2, and m2 must be a subset of m1. (This is + // trivially true if contained has no target as per above). + + // contained has target, but container has not, error + Attribute.Array containerTarget = getAttributeTargetAttribute(container); + if (containerTarget == null) { + log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained); + return; + } + + Set<Name> containerTargets = new HashSet<Name>(); + for (Attribute app : containerTarget.values) { + if (!(app instanceof Attribute.Enum)) { + continue; // recovery + } + Attribute.Enum e = (Attribute.Enum)app; + containerTargets.add(e.value.name); + } + + Set<Name> containedTargets = new HashSet<Name>(); + for (Attribute app : containedTarget.values) { + if (!(app instanceof Attribute.Enum)) { + continue; // recovery + } + Attribute.Enum e = (Attribute.Enum)app; + containedTargets.add(e.value.name); + } + + if (!isTargetSubset(containedTargets, containerTargets)) { + log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained); + } + } + + /** Checks that t is a subset of s, with respect to ElementType + * semantics, specifically {ANNOTATION_TYPE} is a subset of {TYPE} + */ + private boolean isTargetSubset(Set<Name> s, Set<Name> t) { + // Check that all elements in t are present in s + for (Name n2 : t) { + boolean currentElementOk = false; + for (Name n1 : s) { + if (n1 == n2) { + currentElementOk = true; + break; + } else if (n1 == names.TYPE && n2 == names.ANNOTATION_TYPE) { + currentElementOk = true; + break; + } + } + if (!currentElementOk) + return false; + } + return true; + } + /** Is s a method symbol that overrides a method in a superclass? */ boolean isOverrider(Symbol s) { if (s.kind != MTH || s.isStatic()) @@ -2461,12 +2667,10 @@ public class Check { /** Is the annotation applicable to the symbol? */ boolean annotationApplicable(JCAnnotation a, Symbol s) { - Attribute.Compound atTarget = - a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym); - if (atTarget == null) return true; - Attribute atValue = atTarget.member(names.value); - if (!(atValue instanceof Attribute.Array)) return true; // error recovery - Attribute.Array arr = (Attribute.Array) atValue; + Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym); + if (arr == null) { + return true; + } for (Attribute app : arr.values) { if (!(app instanceof Attribute.Enum)) return true; // recovery Attribute.Enum e = (Attribute.Enum) app; @@ -2508,6 +2712,16 @@ public class Check { return false; } + + Attribute.Array getAttributeTargetAttribute(Symbol s) { + Attribute.Compound atTarget = + s.attribute(syms.annotationTargetType.tsym); + if (atTarget == null) return null; // ok, is applicable + Attribute atValue = atTarget.member(names.value); + if (!(atValue instanceof Attribute.Array)) return null; // error recovery + return (Attribute.Array) atValue; + } + /** Check an annotation value. */ public void validateAnnotation(JCAnnotation a) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java index 514d651be93..22e0c9231f5 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java @@ -157,7 +157,7 @@ public class Enter extends JCTree.Visitor { Env<AttrContext> lintEnv = localEnv; while (lintEnv.info.lint == null) lintEnv = lintEnv.next; - localEnv.info.lint = lintEnv.info.lint.augment(sym.attributes_field, sym.flags()); + localEnv.info.lint = lintEnv.info.lint.augment(sym.annotations, sym.flags()); return localEnv; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java index fc4fde9a051..3dad6e3b2c3 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java @@ -406,7 +406,7 @@ public class Flow { Lint lintPrev = lint; pendingExits = new ListBuffer<PendingExit>(); - lint = lint.augment(tree.sym.attributes_field); + lint = lint.augment(tree.sym.annotations); try { // process all the static initializers @@ -442,7 +442,7 @@ public class Flow { if (tree.body == null) return; Lint lintPrev = lint; - lint = lint.augment(tree.sym.attributes_field); + lint = lint.augment(tree.sym.annotations); Assert.check(pendingExits.isEmpty()); @@ -468,7 +468,7 @@ public class Flow { public void visitVarDef(JCVariableDecl tree) { if (tree.init != null) { Lint lintPrev = lint; - lint = lint.augment(tree.sym.attributes_field); + lint = lint.augment(tree.sym.annotations); try{ scan(tree.init); } finally { @@ -783,7 +783,7 @@ public class Flow { } classDef = tree; thrown = List.nil(); - lint = lint.augment(tree.sym.attributes_field); + lint = lint.augment(tree.sym.annotations); try { // process all the static initializers @@ -863,7 +863,7 @@ public class Flow { List<Type> mthrown = tree.sym.type.getThrownTypes(); Lint lintPrev = lint; - lint = lint.augment(tree.sym.attributes_field); + lint = lint.augment(tree.sym.annotations); Assert.check(pendingExits.isEmpty()); @@ -902,7 +902,7 @@ public class Flow { public void visitVarDef(JCVariableDecl tree) { if (tree.init != null) { Lint lintPrev = lint; - lint = lint.augment(tree.sym.attributes_field); + lint = lint.augment(tree.sym.annotations); try{ scan(tree.init); } finally { @@ -1491,7 +1491,7 @@ public class Flow { firstadr = nextadr; } classDef = tree; - lint = lint.augment(tree.sym.attributes_field); + lint = lint.augment(tree.sym.annotations); try { // define all the static fields @@ -1558,7 +1558,7 @@ public class Flow { int firstadrPrev = firstadr; Lint lintPrev = lint; - lint = lint.augment(tree.sym.attributes_field); + lint = lint.augment(tree.sym.annotations); Assert.check(pendingExits.isEmpty()); @@ -1609,7 +1609,7 @@ public class Flow { if (track && tree.sym.owner.kind == MTH) newVar(tree.sym); if (tree.init != null) { Lint lintPrev = lint; - lint = lint.augment(tree.sym.attributes_field); + lint = lint.augment(tree.sym.annotations); try{ scanExpr(tree.init); if (track) letInit(tree.pos(), tree.sym); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java index 00f5cd7f625..1745da3711b 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java @@ -2257,7 +2257,7 @@ public class Lower extends TreeTranslator { null, List.<JCExpression>nil(), List.<JCTree>nil()); ClassSymbol c = tree.packge.package_info; c.flags_field |= flags; - c.attributes_field = tree.packge.attributes_field; + c.annotations.setAttributes(tree.packge.annotations); ClassType ctype = (ClassType) c.type; ctype.supertype_field = syms.objectType; ctype.interfaces_field = List.nil(); @@ -2274,7 +2274,8 @@ public class Lower extends TreeTranslator { case LEGACY: return tree.packageAnnotations.nonEmpty(); case NONEMPTY: - for (Attribute.Compound a: tree.packge.attributes_field) { + for (Attribute.Compound a : + tree.packge.annotations.getAttributes()) { Attribute.RetentionPolicy p = types.getRetention(a); if (p != Attribute.RetentionPolicy.SOURCE) return true; @@ -3499,7 +3500,6 @@ public class Lower extends TreeTranslator { JCExpression expression = oneCase.getExpression(); if (expression != null) { // expression for a "default" case is null - expression = TreeInfo.skipParens(expression); String labelExpr = (String) expression.type.constValue(); Integer mapping = caseLabelToPosition.put(labelExpr, casePosition); Assert.checkNull(mapping); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java index ff57daa4d59..70f021da099 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java @@ -76,11 +76,10 @@ public class MemberEnter extends JCTree.Visitor implements Completer { private final Annotate annotate; private final Types types; private final JCDiagnostic.Factory diags; + private final Source source; private final Target target; private final DeferredLintHandler deferredLintHandler; - private final boolean skipAnnotations; - public static MemberEnter instance(Context context) { MemberEnter instance = context.get(memberEnterKey); if (instance == null) @@ -102,10 +101,9 @@ public class MemberEnter extends JCTree.Visitor implements Completer { annotate = Annotate.instance(context); types = Types.instance(context); diags = JCDiagnostic.Factory.instance(context); + source = Source.instance(context); target = Target.instance(context); deferredLintHandler = DeferredLintHandler.instance(context); - Options options = Options.instance(context); - skipAnnotations = options.isSet("skipAnnotations"); } /** A queue for classes whose members still need to be entered into the @@ -690,7 +688,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { public Env<AttrContext> getMethodEnv(JCMethodDecl tree, Env<AttrContext> env) { Env<AttrContext> mEnv = methodEnv(tree, env); - mEnv.info.lint = mEnv.info.lint.augment(tree.sym.attributes_field, tree.sym.flags()); + mEnv.info.lint = mEnv.info.lint.augment(tree.sym.annotations, tree.sym.flags()); for (List<JCTypeParameter> l = tree.typarams; l.nonEmpty(); l = l.tail) mEnv.info.scope.enterIfAbsent(l.head.type.tsym); for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) @@ -727,18 +725,24 @@ public class MemberEnter extends JCTree.Visitor implements Completer { void annotateLater(final List<JCAnnotation> annotations, final Env<AttrContext> localEnv, final Symbol s) { - if (annotations.isEmpty()) return; - if (s.kind != PCK) s.attributes_field = null; // mark it incomplete for now - annotate.later(new Annotate.Annotator() { + if (annotations.isEmpty()) { + return; + } + if (s.kind != PCK) { + s.annotations.reset(); // mark Annotations as incomplete for now + } + annotate.normal(new Annotate.Annotator() { + @Override public String toString() { return "annotate " + annotations + " onto " + s + " in " + s.owner; } + + @Override public void enterAnnotation() { - Assert.check(s.kind == PCK || s.attributes_field == null); + Assert.check(s.kind == PCK || s.annotations.pendingCompletion()); JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); try { - if (s.attributes_field != null && - s.attributes_field.nonEmpty() && + if (!s.annotations.isEmpty() && annotations.nonEmpty()) log.error(annotations.head.pos, "already.annotated", @@ -756,7 +760,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { * java.lang.Deprecated. **/ private boolean hasDeprecatedAnnotation(List<JCAnnotation> annotations) { - for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) { + for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) { JCAnnotation a = al.head; if (a.annotationType.type == syms.deprecatedType && a.args.isEmpty()) return true; @@ -764,42 +768,62 @@ public class MemberEnter extends JCTree.Visitor implements Completer { return false; } - /** Enter a set of annotations. */ private void enterAnnotations(List<JCAnnotation> annotations, Env<AttrContext> env, Symbol s) { - ListBuffer<Attribute.Compound> buf = - new ListBuffer<Attribute.Compound>(); - Set<TypeSymbol> annotated = new HashSet<TypeSymbol>(); - if (!skipAnnotations) - for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) { + Map<TypeSymbol, ListBuffer<Attribute.Compound>> annotated = + new LinkedHashMap<TypeSymbol, ListBuffer<Attribute.Compound>>(); + Map<Attribute.Compound, DiagnosticPosition> pos = + new HashMap<Attribute.Compound, DiagnosticPosition>(); + + for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) { JCAnnotation a = al.head; Attribute.Compound c = annotate.enterAnnotation(a, syms.annotationType, env); - if (c == null) continue; - buf.append(c); + if (c == null) { + continue; + } + + if (annotated.containsKey(a.type.tsym)) { + if (source.allowRepeatedAnnotations()) { + ListBuffer<Attribute.Compound> l = annotated.get(a.type.tsym); + l = l.append(c); + annotated.put(a.type.tsym, l); + pos.put(c, a.pos()); + } else { + log.error(a.pos(), "duplicate.annotation"); + } + } else { + annotated.put(a.type.tsym, ListBuffer.of(c)); + pos.put(c, a.pos()); + } + // Note: @Deprecated has no effect on local variables and parameters if (!c.type.isErroneous() && s.owner.kind != MTH - && types.isSameType(c.type, syms.deprecatedType)) + && types.isSameType(c.type, syms.deprecatedType)) { s.flags_field |= Flags.DEPRECATED; - if (!annotated.add(a.type.tsym)) - log.error(a.pos, "duplicate.annotation"); } - s.attributes_field = buf.toList(); + } + + s.annotations.setAttributesWithCompletion( + annotate.new AnnotateRepeatedContext(env, annotated, pos, log)); } /** Queue processing of an attribute default value. */ void annotateDefaultValueLater(final JCExpression defaultValue, final Env<AttrContext> localEnv, final MethodSymbol m) { - annotate.later(new Annotate.Annotator() { + annotate.normal(new Annotate.Annotator() { + @Override public String toString() { return "annotate " + m.owner + "." + m + " default " + defaultValue; } + + @Override public void enterAnnotation() { JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); try { diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java index ecd271ba1f6..92c0026f460 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -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 diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java b/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java index 468e97c4627..1ca860e95d4 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java +++ b/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java index a1c8ed7f95d..b221ba5b705 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -188,7 +188,7 @@ public class ClassReader implements Completer { /** The current input pointer. */ - int bp; + protected int bp; /** The objects of the constant pool. */ @@ -890,13 +890,13 @@ public class ClassReader implements Completer { protected enum AttributeKind { CLASS, MEMBER }; protected abstract class AttributeReader { - AttributeReader(Name name, ClassFile.Version version, Set<AttributeKind> kinds) { + protected AttributeReader(Name name, ClassFile.Version version, Set<AttributeKind> kinds) { this.name = name; this.version = version; this.kinds = kinds; } - boolean accepts(AttributeKind kind) { + protected boolean accepts(AttributeKind kind) { if (kinds.contains(kind)) { if (majorVersion > version.major || (majorVersion == version.major && minorVersion >= version.minor)) return true; @@ -915,11 +915,11 @@ public class ClassReader implements Completer { return false; } - abstract void read(Symbol sym, int attrLen); + protected abstract void read(Symbol sym, int attrLen); - final Name name; - final ClassFile.Version version; - final Set<AttributeKind> kinds; + protected final Name name; + protected final ClassFile.Version version; + protected final Set<AttributeKind> kinds; } protected Set<AttributeKind> CLASS_ATTRIBUTE = @@ -936,7 +936,7 @@ public class ClassReader implements Completer { // v45.3 attributes new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { if (readAllOfClassFile || saveParameterNames) ((MethodSymbol)sym).code = readCode(sym); else @@ -945,7 +945,7 @@ public class ClassReader implements Completer { }, new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { Object v = readPool(nextChar()); // Ignore ConstantValue attribute if field not final. if ((sym.flags() & FINAL) != 0) @@ -954,13 +954,13 @@ public class ClassReader implements Completer { }, new AttributeReader(names.Deprecated, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { sym.flags_field |= DEPRECATED; } }, new AttributeReader(names.Exceptions, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { int nexceptions = nextChar(); List<Type> thrown = List.nil(); for (int j = 0; j < nexceptions; j++) @@ -971,14 +971,14 @@ public class ClassReader implements Completer { }, new AttributeReader(names.InnerClasses, V45_3, CLASS_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { ClassSymbol c = (ClassSymbol) sym; readInnerClasses(c); } }, new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { int newbp = bp + attrLen; if (saveParameterNames) { // Pick up parameter names from the variable table. @@ -1014,7 +1014,7 @@ public class ClassReader implements Completer { }, new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { ClassSymbol c = (ClassSymbol) sym; Name n = readName(nextChar()); c.sourcefile = new SourceFileObject(n, c.flatname); @@ -1022,7 +1022,7 @@ public class ClassReader implements Completer { }, new AttributeReader(names.Synthetic, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { // bridge methods are visible when generics not enabled if (allowGenerics || (sym.flags_field & BRIDGE) == 0) sym.flags_field |= SYNTHETIC; @@ -1032,7 +1032,7 @@ public class ClassReader implements Completer { // standard v49 attributes new AttributeReader(names.EnclosingMethod, V49, CLASS_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { int newbp = bp + attrLen; readEnclosingMethodAttr(sym); bp = newbp; @@ -1041,11 +1041,11 @@ public class ClassReader implements Completer { new AttributeReader(names.Signature, V49, CLASS_OR_MEMBER_ATTRIBUTE) { @Override - boolean accepts(AttributeKind kind) { + protected boolean accepts(AttributeKind kind) { return super.accepts(kind) && allowGenerics; } - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { if (sym.kind == TYP) { ClassSymbol c = (ClassSymbol) sym; readingClassAttr = true; @@ -1074,31 +1074,31 @@ public class ClassReader implements Completer { // v49 annotation attributes new AttributeReader(names.AnnotationDefault, V49, CLASS_OR_MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { attachAnnotationDefault(sym); } }, new AttributeReader(names.RuntimeInvisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { attachAnnotations(sym); } }, new AttributeReader(names.RuntimeInvisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { attachParameterAnnotations(sym); } }, new AttributeReader(names.RuntimeVisibleAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { attachAnnotations(sym); } }, new AttributeReader(names.RuntimeVisibleParameterAnnotations, V49, CLASS_OR_MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { attachParameterAnnotations(sym); } }, @@ -1106,14 +1106,14 @@ public class ClassReader implements Completer { // additional "legacy" v49 attributes, superceded by flags new AttributeReader(names.Annotation, V49, CLASS_OR_MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { if (allowAnnotations) sym.flags_field |= ANNOTATION; } }, new AttributeReader(names.Bridge, V49, MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { sym.flags_field |= BRIDGE; if (!allowGenerics) sym.flags_field &= ~SYNTHETIC; @@ -1121,13 +1121,13 @@ public class ClassReader implements Completer { }, new AttributeReader(names.Enum, V49, CLASS_OR_MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { sym.flags_field |= ENUM; } }, new AttributeReader(names.Varargs, V49, CLASS_OR_MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { + protected void read(Symbol sym, int attrLen) { if (allowVarargs) sym.flags_field |= VARARGS; } @@ -1153,7 +1153,7 @@ public class ClassReader implements Completer { - void readEnclosingMethodAttr(Symbol sym) { + protected void readEnclosingMethodAttr(Symbol sym) { // sym is a nested class with an "Enclosing Method" attribute // remove sym from it's current owners scope and place it in // the scope specified by the attribute @@ -1321,7 +1321,7 @@ public class ClassReader implements Completer { else proxies.append(proxy); } - annotate.later(new AnnotationCompleter(sym, proxies.toList())); + annotate.normal(new AnnotationCompleter(sym, proxies.toList())); } } @@ -1347,7 +1347,7 @@ public class ClassReader implements Completer { void attachAnnotationDefault(final Symbol sym) { final MethodSymbol meth = (MethodSymbol)sym; // only on methods final Attribute value = readAttributeValue(); - annotate.later(new AnnotationDefaultCompleter(meth, value)); + annotate.normal(new AnnotationDefaultCompleter(meth, value)); } Type readTypeOrClassSymbol(int i) { @@ -1693,10 +1693,13 @@ public class ClassReader implements Completer { JavaFileObject previousClassFile = currentClassFile; try { currentClassFile = classFile; + Annotations annotations = sym.annotations; List<Attribute.Compound> newList = deproxyCompoundList(l); - sym.attributes_field = ((sym.attributes_field == null) - ? newList - : newList.prependList(sym.attributes_field)); + if (annotations.pendingCompletion()) { + annotations.setAttributes(newList); + } else { + annotations.append(newList); + } } finally { currentClassFile = previousClassFile; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 8665a1ef87f..4ed076afe83 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -164,7 +164,7 @@ public class ClassWriter extends ClassFile { /** Construct a class writer, given an options table. */ - private ClassWriter(Context context) { + protected ClassWriter(Context context) { context.put(classWriterKey, this); log = Log.instance(context); @@ -601,12 +601,20 @@ public class ClassWriter extends ClassFile { * Returns the number of attributes written (0 or 1). */ int writeEnclosingMethodAttribute(ClassSymbol c) { - if (!target.hasEnclosingMethodAttribute() || - c.owner.kind != MTH && // neither a local class + if (!target.hasEnclosingMethodAttribute()) + return 0; + return writeEnclosingMethodAttribute(names.EnclosingMethod, c); + } + + /** Write the EnclosingMethod attribute with a specified name. + * Returns the number of attributes written (0 or 1). + */ + protected int writeEnclosingMethodAttribute(Name attributeName, ClassSymbol c) { + if (c.owner.kind != MTH && // neither a local class c.name != names.empty) // nor anonymous return 0; - int alenIdx = writeAttr(names.EnclosingMethod); + int alenIdx = writeAttr(attributeName); ClassSymbol enclClass = c.owner.enclClass(); MethodSymbol enclMethod = (c.owner.type == null // local to init block @@ -817,7 +825,7 @@ public class ClassWriter extends ClassFile { } public void visitClass(Attribute.Class clazz) { databuf.appendByte('c'); - databuf.appendChar(pool.put(typeSig(clazz.type))); + databuf.appendChar(pool.put(typeSig(clazz.classType))); } public void visitCompound(Attribute.Compound compound) { databuf.appendByte('@'); @@ -1569,6 +1577,7 @@ public class ClassWriter extends ClassFile { acount += writeFlagAttrs(c.flags()); acount += writeJavaAnnotations(c.getAnnotationMirrors()); acount += writeEnclosingMethodAttribute(c); + acount += writeExtraClassAttributes(c); poolbuf.appendInt(JAVA_MAGIC); poolbuf.appendChar(target.minorVersion); @@ -1588,6 +1597,14 @@ public class ClassWriter extends ClassFile { pool = c.pool = null; // to conserve space } + /**Allows subclasses to write additional class attributes + * + * @return the number of attributes written + */ + protected int writeExtraClassAttributes(ClassSymbol c) { + return 0; + } + int adjustFlags(final long flags) { int result = (int)flags; if ((flags & SYNTHETIC) != 0 && !target.useSyntheticFlag()) diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java index eda91f31259..765b79190d7 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java @@ -157,7 +157,7 @@ public class JNIWriter { if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0) return false; - for (Attribute.Compound a: c.attributes_field) { + for (Attribute.Compound a: c.annotations.getAttributes()) { if (a.type.tsym == syms.nativeHeaderType.tsym) return true; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/Main.java b/langtools/src/share/classes/com/sun/tools/javac/main/Main.java index 576c07003af..f21a9ca8358 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/main/Main.java +++ b/langtools/src/share/classes/com/sun/tools/javac/main/Main.java @@ -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 diff --git a/langtools/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java b/langtools/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java index bf1ec29529b..92e1c1790e1 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java +++ b/langtools/src/share/classes/com/sun/tools/javac/model/AnnotationProxyMaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, 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 @@ -177,7 +177,7 @@ public class AnnotationProxyMaker { } public void visitClass(Attribute.Class c) { - value = new MirroredTypeExceptionProxy(c.type); + value = new MirroredTypeExceptionProxy(c.classType); } public void visitArray(Attribute.Array a) { @@ -187,7 +187,7 @@ public class AnnotationProxyMaker { // Construct a proxy for a MirroredTypesException ListBuffer<TypeMirror> elems = new ListBuffer<TypeMirror>(); for (Attribute value : a.values) { - Type elem = ((Attribute.Class) value).type; + Type elem = ((Attribute.Class) value).classType; elems.append(elem); } value = new MirroredTypesExceptionProxy(elems.toList()); diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index 56e5b767d63..b931053a671 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -250,6 +250,70 @@ compiler.err.duplicate.annotation=\ compiler.err.duplicate.annotation.member.value=\ duplicate annotation member value {0} in {1} +# 0: type +compiler.err.duplicate.annotation.missing.container=\ + duplicate annotation, the declaration of {0} does not have a ContainedBy annotation + +# 0: type, 1: type +compiler.err.invalid.container.no.containedby=\ + invalid contained repeatable annotation, {0} is not annotated with {1} + +# 0: type, 1: type +compiler.err.invalid.container.wrong.containedby=\ + invalid contained repeatable annotation, {0} does not match {1} + +# 0: type, 1: type +compiler.err.invalid.container.no.containerfor=\ + invalid container for repeating annotations, {0} is not annotated with {1} + +# 0: type, 1: type +compiler.err.invalid.container.wrong.containerfor=\ + invalid container for repeating annotations, {0} does not match {1} + +# 0: type +compiler.err.invalid.containedby.annotation=\ + duplicate annotation, {0} is annotated with an invalid ContainedBy annotation + +# 0: type +compiler.err.invalid.containedby.annotation.no.value=\ + duplicate annotation, {0} is not a valid ContainedBy, no value element method declared + +# 0: type, 1: number +compiler.err.invalid.containedby.annotation.multiple.values=\ + duplicate annotation, {0} is not a valid ContainedBy, {1} value element methods declared + +# 0: type +compiler.err.invalid.containedby.annotation.invalid.value=\ + duplicate annotation, {0} is not a valid ContainedBy, invalid value element, need a method + +# 0: type, 1: type, 2: type +compiler.err.invalid.containedby.annotation.value.return=\ + duplicate annotation, value element of containing annotation {0} should have type {2}, found {1} + +# 0: type, 1: symbol +compiler.err.invalid.containedby.annotation.elem.nondefault=\ + duplicate annotation, element {1} in containing annotation {0} does not have a default value + +# 0: symbol, 1: type, 2: symbol, 3: type +compiler.err.invalid.containedby.annotation.retention=\ + containing annotation {0} has shorter retention ({1}) than the contained annotation {2} with retention {3} + +# 0: symbol, 1: symbol +compiler.err.invalid.containedby.annotation.not.documented=\ + containing annotation type, {0}, is not @Documented while repeated annotation type, {1}, is + +# 0: symbol, 1: symbol +compiler.err.invalid.containedby.annotation.not.inherited=\ + containing annotation type, {0}, is not @Inherited while repeated annotation type, {1}, is + +# 0: symbol, 1: symbol +compiler.err.invalid.containedby.annotation.incompatible.target=\ + target of container annotation {0} is not a subset of target of repeated annotation {1} + +# 0: symbol +compiler.err.invalid.containedby.annotation.repeated.and.container.present=\ + container {0} must not be present at the same time as the element it contains + # 0: name compiler.err.duplicate.class=\ duplicate class: {0} diff --git a/langtools/src/share/classes/com/sun/tools/javac/sym/CreateSymbols.java b/langtools/src/share/classes/com/sun/tools/javac/sym/CreateSymbols.java index 9ee550e5ce8..53b37fb4554 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/sym/CreateSymbols.java +++ b/langtools/src/share/classes/com/sun/tools/javac/sym/CreateSymbols.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -206,9 +206,7 @@ public class CreateSymbols extends AbstractProcessor { } ClassSymbol cs = (ClassSymbol) sym; if (addLegacyAnnotation) { - cs.attributes_field = (cs.attributes_field == null) - ? List.of(proprietary) - : cs.attributes_field.prepend(proprietary); + cs.annotations.prepend(List.of(proprietary)); } writeClass(pool, cs, writer); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java index 6191f4b8875..f9be124079f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java @@ -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 @@ -740,7 +740,7 @@ public class TreeMaker implements JCTree.Factory { result = Literal(v.value); } public void visitClass(Attribute.Class clazz) { - result = ClassLiteral(clazz.type).setType(syms.classType); + result = ClassLiteral(clazz.classType).setType(syms.classType); } public void visitEnum(Attribute.Enum e) { result = QualIdent(e.value); diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java b/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java index 219184c7e51..fc2ed35c3d6 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationValueImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationValueImpl.java index dae37c488d9..82014ca96fc 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationValueImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationValueImpl.java @@ -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 @@ -83,7 +83,7 @@ public class AnnotationValueImpl implements AnnotationValue { public void visitClass(Attribute.Class c) { value = TypeMaker.getType(env, - env.types.erasure(c.type)); + env.types.erasure(c.classType)); } public void visitEnum(Attribute.Enum e) { diff --git a/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java b/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java index 2fd98b00717..4abbc276a58 100644 --- a/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java +++ b/langtools/src/share/classes/com/sun/tools/javah/JavahTask.java @@ -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 @@ -506,7 +506,7 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask { List<String> opts = new ArrayList<String>(); opts.add("-proc:only"); opts.addAll(javac_extras); - CompilationTask t = c.getTask(log, fileManager, diagnosticListener, opts, internalize(classes), null); + CompilationTask t = c.getTask(log, fileManager, diagnosticListener, opts, classes, null); JavahProcessor p = new JavahProcessor(g); t.setProcessors(Collections.singleton(p)); @@ -516,14 +516,6 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask { return ok; } - private List<String> internalize(List<String> classes) { - List<String> l = new ArrayList<String>(); - for (String c: classes) { - l.add(c.replace('$', '.')); - } - return l; - } - private List<File> pathToFiles(String path) { List<File> files = new ArrayList<File>(); for (String f: path.split(File.pathSeparator)) { diff --git a/langtools/test/tools/javac/ProtectedInnerClass/ProtectedInnerClass.sh b/langtools/test/tools/javac/ProtectedInnerClass/ProtectedInnerClass.sh index d06b82a5da5..cad19da6b52 100644 --- a/langtools/test/tools/javac/ProtectedInnerClass/ProtectedInnerClass.sh +++ b/langtools/test/tools/javac/ProtectedInnerClass/ProtectedInnerClass.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2009, 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 diff --git a/langtools/test/tools/javac/StringsInSwitch/7181320/BinOpInCaseLabel.java b/langtools/test/tools/javac/StringsInSwitch/7181320/BinOpInCaseLabel.java new file mode 100644 index 00000000000..f44c1d66f27 --- /dev/null +++ b/langtools/test/tools/javac/StringsInSwitch/7181320/BinOpInCaseLabel.java @@ -0,0 +1,38 @@ +/* + * 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 7181320 + * @summary javac NullPointerException for switch labels with cast to String expressions + * @compile BinOpInCaseLabel.java + */ + +public class BinOpInCaseLabel { + public static void main(String [] args) { + switch (args[0]) { + case "hello" + "world": + break; + } + } +} diff --git a/langtools/test/tools/javac/StringsInSwitch/7181320/CastInCaseLabel.java b/langtools/test/tools/javac/StringsInSwitch/7181320/CastInCaseLabel.java new file mode 100644 index 00000000000..2125d88e907 --- /dev/null +++ b/langtools/test/tools/javac/StringsInSwitch/7181320/CastInCaseLabel.java @@ -0,0 +1,38 @@ +/* + * 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 7181320 + * @summary javac NullPointerException for switch labels with cast to String expressions + * @compile CastInCaseLabel.java + */ + +public class CastInCaseLabel { + public static void main(String [] args) { + switch (args[0]) { + case (String)"hello": + break; + } + } +} diff --git a/langtools/test/tools/javac/StringsInSwitch/7181320/CondExprInCaseLabel.java b/langtools/test/tools/javac/StringsInSwitch/7181320/CondExprInCaseLabel.java new file mode 100644 index 00000000000..6049ec78bda --- /dev/null +++ b/langtools/test/tools/javac/StringsInSwitch/7181320/CondExprInCaseLabel.java @@ -0,0 +1,39 @@ +/* + * 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 7181320 + * @summary javac NullPointerException for switch labels with cast to String expressions + * @compile CondExprInCaseLabel.java + */ + +public class CondExprInCaseLabel { + public static void main(String [] args) { + final boolean cond = true; + switch (args[0]) { + case cond ? "hello" : "world": + break; + } + } +} diff --git a/langtools/test/tools/javac/StringsInSwitch/7181320/CondExprInCaseLabel1.java b/langtools/test/tools/javac/StringsInSwitch/7181320/CondExprInCaseLabel1.java new file mode 100644 index 00000000000..37b02923daa --- /dev/null +++ b/langtools/test/tools/javac/StringsInSwitch/7181320/CondExprInCaseLabel1.java @@ -0,0 +1,39 @@ +/* + * 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 7181320 + * @summary javac NullPointerException for switch labels with cast to String expressions + * @compile CondExprInCaseLabel1.java + */ + +public class CondExprInCaseLabel1 { + public static void main(String [] args) { + final boolean cond = true; + switch (args[0]) { + case cond ? (String)"hello" : "world": + break; + } + } +} diff --git a/langtools/test/tools/javac/StringsInSwitch/7181320/CondExprInCaseLabel2.java b/langtools/test/tools/javac/StringsInSwitch/7181320/CondExprInCaseLabel2.java new file mode 100644 index 00000000000..b5ef26dfbaa --- /dev/null +++ b/langtools/test/tools/javac/StringsInSwitch/7181320/CondExprInCaseLabel2.java @@ -0,0 +1,39 @@ +/* + * 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 7181320 + * @summary javac NullPointerException for switch labels with cast to String expressions + * @compile CondExprInCaseLabel2.java + */ + +public class CondExprInCaseLabel2 { + public static void main(String [] args) { + final boolean cond = true; + switch (args[0]) { + case cond ? "hello" : (String)"world": + break; + } + } +} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/BasicRepeatingAnnotations.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/BasicRepeatingAnnotations.java new file mode 100644 index 00000000000..9d9e59c1fc4 --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/BasicRepeatingAnnotations.java @@ -0,0 +1,79 @@ +/* + * 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 + * @summary Smoke test for repeating annotations + * @bug 7151010 + * + * @run clean BasicRepeatingAnnotations BasicRepeatingAnnos BasicNonRepeatingAnno Foo Foos Bar + * @run compile BasicRepeatingAnnotations.java + * @run main BasicRepeatingAnnotations + */ + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@ContainedBy(Foos.class) +@interface Foo {} + +@ContainerFor(Foo.class) +@Retention(RetentionPolicy.RUNTIME) +@interface Foos { + Foo[] value(); +} + +@interface Bar {} + +@Foo @Foo +@Foo +@Bar +@Foo +@Foo +@Foo +@Foo +@Foo @Foo +@Foo +class BasicRepeatingAnnos {} + +@Foo +class BasicNonRepeatingAnno {} + +public class BasicRepeatingAnnotations { + public static void main(String[] args) throws Exception { + Annotation a = BasicRepeatingAnnos.class.getAnnotation(Foos.class); + if (a == null) { + throw new RuntimeException("Container annotation missing"); + } + + // verify that container not present on nonrepeating + a = BasicNonRepeatingAnno.class.getAnnotation(Foos.class); + if (a != null) { + throw new RuntimeException("Container annotation present"); + } + a = BasicNonRepeatingAnno.class.getAnnotation(Foo.class); + if (a == null) { + throw new RuntimeException("Repeated annoation not directly present"); + } + } +} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/CheckTargets.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/CheckTargets.java new file mode 100644 index 00000000000..1489cea562d --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/CheckTargets.java @@ -0,0 +1,67 @@ +/* + * 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 + * @summary Smoke test for repeating annotations + * @bug 7151010 + * + * @run clean Foos Foo Bars Bar Baz Bazs CheckTargets + * @run compile CheckTargets.java + */ + +import java.lang.annotation.*; + +@ContainedBy(Foos.class) +@Target(ElementType.TYPE) +@interface Foo {} + +@ContainerFor(Foo.class) +@Target(ElementType.ANNOTATION_TYPE) +@interface Foos { + Foo[] value(); +} + +@ContainedBy(Bars.class) +@Target(ElementType.TYPE) +@interface Bar {} + +@ContainerFor(Bar.class) +@Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE }) +@interface Bars { + Bar[] value(); +} + + +@ContainedBy(Bazs.class) +@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE }) +@interface Baz {} + +@ContainerFor(Baz.class) +@Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE }) +@interface Bazs { + Baz[] value(); +} + + +public class CheckTargets {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/ContainerHasRepeatedContained.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/ContainerHasRepeatedContained.java new file mode 100644 index 00000000000..ca2345d6b16 --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/ContainerHasRepeatedContained.java @@ -0,0 +1,46 @@ +/* + * 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 + * @summary Smoke test for repeating annotations + * @bug 7151010 + * + * @run clean Bar BarContainer ContainerHasRepeatedContained + * @run compile ContainerHasRepeatedContained.java + */ + +import java.lang.annotation.ContainedBy; +import java.lang.annotation.ContainerFor; + +@ContainedBy(BarContainer.class) +@interface Bar {} + +@Bar +@Bar +@ContainerFor(Bar.class) +@interface BarContainer { + Bar[] value(); +} + +public class ContainerHasRepeatedContained {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/DelayRepeatedContainer.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/DelayRepeatedContainer.java new file mode 100644 index 00000000000..ffceb9c3707 --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/DelayRepeatedContainer.java @@ -0,0 +1,50 @@ +/* + * 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 + * @summary Smoke test for repeating annotations + * @bug 7151010 + * + * @run clean DelayRepeatedContainer Bar BarContainer + * @run compile DelayRepeatedContainer.java + */ + +import java.lang.annotation.*; + +public class DelayRepeatedContainer { + @Bar("apa") @Bar("banan") + String meh() { return "meh"; } +} + +@Bar("katt") +@Bar("lol") +@ContainedBy(BarContainer.class) +@interface Bar { + String value(); +} + +@ContainerFor(Bar.class) +@interface BarContainer { + Bar[] value(); +} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/InvalidTarget.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/InvalidTarget.java new file mode 100644 index 00000000000..24c23386033 --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/InvalidTarget.java @@ -0,0 +1,45 @@ +/* + * 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 + * @summary Smoke test for repeating annotations + * @bug 7151010 + * + * @run clean Foos Foo + * @run compile/fail InvalidTarget.java + */ + +import java.lang.annotation.*; + +@ContainedBy(Foos.class) +@Target(ElementType.ANNOTATION_TYPE) +@interface Foo {} + +@ContainerFor(Foo.class) +@Target(ElementType.TYPE) +@interface Foos { + Foo[] value(); +} + +public class InvalidTargets {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainedBy.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainedBy.java new file mode 100644 index 00000000000..0a141a9e129 --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainedBy.java @@ -0,0 +1,39 @@ +/* + * 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 + * @summary Smoke test for repeating annotations + * @compile/fail MissingContainedBy.java + * @bug 7151010 + */ + +import java.lang.annotation.*; + + +@ContainerFor(MissingContainedBy.class) +@interface Foos { + MissingContainedBy[] value(); +} + +public @interface MissingContainedBy {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainerFor.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainerFor.java new file mode 100644 index 00000000000..7d22aebf9b3 --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainerFor.java @@ -0,0 +1,38 @@ +/* + * 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 + * @summary Smoke test for repeating annotations + * @compile/fail MissingContainerFor.java + * @bug 7151010 + */ + +import java.lang.annotation.*; + +@interface Foos { + MissingContainerFor[] value(); +} + +@ContainedBy(Foos.class) +public @interface MissingContainerFor {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/NestedContainers.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/NestedContainers.java new file mode 100644 index 00000000000..c492258801a --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/NestedContainers.java @@ -0,0 +1,74 @@ +/* + * 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 + * @summary Smoke test for repeating annotations + * @bug 7151010 + * + * @run clean NestedContainers BasicRepeatingAnnos BasicRepeatingAnnos2 Foo Foos FoosFoos + * @run compile NestedContainers.java + * @run main NestedContainers + */ + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@ContainedBy(Foos.class) +@interface Foo {} + +@Retention(RetentionPolicy.RUNTIME) +@ContainedBy(FoosFoos.class) +@ContainerFor(Foo.class) +@interface Foos { + Foo[] value(); +} + +@ContainerFor(Foos.class) +@Retention(RetentionPolicy.RUNTIME) +@interface FoosFoos { + Foos[] value(); +} + +@Foo +@Foo +class BasicRepeatingAnnos {} + +@Foos({}) +@Foos({}) +class BasicRepeatingAnnos2 {} + +public class NestedContainers { + public static void main(String[] args) throws Exception { + Annotation a = BasicRepeatingAnnos.class.getAnnotation(Foos.class); + if (a == null) { + throw new RuntimeException("Container annotation missing"); + } + + // Check 2:nd level container + a = BasicRepeatingAnnos2.class.getAnnotation(FoosFoos.class); + if (a == null) { + throw new RuntimeException("Container annotation missing"); + } + } +} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepMemberAnno.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepMemberAnno.java new file mode 100644 index 00000000000..bb67c91cee0 --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepMemberAnno.java @@ -0,0 +1,49 @@ +/* + * 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 + * @summary Smoke test for repeating annotations + * @bug 7151010 + * + * @run clean RepMemberAnno Bar BarContainer + * @run compile RepMemberAnno.java + */ + +import java.lang.annotation.ContainedBy; +import java.lang.annotation.ContainerFor; + +public class RepMemberAnno { + @Bar("Apa") @Bar("Banan") + public void meh() {} +} + +@ContainedBy(BarContainer.class) +@interface Bar { + String value(); +} + +@ContainerFor(Bar.class) +@interface BarContainer { + Bar[] value(); +} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepSelfMemberAnno.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepSelfMemberAnno.java new file mode 100644 index 00000000000..bc11c69c1f0 --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepSelfMemberAnno.java @@ -0,0 +1,60 @@ +/* + * 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 + * @summary Smoke test for repeating annotations + * @bug 7151010 + * + * @run clean RepSelfMemberAnno BarContainer BarContainerContainer + * @run compile RepSelfMemberAnno.java + */ + +import java.lang.annotation.*; + + +@Retention(RetentionPolicy.RUNTIME) +@ContainedBy(BarContainer.class) +public @interface RepSelfMemberAnno { + @RepSelfMemberAnno @RepSelfMemberAnno + String meh() default "banan"; +} + + +@ContainedBy(BarContainerContainer.class) +@Retention(RetentionPolicy.RUNTIME) +@ContainerFor(RepSelfMemberAnno.class) +@interface BarContainer { + RepSelfMemberAnno[] value(); +} + +@ContainerFor(BarContainer.class) +@Retention(RetentionPolicy.RUNTIME) +@interface BarContainerContainer { + BarContainer[] value(); + String meh() default "apa"; +} + +@BarContainer(value={}) +@BarContainer(value={}) +@interface Bar {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java new file mode 100644 index 00000000000..26d98513502 --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java @@ -0,0 +1,44 @@ +/* + * 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 + * @summary Smoke test for repeating annotations + * @compile/fail RepeatingAndContainerPresent.java + * @bug 7151010 + */ + +import java.lang.annotation.*; + +@ContainedBy(Foos.class) +@interface Foo {} + +@interface Foos { + Foo[] value(); +} + + +@Foo +@Foo +@Foos({}) +public class RepeatingAndContainerPresent {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/SelfRepeatingAnnotations.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/SelfRepeatingAnnotations.java new file mode 100644 index 00000000000..b0eb87d876b --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/SelfRepeatingAnnotations.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @summary Smoke test for repeating annotations + * @bug 7151010 + * + * @run clean SelfRepeatingAnnotations Foos SelfRepeatingAnno + * @run compile SelfRepeatingAnnotations.java + * @run main SelfRepeatingAnnotations + */ + +import java.lang.annotation.*; + +@ContainerFor(SelfRepeatingAnno.class) +@Retention(RetentionPolicy.RUNTIME) +@interface Foos { + SelfRepeatingAnno[] value(); +} + +@SelfRepeatingAnno +@Retention(RetentionPolicy.RUNTIME) +@SelfRepeatingAnno +@ContainedBy(Foos.class) +@interface SelfRepeatingAnno {} + +public class SelfRepeatingAnnotations { + public static void main(String[] args) throws Exception { + Annotation a = SelfRepeatingAnno.class.getAnnotation(Foos.class); + if (a == null) { + throw new RuntimeException("Container annotation missing"); + } + } +} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/SingleRepeatingAndContainer.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/SingleRepeatingAndContainer.java new file mode 100644 index 00000000000..b18d259670f --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/SingleRepeatingAndContainer.java @@ -0,0 +1,43 @@ +/* + * 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 + * @summary Smoke test for repeating annotations + * @compile SingleRepeatingAndContainer.java + * @bug 7151010 + */ + +import java.lang.annotation.*; + +@ContainedBy(Foos.class) +@interface Foo {} + +@ContainerFor(Foo.class) +@interface Foos { + Foo[] value(); +} + +@Foo +@Foos({}) +public class SingleRepeatingAndContainer {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainedBy.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainedBy.java new file mode 100644 index 00000000000..a8a8a633d6b --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainedBy.java @@ -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. + */ + +/** + * @test + * @summary Smoke test for repeating annotations + * @compile/fail UseWrongContainedBy.java + * @bug 7151010 + */ + +import java.lang.annotation.*; + +@ContainerFor(UseWrongContainedBy.class) +@interface Foos { + UseWrongContainedBy[] value(); +} + +@ContainedBy(Target.class) +public @interface UseWrongContainedBy {} + +@UseWrongContainedBy @UseWrongContainedBy +@interface Foo {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainerFor.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainerFor.java new file mode 100644 index 00000000000..5067ef20625 --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainerFor.java @@ -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. + */ + +/** + * @test + * @summary Smoke test for repeating annotations + * @compile/fail UseWrongContainerFor.java + * @bug 7151010 + */ + +import java.lang.annotation.*; + +@ContainerFor(Retention.class) +@interface Foos { + UseWrongContainerFor[] value(); +} + +@ContainedBy(Foos.class) +public @interface UseWrongContainerFor {} + +@UseWrongContainerFor @UseWrongContainerFor +@interface Foo {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainedBy.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainedBy.java new file mode 100644 index 00000000000..182acf0534d --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainedBy.java @@ -0,0 +1,39 @@ +/* + * 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 + * @summary Smoke test for repeating annotations + * @compile/fail WrongContainedBy.java + * @bug 7151010 + */ + +import java.lang.annotation.*; + +@ContainerFor(WrongContainedBy.class) +@interface Foos { + WrongContainedBy[] value(); +} + +@ContainedBy(Target.class) +public @interface WrongContainedBy {} diff --git a/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainerFor.java b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainerFor.java new file mode 100644 index 00000000000..c87bdbcc40b --- /dev/null +++ b/langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainerFor.java @@ -0,0 +1,39 @@ +/* + * 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 + * @summary Smoke test for repeating annotations + * @compile/fail WrongContainerFor.java + * @bug 7151010 + */ + +import java.lang.annotation.*; + +@ContainerFor(Retention.class) +@interface Foos { + WrongContainerFor[] value(); +} + +@ContainedBy(Foos.class) +public @interface WrongContainerFor {} diff --git a/langtools/test/tools/javac/api/7086261/T7086261.java b/langtools/test/tools/javac/api/7086261/T7086261.java index a22c5fbecc0..47fae1b87f7 100644 --- a/langtools/test/tools/javac/api/7086261/T7086261.java +++ b/langtools/test/tools/javac/api/7086261/T7086261.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/langtools/test/tools/javac/api/T6397104.java b/langtools/test/tools/javac/api/T6397104.java index 841ffbbca90..a3d919c057d 100644 --- a/langtools/test/tools/javac/api/T6397104.java +++ b/langtools/test/tools/javac/api/T6397104.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 diff --git a/langtools/test/tools/javac/diags/CheckExamples.java b/langtools/test/tools/javac/diags/CheckExamples.java index aa35fc1589b..9bf63ee5892 100644 --- a/langtools/test/tools/javac/diags/CheckExamples.java +++ b/langtools/test/tools/javac/diags/CheckExamples.java @@ -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 diff --git a/langtools/test/tools/javac/diags/MessageInfo.java b/langtools/test/tools/javac/diags/MessageInfo.java index f053b3da3be..80809affe8f 100644 --- a/langtools/test/tools/javac/diags/MessageInfo.java +++ b/langtools/test/tools/javac/diags/MessageInfo.java @@ -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 diff --git a/langtools/test/tools/javac/diags/RunExamples.java b/langtools/test/tools/javac/diags/RunExamples.java index 858948387a6..08e161c3e7b 100644 --- a/langtools/test/tools/javac/diags/RunExamples.java +++ b/langtools/test/tools/javac/diags/RunExamples.java @@ -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 diff --git a/langtools/test/tools/javac/diags/examples.not-yet.txt b/langtools/test/tools/javac/diags/examples.not-yet.txt index 0262f05b424..9b569fcf309 100644 --- a/langtools/test/tools/javac/diags/examples.not-yet.txt +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt @@ -5,6 +5,9 @@ compiler.err.cant.apply.symbol compiler.err.cant.read.file # (apt.JavaCompiler?) compiler.err.cant.select.static.class.from.param.type compiler.err.illegal.char.for.encoding +compiler.err.invalid.containedby.annotation # should not happen +compiler.err.invalid.containedby.annotation.invalid.value # "can't" happen +compiler.err.invalid.containedby.annotation.multiple.values # can't happen compiler.err.io.exception # (javah.JavahTask?) compiler.err.limit.code # Code compiler.err.limit.code.too.large.for.try.stmt # Gen diff --git a/langtools/test/tools/javac/diags/examples/ApplicableMethodFound1.java b/langtools/test/tools/javac/diags/examples/ApplicableMethodFound1.java index a07c3b16001..0780b320d08 100644 --- a/langtools/test/tools/javac/diags/examples/ApplicableMethodFound1.java +++ b/langtools/test/tools/javac/diags/examples/ApplicableMethodFound1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/langtools/test/tools/javac/diags/examples/ContainedByDocumentedMismatch.java b/langtools/test/tools/javac/diags/examples/ContainedByDocumentedMismatch.java new file mode 100644 index 00000000000..a5077c7b825 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ContainedByDocumentedMismatch.java @@ -0,0 +1,37 @@ +/* + * 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. + */ + +// key: compiler.err.invalid.containedby.annotation.not.documented + +import java.lang.annotation.*; + +@Documented +@ContainedBy(Annos.class) +@interface Anno { } + +@ContainerFor(Anno.class) +@interface Annos { Anno[] value(); } + +@Anno +@Anno +class ContainedByDocumentedMismatch { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByInheritedMismatch.java b/langtools/test/tools/javac/diags/examples/ContainedByInheritedMismatch.java new file mode 100644 index 00000000000..d7723bad61c --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ContainedByInheritedMismatch.java @@ -0,0 +1,37 @@ +/* + * 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. + */ + +// key: compiler.err.invalid.containedby.annotation.not.inherited + +import java.lang.annotation.*; + +@Inherited +@ContainedBy(Annos.class) +@interface Anno { } + +@ContainerFor(Anno.class) +@interface Annos { Anno[] value(); } + +@Anno +@Anno +class ContainedByInheritedMismatch { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByNoValue.java b/langtools/test/tools/javac/diags/examples/ContainedByNoValue.java new file mode 100644 index 00000000000..8cb612808f9 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ContainedByNoValue.java @@ -0,0 +1,36 @@ +/* + * 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. + */ + +// key: compiler.err.invalid.containedby.annotation.no.value + +import java.lang.annotation.*; + +@ContainedBy(Annos.class) +@interface Anno { } + +@ContainerFor(Anno.class) +@interface Annos {} + +@Anno +@Anno +class ContainedByNoValue { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByNonDefault.java b/langtools/test/tools/javac/diags/examples/ContainedByNonDefault.java new file mode 100644 index 00000000000..d64b6b31d7c --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ContainedByNonDefault.java @@ -0,0 +1,36 @@ +/* + * 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. + */ + +// key: compiler.err.invalid.containedby.annotation.elem.nondefault + +import java.lang.annotation.*; + +@ContainedBy(Annos.class) +@interface Anno { } + +@ContainerFor(Anno.class) +@interface Annos { Anno[] value(); String foo(); } + +@Anno +@Anno +class ContainedByNonDefault { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByRetentionMismatch.java b/langtools/test/tools/javac/diags/examples/ContainedByRetentionMismatch.java new file mode 100644 index 00000000000..22680f5b644 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ContainedByRetentionMismatch.java @@ -0,0 +1,37 @@ +/* + * 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. + */ + +// key: compiler.err.invalid.containedby.annotation.retention + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@ContainedBy(Annos.class) +@interface Anno { } + +@ContainerFor(Anno.class) +@interface Annos { Anno[] value(); } + +@Anno +@Anno +class ContainedByRetentionMismatch { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByTargetMismatch.java b/langtools/test/tools/javac/diags/examples/ContainedByTargetMismatch.java new file mode 100644 index 00000000000..3fcd4fb3f5d --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ContainedByTargetMismatch.java @@ -0,0 +1,35 @@ +/* + * 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. + */ + +// key: compiler.err.invalid.containedby.annotation.incompatible.target + +import java.lang.annotation.*; + +@ContainedBy(Annos.class) +@Target(ElementType.METHOD) +@interface Anno { } + +@ContainerFor(Anno.class) +@interface Annos { Anno[] value(); } + +class ContainedByTargetMismatch { } diff --git a/langtools/test/tools/javac/diags/examples/ContainedByWrongValueType.java b/langtools/test/tools/javac/diags/examples/ContainedByWrongValueType.java new file mode 100644 index 00000000000..9b963bd3f6e --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ContainedByWrongValueType.java @@ -0,0 +1,36 @@ +/* + * 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. + */ + +// key: compiler.err.invalid.containedby.annotation.value.return + +import java.lang.annotation.*; + +@ContainedBy(Annos.class) +@interface Anno { } + +@ContainerFor(Anno.class) +@interface Annos { String value(); } + +@Anno +@Anno +class ContainedByWrongValueType { } diff --git a/langtools/test/tools/javac/diags/examples/DuplicateAnnotation.java b/langtools/test/tools/javac/diags/examples/DuplicateAnnotation.java index 48a43251e4c..09935e550f4 100644 --- a/langtools/test/tools/javac/diags/examples/DuplicateAnnotation.java +++ b/langtools/test/tools/javac/diags/examples/DuplicateAnnotation.java @@ -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 @@ -22,6 +22,8 @@ */ // key: compiler.err.duplicate.annotation +// key: compiler.warn.source.no.bootclasspath +// options: -source 7 @interface Anno { } diff --git a/langtools/test/tools/javac/diags/examples/DuplicateAnnotationJava8.java b/langtools/test/tools/javac/diags/examples/DuplicateAnnotationJava8.java new file mode 100644 index 00000000000..8fcb54949f6 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DuplicateAnnotationJava8.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +// key: compiler.err.duplicate.annotation.missing.container + +@interface Anno { } + +@Anno +@Anno +class DuplicateAnnotationJava8 { } diff --git a/langtools/test/tools/javac/diags/examples/IllegalDot.java b/langtools/test/tools/javac/diags/examples/IllegalDot.java index 15684a5d1c5..be0aa4b6360 100644 --- a/langtools/test/tools/javac/diags/examples/IllegalDot.java +++ b/langtools/test/tools/javac/diags/examples/IllegalDot.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/langtools/test/tools/javac/diags/examples/InconvertibleTypes.java b/langtools/test/tools/javac/diags/examples/InconvertibleTypes.java index 7df79d4673f..5c76b85a2ec 100644 --- a/langtools/test/tools/javac/diags/examples/InconvertibleTypes.java +++ b/langtools/test/tools/javac/diags/examples/InconvertibleTypes.java @@ -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 diff --git a/langtools/test/tools/javac/diags/examples/KindnameConstructor.java b/langtools/test/tools/javac/diags/examples/KindnameConstructor.java index 8144da6eff6..c8f20c29d69 100644 --- a/langtools/test/tools/javac/diags/examples/KindnameConstructor.java +++ b/langtools/test/tools/javac/diags/examples/KindnameConstructor.java @@ -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 diff --git a/langtools/test/tools/javac/diags/examples/NotApplicableMethodFound.java b/langtools/test/tools/javac/diags/examples/NotApplicableMethodFound.java index acba6fb7fa4..f9f222b2c7f 100644 --- a/langtools/test/tools/javac/diags/examples/NotApplicableMethodFound.java +++ b/langtools/test/tools/javac/diags/examples/NotApplicableMethodFound.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/langtools/test/tools/javac/diags/examples/PossibleLossPrecision.java b/langtools/test/tools/javac/diags/examples/PossibleLossPrecision.java index bbb1d49cd3c..1626a3cd4ea 100644 --- a/langtools/test/tools/javac/diags/examples/PossibleLossPrecision.java +++ b/langtools/test/tools/javac/diags/examples/PossibleLossPrecision.java @@ -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 diff --git a/langtools/test/tools/javac/diags/examples/RepeatingAnnotationAndContainer.java b/langtools/test/tools/javac/diags/examples/RepeatingAnnotationAndContainer.java new file mode 100644 index 00000000000..07a9bfddefb --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/RepeatingAnnotationAndContainer.java @@ -0,0 +1,37 @@ +/* + * 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. + */ + +// key: compiler.err.invalid.containedby.annotation.repeated.and.container.present + +import java.lang.annotation.*; + +@ContainedBy(Annos.class) +@interface Anno { } + +@ContainerFor(Anno.class) +@interface Annos { Anno[] value(); } + +@Anno +@Anno +@Annos(@Anno) +class RepeatingAnnotationAndContainer { } diff --git a/langtools/test/tools/javac/diags/examples/ResourceNotApplicableToType.java b/langtools/test/tools/javac/diags/examples/ResourceNotApplicableToType.java index 16452b88961..eb4e01e64b9 100644 --- a/langtools/test/tools/javac/diags/examples/ResourceNotApplicableToType.java +++ b/langtools/test/tools/javac/diags/examples/ResourceNotApplicableToType.java @@ -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 diff --git a/langtools/test/tools/javac/diags/examples/VarargsArgumentMismatch.java b/langtools/test/tools/javac/diags/examples/VarargsArgumentMismatch.java index 6b57224d531..eae18c983b8 100644 --- a/langtools/test/tools/javac/diags/examples/VarargsArgumentMismatch.java +++ b/langtools/test/tools/javac/diags/examples/VarargsArgumentMismatch.java @@ -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 diff --git a/langtools/test/tools/javac/diags/examples/VerboseResolveMulti1.java b/langtools/test/tools/javac/diags/examples/VerboseResolveMulti1.java index 32ffdd38a62..833c4cbcae1 100644 --- a/langtools/test/tools/javac/diags/examples/VerboseResolveMulti1.java +++ b/langtools/test/tools/javac/diags/examples/VerboseResolveMulti1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/langtools/test/tools/javac/diags/examples/WhereCaptured.java b/langtools/test/tools/javac/diags/examples/WhereCaptured.java index 3fa141d32f3..6a0b1242dab 100644 --- a/langtools/test/tools/javac/diags/examples/WhereCaptured.java +++ b/langtools/test/tools/javac/diags/examples/WhereCaptured.java @@ -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 diff --git a/langtools/test/tools/javac/diags/examples/WhereCaptured1.java b/langtools/test/tools/javac/diags/examples/WhereCaptured1.java index 08033a08d4f..df657311ac9 100644 --- a/langtools/test/tools/javac/diags/examples/WhereCaptured1.java +++ b/langtools/test/tools/javac/diags/examples/WhereCaptured1.java @@ -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 diff --git a/langtools/test/tools/javac/diags/examples/WhereIntersection.java b/langtools/test/tools/javac/diags/examples/WhereIntersection.java index b6cc4b1cd55..cb72d7324ec 100644 --- a/langtools/test/tools/javac/diags/examples/WhereIntersection.java +++ b/langtools/test/tools/javac/diags/examples/WhereIntersection.java @@ -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 diff --git a/langtools/test/tools/javac/diags/examples/WhereTypeVar.java b/langtools/test/tools/javac/diags/examples/WhereTypeVar.java index 1808efdea48..ad7d494991a 100644 --- a/langtools/test/tools/javac/diags/examples/WhereTypeVar.java +++ b/langtools/test/tools/javac/diags/examples/WhereTypeVar.java @@ -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 diff --git a/langtools/test/tools/javac/diags/examples/WrongContainedBy.java b/langtools/test/tools/javac/diags/examples/WrongContainedBy.java new file mode 100644 index 00000000000..6914c4bd64e --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/WrongContainedBy.java @@ -0,0 +1,35 @@ +/* + * 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. + */ + +// key: compiler.err.invalid.container.no.containerfor +// key: compiler.err.invalid.container.wrong.containedby + +import java.lang.annotation.*; + +@ContainerFor(WrongContainedBy.class) +@interface Foos { + WrongContainedBy[] value(); +} + +@ContainedBy(Target.class) +public @interface WrongContainedBy {} diff --git a/langtools/test/tools/javac/diags/examples/WrongContainerFor.java b/langtools/test/tools/javac/diags/examples/WrongContainerFor.java new file mode 100644 index 00000000000..e439b780fbe --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/WrongContainerFor.java @@ -0,0 +1,35 @@ +/* + * 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. + */ + +// key: compiler.err.invalid.container.wrong.containerfor +// key: compiler.err.invalid.container.no.containedby + +import java.lang.annotation.*; + +@ContainerFor(Retention.class) +@interface Foos { + WrongContainerFor[] value(); +} + +@ContainedBy(Foos.class) +public @interface WrongContainerFor {} diff --git a/langtools/test/tools/javac/generics/typevars/T7148242.java b/langtools/test/tools/javac/generics/typevars/T7148242.java index 1080c0d0ff5..2a9a54295cc 100644 --- a/langtools/test/tools/javac/generics/typevars/T7148242.java +++ b/langtools/test/tools/javac/generics/typevars/T7148242.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 diff --git a/langtools/test/tools/javac/newlines/Newlines.sh b/langtools/test/tools/javac/newlines/Newlines.sh index ccb30c65e99..5ea844c11f1 100644 --- a/langtools/test/tools/javac/newlines/Newlines.sh +++ b/langtools/test/tools/javac/newlines/Newlines.sh @@ -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 diff --git a/langtools/test/tools/javac/parser/T4881269.java b/langtools/test/tools/javac/parser/T4881269.java index c830a4e822a..8c5ca9b6fa9 100644 --- a/langtools/test/tools/javac/parser/T4881269.java +++ b/langtools/test/tools/javac/parser/T4881269.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/langtools/test/tools/javac/processing/6348499/T6348499.java b/langtools/test/tools/javac/processing/6348499/T6348499.java index 25e2a07a03f..d85a39d4526 100644 --- a/langtools/test/tools/javac/processing/6348499/T6348499.java +++ b/langtools/test/tools/javac/processing/6348499/T6348499.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -47,6 +47,7 @@ public class T6348499 { public static void main(String... args) { String testSrc = System.getProperty("test.src", "."); String testClasses = System.getProperty("test.classes"); + String testClassPath = System.getProperty("test.class.path", testClasses); String A_java = new File(testSrc, "A.java").getPath(); JavacTool tool = JavacTool.create(); MyDiagListener dl = new MyDiagListener(); @@ -55,7 +56,7 @@ public class T6348499 { fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrc, "A.java"))); Iterable<String> opts = Arrays.asList("-proc:only", "-processor", "A", - "-processorpath", testClasses); + "-processorpath", testClassPath); StringWriter out = new StringWriter(); JavacTask task = tool.getTask(out, fm, dl, opts, null, files); task.call(); diff --git a/langtools/test/tools/javac/processing/6414633/T6414633.java b/langtools/test/tools/javac/processing/6414633/T6414633.java index 0ae395153cb..06729a68f43 100644 --- a/langtools/test/tools/javac/processing/6414633/T6414633.java +++ b/langtools/test/tools/javac/processing/6414633/T6414633.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -43,20 +43,20 @@ public class T6414633 { public static void main(String... args) { String testSrc = System.getProperty("test.src", "."); String testClasses = System.getProperty("test.classes", "."); + String testClassPath = System.getProperty("test.class.path", testClasses); JavacTool tool = JavacTool.create(); MyDiagListener dl = new MyDiagListener(); StandardJavaFileManager fm = tool.getStandardFileManager(dl, null, null); try { - fm.setLocation(StandardLocation.CLASS_PATH, Arrays.asList(new File(testClasses))); + fm.setLocation(StandardLocation.CLASS_PATH, pathToFiles(testClassPath)); } catch (IOException e) { throw new AssertionError(e); } Iterable<? extends JavaFileObject> files = fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrc, A.class.getName()+".java"))); String[] opts = { "-proc:only", - "-processor", A.class.getName(), - "-classpath", testClasses + System.getProperty("path.separator") + "../../lib" }; + "-processor", A.class.getName() }; JavacTask task = tool.getTask(null, fm, dl, Arrays.asList(opts), null, files); task.call(); @@ -65,6 +65,15 @@ public class T6414633 { throw new AssertionError(dl.diags + " diagnostics reported"); } + private static List<File> pathToFiles(String path) { + List<File> list = new ArrayList<File>(); + for (String s: path.split(File.pathSeparator)) { + if (!s.isEmpty()) + list.add(new File(s)); + } + return list; + } + private static class MyDiagListener implements DiagnosticListener<JavaFileObject> { public void report(Diagnostic d) { diff --git a/langtools/test/tools/javac/processing/T6920317.java b/langtools/test/tools/javac/processing/T6920317.java index 1f005090361..2308f626398 100644 --- a/langtools/test/tools/javac/processing/T6920317.java +++ b/langtools/test/tools/javac/processing/T6920317.java @@ -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 @@ -156,7 +156,9 @@ public class T6920317 { String expect = null; opts.add("-processorpath"); - opts.add(System.getProperty("test.classes")); + String testClasses = System.getProperty("test.classes"); + String testClassPath = System.getProperty("test.class.path", testClasses); + opts.add(testClassPath); opts.add("-processor"); opts.add(Processor.class.getName()); opts.add("-proc:only"); diff --git a/langtools/test/tools/javac/processing/TestWarnErrorCount.java b/langtools/test/tools/javac/processing/TestWarnErrorCount.java index 7af968877c0..f2bdef0a2a4 100644 --- a/langtools/test/tools/javac/processing/TestWarnErrorCount.java +++ b/langtools/test/tools/javac/processing/TestWarnErrorCount.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/langtools/test/tools/javac/processing/options/testPrintProcessorInfo/TestWithXstdout.java b/langtools/test/tools/javac/processing/options/testPrintProcessorInfo/TestWithXstdout.java index e11a39f48c8..0163b2742f7 100644 --- a/langtools/test/tools/javac/processing/options/testPrintProcessorInfo/TestWithXstdout.java +++ b/langtools/test/tools/javac/processing/options/testPrintProcessorInfo/TestWithXstdout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,8 @@ import java.util.*; public class TestWithXstdout { public static void main(String... args) throws Exception { File testSrc = new File(System.getProperty("test.src")); - File testClasses = new File(System.getProperty("test.classes")); + String testClasses = System.getProperty("test.classes", "."); + String testClassPath = System.getProperty("test.class.path", testClasses); File stdout = new File("stdout.out"); run_javac("-XDrawDiagnostics", "-XprintProcessorInfo", @@ -46,7 +47,7 @@ public class TestWithXstdout { "-proc:only", "-processor", "Test", "-Xstdout", stdout.getPath(), - "-classpath", testClasses.getPath(), + "-classpath", testClassPath, new File(testSrc, "Test.java").getPath()); boolean ok = compare(stdout, new File(testSrc, "Test.out")); if (!ok) diff --git a/langtools/test/tools/javah/T7185778.java b/langtools/test/tools/javah/T7185778.java new file mode 100644 index 00000000000..0f45f2b33a1 --- /dev/null +++ b/langtools/test/tools/javah/T7185778.java @@ -0,0 +1,56 @@ +/* + * 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 7185778 + * @summary javah error "Not a valid class name" on class names with dollar signs + * The first two tests are on an inner class name whose name does not contain $. + * The second two tests are on an inner class name whose name does contain $. + * The last test is on an outer class whose name contains $. + * @run main T7185778 T7185778$inner + * @run main T7185778 T7185778.inner + * @run main T7185778 T7185778$inner$ + * @run main T7185778 T7185778.inner$ + * @run main T7185778 xx$yy + */ + +public class T7185778 { + class inner { + native byte[] xxxxx(String name); + } + class inner$ { + native byte[] xxxxx(String name); + } + + static public void main(String[] args) { + int rc = com.sun.tools.javah.Main.run(args, null); + if ( rc != 0) { + throw new Error("javah returned non zero: " + rc); + } + } +} + +class xx$yy { + native byte[] xxxxx(String name); +} diff --git a/make/scripts/hgforest.sh b/make/scripts/hgforest.sh index 5906f721c87..ed937f3711e 100644 --- a/make/scripts/hgforest.sh +++ b/make/scripts/hgforest.sh @@ -58,7 +58,7 @@ if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then fi done if [ "${pull_extra_base}" != "" ] ; then - subrepos_extra="jdk/src/closed jdk/make/closed jdk/test/closed hotspot/src/closed hotspot/test/closed deploy install sponsors pubs" + subrepos_extra="jdk/src/closed jdk/make/closed jdk/test/closed hotspot/make/closed hotspot/src/closed hotspot/test/closed deploy install sponsors pubs" pull_default_tail=`echo ${pull_default} | sed -e 's@^.*://[^/]*/\(.*\)@\1@'` pull_extra="${pull_extra_base}/${pull_default_tail}" for i in ${subrepos_extra} ; do