From b6622dce73509b92a0aaabfdcfcf97d939ec0451 Mon Sep 17 00:00:00 2001 From: Joseph Provino Date: Wed, 8 Aug 2012 15:43:51 -0400 Subject: [PATCH 01/53] 7153374: ARM ONLY .. linking problem with new compilers.. Need to use -fPIC Add "arm" to the list of processors that need -fPIC Reviewed-by: vladidan, dholmes --- hotspot/make/pic.make | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 12a8d1286308cba4b9a28b218e0e6c9131c66dda Mon Sep 17 00:00:00 2001 From: Steve Sides Date: Wed, 15 Aug 2012 13:48:46 -0700 Subject: [PATCH 02/53] 7191449: update copyright year to match last edit in jdk8 langtools repository Reviewed-by: jjh --- langtools/make/jprt.properties | 2 +- langtools/make/tools/anttasks/CompilePropertiesTask.java | 2 +- langtools/make/tools/anttasks/GenStubsTask.java | 2 +- langtools/make/tools/anttasks/SelectToolTask.java | 2 +- langtools/make/tools/compileproperties/CompileProperties.java | 2 +- langtools/make/tools/genstubs/GenStubs.java | 2 +- .../src/share/classes/com/sun/tools/javac/code/Source.java | 2 +- langtools/src/share/classes/com/sun/tools/javac/code/Type.java | 2 +- .../src/share/classes/com/sun/tools/javac/comp/AttrContext.java | 2 +- .../src/share/classes/com/sun/tools/javac/comp/TransTypes.java | 2 +- .../share/classes/com/sun/tools/javac/file/ZipFileIndex.java | 2 +- langtools/src/share/classes/com/sun/tools/javac/main/Main.java | 2 +- .../com/sun/tools/javac/util/RichDiagnosticFormatter.java | 2 +- .../test/tools/javac/ProtectedInnerClass/ProtectedInnerClass.sh | 2 +- langtools/test/tools/javac/api/7086261/T7086261.java | 2 +- langtools/test/tools/javac/api/T6397104.java | 2 +- langtools/test/tools/javac/diags/CheckExamples.java | 2 +- langtools/test/tools/javac/diags/MessageInfo.java | 2 +- langtools/test/tools/javac/diags/RunExamples.java | 2 +- .../test/tools/javac/diags/examples/ApplicableMethodFound1.java | 2 +- langtools/test/tools/javac/diags/examples/IllegalDot.java | 2 +- .../test/tools/javac/diags/examples/InconvertibleTypes.java | 2 +- .../test/tools/javac/diags/examples/KindnameConstructor.java | 2 +- .../tools/javac/diags/examples/NotApplicableMethodFound.java | 2 +- .../test/tools/javac/diags/examples/PossibleLossPrecision.java | 2 +- .../tools/javac/diags/examples/ResourceNotApplicableToType.java | 2 +- .../tools/javac/diags/examples/VarargsArgumentMismatch.java | 2 +- .../test/tools/javac/diags/examples/VerboseResolveMulti1.java | 2 +- langtools/test/tools/javac/diags/examples/WhereCaptured.java | 2 +- langtools/test/tools/javac/diags/examples/WhereCaptured1.java | 2 +- .../test/tools/javac/diags/examples/WhereIntersection.java | 2 +- langtools/test/tools/javac/diags/examples/WhereTypeVar.java | 2 +- langtools/test/tools/javac/generics/typevars/T7148242.java | 2 +- langtools/test/tools/javac/newlines/Newlines.sh | 2 +- langtools/test/tools/javac/parser/T4881269.java | 2 +- langtools/test/tools/javac/processing/TestWarnErrorCount.java | 2 +- 36 files changed, 36 insertions(+), 36 deletions(-) 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/Source.java b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java index 5abee40481a..9fcbba44709 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 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/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/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/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/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/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/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/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/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/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/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/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 From 6490b69f576a5b16d92e7d311b1bfa72d0ef08de Mon Sep 17 00:00:00 2001 From: David MacDonald Date: Thu, 16 Aug 2012 10:33:01 +0100 Subject: [PATCH 03/53] 7056731: Race condition in CORBA code causes re-use of ABORTed connections Reviewed-by: lancea --- .../CorbaResponseWaitingRoomImpl.java | 73 +++++++++++-------- .../SocketOrChannelConnectionImpl.java | 5 +- 2 files changed, 46 insertions(+), 32 deletions(-) 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 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()); } //////////////////////////////////////////////////// @@ -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 From 5d2e65169c4f155d33302e041f9ed99e18364ed2 Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Fri, 17 Aug 2012 09:49:42 -0700 Subject: [PATCH 04/53] 7191547: XMLEventFactory.newFactory(String factoryId, ClassLoader loader) does not work as expected Similar to the patch for 6756677 for XMLInputFactory and XMLOutputFactory, this patch fixes an error in XMLEventFactory where factoryId was taken as factory class. Reviewed-by: lancea --- jaxp/src/javax/xml/stream/XMLEventFactory.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) 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()); From 9d9d7877aac5b107b49b1cc917ad04e72fe5aba2 Mon Sep 17 00:00:00 2001 From: John R Rose Date: Fri, 17 Aug 2012 13:42:25 -0700 Subject: [PATCH 05/53] 7191102: nightly failures after JSR 292 lazy method handle update (round 3) Reviewed-by: twisti, kvn --- .../java/lang/invoke/BoundMethodHandle.java | 5 + .../java/lang/invoke/DirectMethodHandle.java | 4 +- .../lang/invoke/InvokerBytecodeGenerator.java | 17 +- .../classes/java/lang/invoke/Invokers.java | 144 ++- .../classes/java/lang/invoke/LambdaForm.java | 21 +- .../java/lang/invoke/MethodHandle.java | 10 +- .../java/lang/invoke/MethodHandleImpl.java | 123 +- .../java/lang/invoke/MethodHandleNatives.java | 30 +- .../java/lang/invoke/MethodHandles.java | 11 + .../classes/java/lang/invoke/MethodType.java | 34 +- .../java/lang/invoke/SimpleMethodHandle.java | 6 +- .../lang/invoke/WrongMethodTypeException.java | 23 + .../sun/invoke/util/ValueConversions.java | 265 +++-- jdk/test/java/lang/invoke/BigArityTest.java | 1044 +++++++++++++++++ jdk/test/java/lang/invoke/MaxTest.java | 143 --- .../java/lang/invoke/MethodHandlesTest.java | 93 +- .../java/lang/invoke/PermuteArgsTest.java | 6 +- jdk/test/java/lang/invoke/RicochetTest.java | 68 +- .../sun/invoke/util/ValueConversionsTest.java | 10 +- 19 files changed, 1672 insertions(+), 385 deletions(-) create mode 100644 jdk/test/java/lang/invoke/BigArityTest.java delete mode 100644 jdk/test/java/lang/invoke/MaxTest.java 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 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/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. 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 slots + * 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/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() { + @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[] 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_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 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 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 TYPED_COLLECTORS = new ClassValue() { + @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 objArrayType = (Class) 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.>nCopies(nargs, elemType))); - cache[nargs] = mh; + assert(assertCorrectArity(mh, nargs)); + if (nargs < cache.length) + cache[nargs] = mh; return mh; } 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 arrayClass, int arity) { + if (arrayClass == Object[].class) + return MH_hashArguments(arity); + ArrayList> ptypes = new ArrayList<>(Collections.>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 cls = (Class) cls0; + //Class 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 cls = (Class) 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 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 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( + // + 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, + // + Object xF8, Object xF9, Object xFA, Object xFB) { + return Objects.hash( + // + 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, + // + 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( + // + 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], + // + 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( + // + 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], + // + 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, + // + 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], + // + 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, + // + (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], + // + 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( + // + 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], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB]); + assertEquals(r0, r); + r = mh.invoke( + // + (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], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB]); + assertEquals(r0, r); + } + + static Object hashArguments_253( + // + 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, + // + Object xF8, Object xF9, Object xFA, Object xFB, Object xFC) { + return Objects.hash( + // + 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, + // + 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( + // + 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], + // + 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( + // + 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], + // + 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, + // + 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], + // + 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, + // + (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], + // + 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( + // + 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], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); + assertEquals(r0, r); + r = mh.invoke( + // + (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], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC]); + assertEquals(r0, r); + } + + static Object hashArguments_254( + // + 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, + // + Object xF8, Object xF9, Object xFA, Object xFB, Object xFC, Object xFD) { + return Objects.hash( + // + 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, + // + 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( + // + 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], + // + 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( + // + 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], + // + 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( + // + 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], + // + 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( + // + 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], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); + assertEquals(r0, r); + r = mh.invoke( + // + (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], + // + a[0xF8], a[0xF9], a[0xFA], a[0xFB], a[0xFC], a[0xFD]); + assertEquals(r0, r); + } + + static Object hashArguments_255( + // + 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, + // + Object xF8, Object xF9, Object xFA, Object xFB, Object xFC, Object xFD, Object xFE) { + return Objects.hash( + // + 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, + // + 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( + // + 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], + // + 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( + // + 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], + // + 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..96607ed6ee2 100644 --- a/jdk/test/java/lang/invoke/PermuteArgsTest.java +++ b/jdk/test/java/lang/invoke/PermuteArgsTest.java @@ -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) From c1ee469435d4dad00b4ed521773a50ef08ca9c16 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 17 Aug 2012 17:30:03 -0700 Subject: [PATCH 06/53] 7192449: fix up tests to accommodate jtreg spec change Reviewed-by: darcy --- .../javac/processing/6414633/T6414633.java | 17 +++++++++++++---- .../testPrintProcessorInfo/TestWithXstdout.java | 7 ++++--- 2 files changed, 17 insertions(+), 7 deletions(-) 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 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 pathToFiles(String path) { + List list = new ArrayList(); + for (String s: path.split(File.pathSeparator)) { + if (!s.isEmpty()) + list.add(new File(s)); + } + return list; + } + private static class MyDiagListener implements DiagnosticListener { public void report(Diagnostic d) { 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) From 6214b5d9062e0923b8d7a13759d056067d2fd81d Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Mon, 20 Aug 2012 21:24:10 +0530 Subject: [PATCH 07/53] 7181320: javac NullPointerException for switch labels with cast to String expressions Reviewed-by: mcimadamore --- .../com/sun/tools/javac/code/Types.java | 9 ++++- .../com/sun/tools/javac/comp/Lower.java | 1 - .../7181320/BinOpInCaseLabel.java | 38 ++++++++++++++++++ .../7181320/CastInCaseLabel.java | 38 ++++++++++++++++++ .../7181320/CondExprInCaseLabel.java | 39 +++++++++++++++++++ .../7181320/CondExprInCaseLabel1.java | 39 +++++++++++++++++++ .../7181320/CondExprInCaseLabel2.java | 39 +++++++++++++++++++ 7 files changed, 201 insertions(+), 2 deletions(-) create mode 100644 langtools/test/tools/javac/StringsInSwitch/7181320/BinOpInCaseLabel.java create mode 100644 langtools/test/tools/javac/StringsInSwitch/7181320/CastInCaseLabel.java create mode 100644 langtools/test/tools/javac/StringsInSwitch/7181320/CondExprInCaseLabel.java create mode 100644 langtools/test/tools/javac/StringsInSwitch/7181320/CondExprInCaseLabel1.java create mode 100644 langtools/test/tools/javac/StringsInSwitch/7181320/CondExprInCaseLabel2.java 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..98f081a6686 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 @@ -1589,9 +1589,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 */ 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..1590ee79293 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 @@ -3499,7 +3499,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/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; + } + } +} From 504f41de5de82066debfeadeaaa326ce274bb1c8 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 20 Aug 2012 13:50:04 -0700 Subject: [PATCH 08/53] 7192744: fix up tests to accommodate jtreg spec change Reviewed-by: darcy --- langtools/test/tools/javac/processing/6348499/T6348499.java | 5 +++-- langtools/test/tools/javac/processing/T6920317.java | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) 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 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/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"); From 6d8fa095b302c373a391b4387aee3428969945c4 Mon Sep 17 00:00:00 2001 From: Staffan Larsen Date: Wed, 22 Aug 2012 10:01:51 +0200 Subject: [PATCH 09/53] 7192916: Hotspot development launcher should use DYLD_LIBRARY_PATH on OS X Reviewed-by: dholmes, dsamersoff, nloodin --- hotspot/src/os/posix/launcher/launcher.script | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) 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 From 68bbfe24e7ea376ae9976a9fa5c126d6c6691e31 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Thu, 23 Aug 2012 10:21:12 +0200 Subject: [PATCH 10/53] 7178363: G1: Remove the serial code for PrintGCDetails and make it a special case of the parallel code Also reviewed by vitalyd@gmail.com. Introduced the WorkerDataArray class. Fixed some minor logging bugs. Reviewed-by: johnc, mgerdin --- .../gc_implementation/g1/g1CollectedHeap.cpp | 117 +++--- .../gc_implementation/g1/g1CollectedHeap.hpp | 4 + .../g1/g1CollectorPolicy.cpp | 73 ++-- .../g1/g1CollectorPolicy.hpp | 1 + .../gc_implementation/g1/g1GCPhaseTimes.cpp | 366 ++++++++---------- .../gc_implementation/g1/g1GCPhaseTimes.hpp | 285 +++++++++----- .../vm/gc_implementation/g1/g1RemSet.cpp | 2 +- hotspot/src/share/vm/runtime/arguments.cpp | 2 +- 8 files changed, 460 insertions(+), 390 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index d0b0a79f586..6eb8f73deae 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(); @@ -2327,8 +2339,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 +3746,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 +3777,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 +3990,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 +4022,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 +4046,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 @@ -4863,7 +4884,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 +5012,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. @@ -5647,11 +5669,6 @@ 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("--"); - } } // 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..e92c8eaf135 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. 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 +void WorkerDataArray::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 +void WorkerDataArray::reset() { + for (uint i = 0; i < _length; i++) { + _data[i] = (T)-1; + } +} + +template +void WorkerDataArray::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 WorkerDataArray : public CHeapObj { + 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 { - 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 _last_gc_worker_start_times_ms; + WorkerDataArray _last_ext_root_scan_times_ms; + WorkerDataArray _last_satb_filtering_times_ms; + WorkerDataArray _last_update_rs_times_ms; + WorkerDataArray _last_update_rs_processed_buffers; + WorkerDataArray _last_scan_rs_times_ms; + WorkerDataArray _last_obj_copy_times_ms; + WorkerDataArray _last_termination_times_ms; + WorkerDataArray _last_termination_attempts; + WorkerDataArray _last_gc_worker_end_times_ms; + WorkerDataArray _last_gc_worker_times_ms; + WorkerDataArray _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 { 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 { 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 { 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/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; } From 2271c9dfad0e2de4e435cf4ee83e7c963cb319e7 Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Fri, 24 Aug 2012 16:23:59 -0700 Subject: [PATCH 11/53] 7194004: new hotspot build - hs24-b22 Reviewed-by: jcoomes --- hotspot/make/hotspot_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 398a74ffa0baa7fad1abbbcedb13a4961ef3f33a Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 27 Aug 2012 07:21:46 -0700 Subject: [PATCH 12/53] 7192068: (javac) provide a way for IDEs to produce Enclosing Method attributes Reviewed-by: jjg --- .../com/sun/tools/javac/jvm/ClassReader.java | 56 +++++++++---------- .../com/sun/tools/javac/jvm/ClassWriter.java | 25 +++++++-- 2 files changed, 49 insertions(+), 32 deletions(-) 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..f7dc3669607 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 kinds) { + protected AttributeReader(Name name, ClassFile.Version version, Set 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 kinds; + protected final Name name; + protected final ClassFile.Version version; + protected final Set kinds; } protected Set 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 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 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..ac5b1387673 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 @@ -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()) From f0d08c04f1312045c5e6f77935b04fe90967a186 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Mon, 27 Aug 2012 09:46:38 -0700 Subject: [PATCH 13/53] 7148109: C2 compiler consumes too much heap resources Add split_arena to allocate temporary arrays in PhaseChaitin::Split() and free them on method's exit. Reviewed-by: twisti --- hotspot/src/share/vm/opto/chaitin.cpp | 5 +++-- hotspot/src/share/vm/opto/chaitin.hpp | 2 +- hotspot/src/share/vm/opto/reg_split.cpp | 30 ++++++++++++++++--------- 3 files changed, 23 insertions(+), 14 deletions(-) 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/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 lidxs; + GrowableArray lidxs(split_arena, _maxlrg, 0, 0); // Array of counters to count splits per live range - GrowableArray splits; + GrowableArray 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---------- From 447e7065d20c22ba8be867be1ecb033ee76633d8 Mon Sep 17 00:00:00 2001 From: Tao Mao Date: Mon, 27 Aug 2012 15:17:17 -0700 Subject: [PATCH 14/53] 6677625: Move platform specific flags from globals.hpp to globals_.hpp Reviewed-by: kvn, dholmes, coleenp --- hotspot/src/cpu/sparc/vm/globals_sparc.hpp | 41 ++- hotspot/src/cpu/x86/vm/globals_x86.hpp | 51 +++- hotspot/src/cpu/zero/vm/globals_zero.hpp | 5 +- hotspot/src/share/vm/c1/c1_globals.hpp | 11 +- hotspot/src/share/vm/opto/c2_globals.hpp | 128 ++++++-- hotspot/src/share/vm/opto/runtime.cpp | 40 --- hotspot/src/share/vm/runtime/globals.cpp | 18 +- hotspot/src/share/vm/runtime/globals.hpp | 285 +----------------- .../share/vm/runtime/globals_extension.hpp | 32 +- 9 files changed, 252 insertions(+), 359 deletions(-) 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/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/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/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/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; From 03930364c82435e00af762d366396e90c48b2a79 Mon Sep 17 00:00:00 2001 From: John R Rose Date: Tue, 28 Aug 2012 13:14:59 -0700 Subject: [PATCH 15/53] 7194612: api/java_lang/invoke/MethodHandles/Lookup/index.html#ExceptionsTests[findVirtualNSME] fails w/ -esa Reviewed-by: kvn, twisti --- jdk/src/share/classes/java/lang/invoke/MemberName.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) 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() { From e48b871bdc4c9633fd1acc600863a7e3432e768b Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Tue, 28 Aug 2012 14:57:43 -0700 Subject: [PATCH 16/53] 7194662: JSR 292: PermuteArgsTest times out in nightly test runs Reviewed-by: kvn --- jdk/test/java/lang/invoke/PermuteArgsTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/test/java/lang/invoke/PermuteArgsTest.java b/jdk/test/java/lang/invoke/PermuteArgsTest.java index 96607ed6ee2..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 From eb2c52c7170431c0ddfc12b1d6ae99786a382cda Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Tue, 28 Aug 2012 15:20:08 -0700 Subject: [PATCH 17/53] 7041879: G1: introduce stress testing parameter to cause frequent evacuation failures Add the flags G1EvacuationFailureALot flag (and supporting flags) to force trigger evacuation failures. The support flags control how often to trigger an evacuation failure and during which types of evacuation pause. This functionality is analogous to that of PromotionFailureALot for the other collectors. Reviewed-by: brutisso --- .../gc_implementation/g1/g1CollectedHeap.cpp | 23 +++++- .../gc_implementation/g1/g1CollectedHeap.hpp | 33 ++++++++ .../g1/g1CollectedHeap.inline.hpp | 77 ++++++++++++++++++- .../vm/gc_implementation/g1/g1_globals.hpp | 30 +++++++- 4 files changed, 159 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 6eb8f73deae..42ec32d8b2e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -1945,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. @@ -4564,7 +4567,15 @@ oop G1ParCopyClosure 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 @@ -4573,6 +4584,8 @@ oop G1ParCopyClosure 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); @@ -5578,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(); @@ -5669,6 +5685,11 @@ void G1CollectedHeap::evacuate_collection_set() { if (evacuation_failed()) { remove_self_forwarding_pointers(); + + // 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 e92c8eaf135..facc576f77b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -915,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/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) From 40c1bd42425ff8b4b4a52c59b2ee2e5dc2ebe700 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Tue, 28 Aug 2012 15:24:39 -0700 Subject: [PATCH 18/53] 7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites Reviewed-by: kvn --- hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 16 +- hotspot/src/share/vm/c1/c1_GraphBuilder.hpp | 2 +- hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp | 29 ++-- hotspot/src/share/vm/ci/ciEnv.cpp | 150 ++++++++---------- hotspot/src/share/vm/ci/ciEnv.hpp | 3 - hotspot/src/share/vm/ci/ciMethod.cpp | 5 +- hotspot/src/share/vm/ci/ciStreams.cpp | 45 +++--- hotspot/src/share/vm/ci/ciStreams.hpp | 6 +- hotspot/src/share/vm/ci/ciTypeFlow.cpp | 29 ++-- .../src/share/vm/interpreter/bytecodes.hpp | 2 + hotspot/src/share/vm/opto/doCall.cpp | 46 +++--- hotspot/src/share/vm/opto/graphKit.cpp | 12 +- 12 files changed, 164 insertions(+), 181 deletions(-) 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/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/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/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; From 31ec802d7e68c4e7e53d84910572c3644ac95323 Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Wed, 29 Aug 2012 15:54:28 +0400 Subject: [PATCH 19/53] 7171045: [macosx] There are no enter or exit events reported against 8b39 for MouseEventsDuringDrag Reviewed-by: anthony, serb --- .../classes/sun/lwawt/LWWindowPeer.java | 153 +++++++++++------- .../classes/sun/lwawt/PlatformWindow.java | 2 + .../lwawt/macosx/CPlatformEmbeddedFrame.java | 4 + .../sun/lwawt/macosx/CPlatformWindow.java | 11 +- jdk/src/macosx/native/sun/awt/AWTView.h | 6 +- jdk/src/macosx/native/sun/awt/AWTView.m | 34 ++-- jdk/src/macosx/native/sun/awt/AWTWindow.m | 122 +++++++++----- 7 files changed, 211 insertions(+), 121 deletions(-) diff --git a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java index 3b7cb79728c..83e7d5d7778 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 @@ -707,66 +713,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; @@ -816,19 +821,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 +851,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, @@ -1096,11 +1127,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; } /* 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/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); From 18e3872928aac59aa0443ecff3a20423fe315dfb Mon Sep 17 00:00:00 2001 From: Leonid Romanov Date: Wed, 29 Aug 2012 19:53:35 +0400 Subject: [PATCH 20/53] 7124375: [macosx] Focus isn't transfered as expected between components Reviewed-by: art, ant, serb --- .../classes/sun/lwawt/LWComponentPeer.java | 24 +++--- .../sun/lwawt/LWKeyboardFocusManagerPeer.java | 74 +++++-------------- .../macosx/classes/sun/lwawt/LWToolkit.java | 4 +- .../classes/sun/lwawt/LWWindowPeer.java | 23 +++--- .../java/awt/KeyboardFocusManager.java | 3 +- .../awt/peer/KeyboardFocusManagerPeer.java | 8 ++ jdk/src/share/classes/sun/awt/HToolkit.java | 18 +++-- .../classes/sun/awt/HeadlessToolkit.java | 23 +++--- .../sun/awt/KeyboardFocusManagerPeerImpl.java | 6 -- .../awt/KeyboardFocusManagerPeerProvider.java | 9 +-- jdk/src/share/classes/sun/awt/SunToolkit.java | 3 +- .../classes/sun/awt/X11/XComponentPeer.java | 2 +- .../classes/sun/awt/X11/XDecoratedPeer.java | 4 +- .../classes/sun/awt/X11/XDialogPeer.java | 2 +- .../sun/awt/X11/XEmbedChildProxyPeer.java | 9 ++- .../sun/awt/X11/XEmbedClientHelper.java | 2 +- .../awt/X11/XKeyboardFocusManagerPeer.java | 63 ++++++---------- .../solaris/classes/sun/awt/X11/XToolkit.java | 8 +- .../classes/sun/awt/X11/XWindowPeer.java | 20 ++--- .../windows/WKeyboardFocusManagerPeer.java | 16 +++- .../classes/sun/awt/windows/WToolkit.java | 4 +- 21 files changed, 137 insertions(+), 188 deletions(-) diff --git a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java index 76d8161c749..7f556aca166 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 ", 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 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; } @@ -1263,8 +1263,8 @@ public abstract class LWComponentPeer 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 instances = - new HashMap(); - - 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 83e7d5d7778..41e266a9be0 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -238,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()) { @@ -248,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) { @@ -915,9 +914,8 @@ public class LWWindowPeer public void dispatchKeyEvent(int id, long when, int modifiers, int keyCode, char keyChar, int keyLocation) { - LWComponentPeer focusOwner = - LWKeyboardFocusManagerPeer.getInstance(getAppContext()). - getFocusOwner(); + KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); + Component focusOwner = kfmPeer.getCurrentFocusOwner(); // Null focus owner may receive key event when // application hides the focused window upon ESC press @@ -925,9 +923,10 @@ public class LWWindowPeer // may come to already hidden window. This check eliminates NPE. if (focusOwner != null) { KeyEvent event = - new KeyEvent(focusOwner.getTarget(), id, when, modifiers, + new KeyEvent(focusOwner, id, when, modifiers, keyCode, keyChar, keyLocation); - focusOwner.postEvent(event); + LWComponentPeer peer = (LWComponentPeer)focusOwner.getPeer(); + peer.postEvent(event); } } @@ -1244,10 +1243,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. @@ -1260,7 +1257,7 @@ 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); diff --git a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java index 15fe15356c2..c172b429e1c 100644 --- a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java +++ b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java @@ -56,7 +56,6 @@ import java.util.WeakHashMap; import sun.util.logging.PlatformLogger; import sun.awt.AppContext; -import sun.awt.HeadlessToolkit; import sun.awt.SunToolkit; import sun.awt.CausedFocusEvent; import sun.awt.KeyboardFocusManagerPeerProvider; @@ -443,7 +442,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/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/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..d0794ffb1ee 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) { 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 68ec628b6ed..66985835fba 100644 --- a/jdk/src/share/classes/sun/awt/SunToolkit.java +++ b/jdk/src/share/classes/sun/awt/SunToolkit.java @@ -53,7 +53,6 @@ import sun.security.action.GetPropertyAction; import sun.security.action.GetBooleanAction; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.security.AccessController; import java.security.PrivilegedAction; @@ -204,7 +203,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; /** diff --git a/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java index 96e47213c46..643767068fa 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XComponentPeer.java @@ -601,7 +601,7 @@ public class XComponentPeer extends XWindow implements ComponentPeer, DropTarget final XWindowPeer parentXWindow = getParentTopLevel(); Window parentWindow = (Window)parentXWindow.getTarget(); if (parentXWindow.isFocusableWindow() && parentXWindow.isSimpleWindow() && - XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() != parentWindow) + XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() != parentWindow) { postEvent(new InvocationEvent(parentWindow, new Runnable() { public void run() { 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 e49f78338d2..c911374d4db 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java @@ -50,7 +50,6 @@ import javax.swing.LookAndFeel; import javax.swing.UIDefaults; import sun.awt.*; import sun.font.FontConfigManager; -import sun.font.FontManager; import sun.java2d.SunGraphicsEnvironment; import sun.misc.PerformanceLogger; import sun.print.PrintJob2D; @@ -667,7 +666,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) { @@ -1159,9 +1158,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..faa8ff0da74 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; @@ -1185,7 +1185,7 @@ 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(); } @@ -1825,7 +1825,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/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); From 373b8ccd272c94f3320e1505dcf0079a06d564d3 Mon Sep 17 00:00:00 2001 From: Pavel Punegov Date: Wed, 29 Aug 2012 14:49:05 -0400 Subject: [PATCH 21/53] 7191926: Remove MKS dependency in Hotspot regression tests Add case for CYGWIN in .sh files. Reviewed-by: coleenp, kvn --- hotspot/test/compiler/6894807/Test6894807.sh | 5 +++++ hotspot/test/gc/6941923/test6941923.sh | 2 +- hotspot/test/runtime/6626217/Test6626217.sh | 8 ++++++++ hotspot/test/runtime/6878713/Test6878713.sh | 5 +++++ hotspot/test/runtime/7020373/Test7020373.sh | 5 +++++ hotspot/test/runtime/7051189/Xchecksig.sh | 2 +- hotspot/test/runtime/7110720/Test7110720.sh | 6 ++++++ hotspot/test/runtime/7158800/Test7158800.sh | 5 +++++ hotspot/test/runtime/7158988/TestFieldMonitor.sh | 12 ++++++++++++ 9 files changed, 48 insertions(+), 2 deletions(-) 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; From da65cc4532632822e20090bc184874d1394b74d8 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Wed, 29 Aug 2012 13:02:40 -0700 Subject: [PATCH 22/53] 7160161: Missed safepoint in non-Counted loop Do not remove safepoints during peeling optimization. Reviewed-by: twisti --- hotspot/src/share/vm/opto/loopTransform.cpp | 5 -- hotspot/src/share/vm/opto/loopnode.cpp | 64 ++++++++++++++------- hotspot/src/share/vm/opto/loopnode.hpp | 2 + 3 files changed, 45 insertions(+), 26 deletions(-) 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) From f51faf2bbeaf137e633a8f6d31bb292f6a6dc7f4 Mon Sep 17 00:00:00 2001 From: Brandon Mitchell Date: Wed, 29 Aug 2012 13:02:54 -0700 Subject: [PATCH 23/53] 7194409: os::javaTimeNanos() shows hot on CPU_CLK_UNHALTED profiles Add inline directives to os::Linux::supports_monotonic_clock() and os::Bsd::supports_monotonic_clock(). Reviewed-by: johnc, azeemj, mikael --- hotspot/src/os/bsd/vm/os_bsd.hpp | 4 ++-- hotspot/src/os/linux/vm/os_linux.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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; } From ac4a9defcaab0144dc437a44152b46d5bafcf417 Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Thu, 30 Aug 2012 01:17:24 +0400 Subject: [PATCH 24/53] 7192887: java/awt/Window/Grab/GrabTest.java still failed (fix failed for CR 7149068) Reviewed-by: ant, serb --- jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java index faa8ff0da74..a6af2e776d2 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java @@ -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(); @@ -1191,6 +1201,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer, } } } + boolean isResizable() { return winAttr.isResizable; } From 58a50b25ebc226149aaa34086209978442942c42 Mon Sep 17 00:00:00 2001 From: Bill Pittore Date: Thu, 30 Aug 2012 11:20:01 -0400 Subject: [PATCH 25/53] 7154641: Servicability agent should work on platforms other than x86, sparc Added capability to load support classes for other cpus Reviewed-by: coleenp, bobv, sla --- hotspot/agent/make/saenv.sh | 2 +- hotspot/agent/make/start-debug-server-proc.sh | 7 +++-- .../agent/src/os/linux/LinuxDebuggerLocal.c | 8 +++-- hotspot/agent/src/os/linux/libproc.h | 11 ++++++- .../classes/sun/jvm/hotspot/HotSpotAgent.java | 10 ++++-- .../sun/jvm/hotspot/bugspot/BugSpotAgent.java | 11 +++++-- .../jvm/hotspot/debugger/ThreadContext.java | 4 +++ .../debugger/amd64/AMD64ThreadContext.java | 5 +++ .../debugger/ia64/IA64ThreadContext.java | 5 +++ .../debugger/linux/LinuxCDebugger.java | 6 ++-- .../linux/LinuxThreadContextFactory.java | 15 +++++++-- .../debugger/proc/ProcDebuggerLocal.java | 18 +++++++++-- .../debugger/remote/RemoteDebuggerClient.java | 16 ++++++++-- .../debugger/sparc/SPARCThreadContext.java | 5 +++ .../debugger/x86/X86ThreadContext.java | 5 +++ .../sun/jvm/hotspot/runtime/Threads.java | 12 ++++++- .../classes/sun/jvm/hotspot/runtime/VM.java | 7 +++++ .../ui/classbrowser/HTMLGenerator.java | 6 ++++ .../hotspot/utilities/AltPlatformInfo.java | 31 +++++++++++++++++++ .../jvm/hotspot/utilities/PlatformInfo.java | 7 +++++ hotspot/make/defs.make | 9 ++++++ hotspot/make/linux/makefiles/defs.make | 2 ++ hotspot/make/linux/makefiles/sa.make | 14 ++++++--- hotspot/make/linux/makefiles/saproc.make | 15 +++++++-- hotspot/src/share/vm/runtime/vmStructs.cpp | 1 + 25 files changed, 203 insertions(+), 29 deletions(-) create mode 100644 hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/AltPlatformInfo.java 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 #include #include #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/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/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 SymbolTwoOopHashtable; /******************/ \ \ declare_constant(UseTLAB) \ + declare_constant(EnableInvokeDynamic) \ \ /**************/ \ /* Stack bias */ \ From 1bd0a0be7d74f28f321c7fc632c87d4eccf83dee Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 30 Aug 2012 10:26:55 -0700 Subject: [PATCH 26/53] Added tag jdk8-b54 for changeset c5705c72aff8 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 8e85f0c6a28..c25c3e9725a 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -175,3 +175,4 @@ c97b99424815c43818e3cc3ffcdd1a60f3198b52 jdk8-b49 57c0aee7309050b9d6cfcbd202dc704e9260b377 jdk8-b51 8d24def5ceb3b8f2e857f2e18b2804fc59eecf8d jdk8-b52 febd7ff5280067ca482faaeb9418ae88764c1a35 jdk8-b53 +c1a277c6022affbc6855bdfb039511e73fbe2395 jdk8-b54 From 0c6def85cc23b08961ba21e6f412766b6a76ce81 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 30 Aug 2012 10:27:01 -0700 Subject: [PATCH 27/53] Added tag jdk8-b54 for changeset bbaf12c708dc --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 6a188eead8e..e19b67b7079 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -175,3 +175,4 @@ d20d9eb9f093adbf392918c703960ad24c93a331 jdk8-b50 9b0f841ca9f7ee9bacf16a5ab41c4f829276bc6b jdk8-b51 80689ff9cb499837513f18a1136dac7f0686cd55 jdk8-b52 63aeb7a2472fb299134ad7388e0a111a5340b02d jdk8-b53 +16c82fc74695bab9b9e0fb05c086a5a08ba0082f jdk8-b54 From f6008840a0ef81353c7a4a54ee1c7d50431cadb2 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 30 Aug 2012 10:27:07 -0700 Subject: [PATCH 28/53] Added tag jdk8-b54 for changeset 0b41a071152f --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 1bf06f8f90f..a1346dce9bd 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -272,3 +272,4 @@ e3619706a7253540a2d94e9e841acaab8ace7038 jdk8-b49 6d0436885201db3f581523344a734793bb989549 jdk8-b52 54240c1b8e87758f28da2c6a569a926fd9e0910a jdk8-b53 9e3ae661284dc04185b029d85440fe7811f1ed07 hs24-b21 +e8fb566b94667f88462164defa654203f0ab6820 jdk8-b54 From 6b75da0827d54d67e9f9f717fb0c7b8732ce1c7e Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 30 Aug 2012 10:27:15 -0700 Subject: [PATCH 29/53] Added tag jdk8-b54 for changeset 3799d28d324f --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 4cd999549d0..1c79925a240 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -175,3 +175,4 @@ f81e981eca7b63316cf9d778f93903a4fc62161d jdk8-b49 dc1ea77ed9d9746e0f98bb1268987c3596c8b4b5 jdk8-b51 bd3c00d5761408954cc29ffb82016a76cbc90b43 jdk8-b52 2c566f25c39f0087464b73e3bcf1c1421d0f2a7e jdk8-b53 +7dd81ccb7c1134df70969b3068b1e98def701746 jdk8-b54 From 1ee5aecfeb7bc2b2505f6607f7c46102e5ee3712 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 30 Aug 2012 10:27:18 -0700 Subject: [PATCH 30/53] Added tag jdk8-b54 for changeset e0b1a72b7a91 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 12ddc0ce1d9..45d200468ea 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -175,3 +175,4 @@ bdab72e87b83bcccf3abe6eaaa4cdc7b1cd2d92b jdk8-b50 1a70b6333ebe12e1c6dbca30e58bc1ba894ab898 jdk8-b51 f62bc618122e87a8bea69865cc02074e9d850426 jdk8-b52 8a35fd644d3c0b75813ff0236adef8a1c6f895c6 jdk8-b53 +91970935926a20f19a5cbbf20931745ac1975e91 jdk8-b54 From 53024605e435999873d1954846984503a50bf63a Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 30 Aug 2012 10:27:39 -0700 Subject: [PATCH 31/53] Added tag jdk8-b54 for changeset edce301a53ed --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 7447046d6b3..737fc671631 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -175,3 +175,4 @@ b2d8a270f5f2144e14a1fe97fbda9e4391a5332e jdk8-b50 c4cd4cab2220817c88c8c139c9bfc91c36b48826 jdk8-b51 1d2db0e5eabc2eaf865986f7b7ffbf7b14b00232 jdk8-b52 d3d0b9cd76e04bf9e381b402630ac3cfe464bb38 jdk8-b53 +9cf72631baf5cb1ebd8736c5efeab7746977ea68 jdk8-b54 From 9c23b8bad0bde881a70d31b7adf1989eb705a376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Borggr=C3=A9n-Franck?= Date: Fri, 31 Aug 2012 10:37:46 +0100 Subject: [PATCH 32/53] 7151010: Add compiler support for repeating annotations Reviewed-by: jjg, mcimadamore --- .../com/sun/tools/javac/code/Annotations.java | 294 ++++++++++++++++++ .../com/sun/tools/javac/code/Attribute.java | 18 +- .../com/sun/tools/javac/code/Lint.java | 10 +- .../com/sun/tools/javac/code/Source.java | 3 + .../com/sun/tools/javac/code/Symbol.java | 20 +- .../com/sun/tools/javac/code/Symtab.java | 8 + .../com/sun/tools/javac/code/Types.java | 20 +- .../com/sun/tools/javac/comp/Annotate.java | 279 ++++++++++++++++- .../com/sun/tools/javac/comp/Attr.java | 44 ++- .../com/sun/tools/javac/comp/Check.java | 234 +++++++++++++- .../com/sun/tools/javac/comp/Enter.java | 2 +- .../com/sun/tools/javac/comp/Flow.java | 18 +- .../com/sun/tools/javac/comp/Lower.java | 5 +- .../com/sun/tools/javac/comp/MemberEnter.java | 74 +++-- .../com/sun/tools/javac/jvm/ClassReader.java | 13 +- .../com/sun/tools/javac/jvm/ClassWriter.java | 2 +- .../com/sun/tools/javac/jvm/JNIWriter.java | 2 +- .../javac/model/AnnotationProxyMaker.java | 6 +- .../tools/javac/resources/compiler.properties | 64 ++++ .../sun/tools/javac/sym/CreateSymbols.java | 6 +- .../com/sun/tools/javac/tree/TreeMaker.java | 4 +- .../tools/javadoc/AnnotationValueImpl.java | 4 +- .../BasicRepeatingAnnotations.java | 79 +++++ .../repeatingAnnotations/CheckTargets.java | 67 ++++ .../ContainerHasRepeatedContained.java | 46 +++ .../DelayRepeatedContainer.java | 50 +++ .../repeatingAnnotations/InvalidTarget.java | 45 +++ .../MissingContainedBy.java | 39 +++ .../MissingContainerFor.java | 38 +++ .../NestedContainers.java | 74 +++++ .../repeatingAnnotations/RepMemberAnno.java | 49 +++ .../RepSelfMemberAnno.java | 60 ++++ .../RepeatingAndContainerPresent.java | 44 +++ .../SelfRepeatingAnnotations.java | 55 ++++ .../SingleRepeatingAndContainer.java | 43 +++ .../UseWrongContainedBy.java | 42 +++ .../UseWrongContainerFor.java | 42 +++ .../WrongContainedBy.java | 39 +++ .../WrongContainerFor.java | 39 +++ .../tools/javac/diags/examples.not-yet.txt | 3 + .../ContainedByDocumentedMismatch.java | 37 +++ .../ContainedByInheritedMismatch.java | 37 +++ .../diags/examples/ContainedByNoValue.java | 36 +++ .../diags/examples/ContainedByNonDefault.java | 36 +++ .../ContainedByRetentionMismatch.java | 37 +++ .../examples/ContainedByTargetMismatch.java | 35 +++ .../examples/ContainedByWrongValueType.java | 36 +++ .../diags/examples/DuplicateAnnotation.java | 4 +- .../examples/DuplicateAnnotationJava8.java | 30 ++ .../RepeatingAnnotationAndContainer.java | 37 +++ .../diags/examples/WrongContainedBy.java | 35 +++ .../diags/examples/WrongContainerFor.java | 35 +++ 52 files changed, 2284 insertions(+), 95 deletions(-) create mode 100644 langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/BasicRepeatingAnnotations.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/CheckTargets.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/ContainerHasRepeatedContained.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/DelayRepeatedContainer.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/InvalidTarget.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainedBy.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/MissingContainerFor.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/NestedContainers.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/RepMemberAnno.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/RepSelfMemberAnno.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/RepeatingAndContainerPresent.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/SelfRepeatingAnnotations.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/SingleRepeatingAndContainer.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainedBy.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/UseWrongContainerFor.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainedBy.java create mode 100644 langtools/test/tools/javac/annotations/repeatingAnnotations/WrongContainerFor.java create mode 100644 langtools/test/tools/javac/diags/examples/ContainedByDocumentedMismatch.java create mode 100644 langtools/test/tools/javac/diags/examples/ContainedByInheritedMismatch.java create mode 100644 langtools/test/tools/javac/diags/examples/ContainedByNoValue.java create mode 100644 langtools/test/tools/javac/diags/examples/ContainedByNonDefault.java create mode 100644 langtools/test/tools/javac/diags/examples/ContainedByRetentionMismatch.java create mode 100644 langtools/test/tools/javac/diags/examples/ContainedByTargetMismatch.java create mode 100644 langtools/test/tools/javac/diags/examples/ContainedByWrongValueType.java create mode 100644 langtools/test/tools/javac/diags/examples/DuplicateAnnotationJava8.java create mode 100644 langtools/test/tools/javac/diags/examples/RepeatingAnnotationAndContainer.java create mode 100644 langtools/test/tools/javac/diags/examples/WrongContainedBy.java create mode 100644 langtools/test/tools/javac/diags/examples/WrongContainerFor.java 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(). + * + *

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. + */ +public class Annotations { + + private static final List NOT_STARTED = List.of(null); + private static final List IN_PROGRESS = List.of(null); + /* + * This field should never be null + */ + private List attributes = NOT_STARTED; + /* + * The Symbol this Annotatios belong to + */ + private final Symbol s; + + public Annotations(Symbol s) { + this.s = s; + } + + public List getAttributes() { + return filterSentinels(attributes); + } + + public void setAttributes(List 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> annotated = ctx.annotated; + boolean atLeastOneRepeated = false; + List buf = List.nil(); + for (ListBuffer 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 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 l) { + attributes = filterSentinels(attributes); + + if (l.isEmpty()) { + ; // no-op + } else if (attributes.isEmpty()) { + attributes = l; + } else { + attributes = attributes.prependList(l); + } + return this; + } + + private List filterSentinels(List a) { + return (a == IN_PROGRESS || a == NOT_STARTED) + ? List.nil() + : a; + } + + private boolean isStarted() { + return attributes != NOT_STARTED; + } + + private List getPlaceholders() { + List res = List.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 env = ctx.env; + JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile); + try { + + if (isEmpty()) { + return; + } + + List 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 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 placeholderFor; + private Symbol on; + + public Placeholder(List placeholderFor, Symbol on) { + super(Type.noType, List.>nil()); + this.placeholderFor = placeholderFor; + this.on = on; + } + + @Override + public String toString() { + return ""; + } + + public List 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 accept(AnnotationValueVisitor 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 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 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 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 9fcbba44709..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 @@ -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 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 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 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/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java index 98f081a6686..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); + } // // @@ -3811,8 +3825,12 @@ public class Types { // 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 q = new ListBuffer(); + ListBuffer repeatedQ = new ListBuffer(); - 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 env; + public final Map> annotated; + public final Map pos; + public final Log log; + + public AnnotateRepeatedContext(Env env, + Map> annotated, + Map 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 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 annotations, + AnnotateRepeatedContext ctx) { + Attribute.Compound firstOccurrence = annotations.head; + List 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 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 p = + new Pair(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 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 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/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 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> 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> 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> 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> 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 containerTargets = new HashSet(); + for (Attribute app : containerTarget.values) { + if (!(app instanceof Attribute.Enum)) { + continue; // recovery + } + Attribute.Enum e = (Attribute.Enum)app; + containerTargets.add(e.value.name); + } + + Set containedTargets = new HashSet(); + 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 s, Set 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 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(); - 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 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 1590ee79293..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.nil(), List.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; 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 getMethodEnv(JCMethodDecl tree, Env env) { Env 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 l = tree.typarams; l.nonEmpty(); l = l.tail) mEnv.info.scope.enterIfAbsent(l.head.type.tsym); for (List l = tree.params; l.nonEmpty(); l = l.tail) @@ -727,18 +725,24 @@ public class MemberEnter extends JCTree.Visitor implements Completer { void annotateLater(final List annotations, final Env 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 annotations) { - for (List al = annotations; al.nonEmpty(); al = al.tail) { + for (List 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 annotations, Env env, Symbol s) { - ListBuffer buf = - new ListBuffer(); - Set annotated = new HashSet(); - if (!skipAnnotations) - for (List al = annotations; al.nonEmpty(); al = al.tail) { + Map> annotated = + new LinkedHashMap>(); + Map pos = + new HashMap(); + + for (List 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 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 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/jvm/ClassReader.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java index f7dc3669607..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 @@ -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 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 ac5b1387673..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 @@ -825,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('@'); 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/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 elems = new ListBuffer(); 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/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/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/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/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/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/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 {} From 99bfc33cceb7960a394892501709d1429ea0090b Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 31 Aug 2012 14:32:09 +0400 Subject: [PATCH 33/53] 7192955: Introspector overide PropertyDescriptor for generic type field defined in super class Reviewed-by: rupashka --- .../java/beans/PropertyDescriptor.java | 5 ++ .../java/beans/Introspector/Test7192955.java | 83 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 jdk/test/java/beans/Introspector/Test7192955.java diff --git a/jdk/src/share/classes/java/beans/PropertyDescriptor.java b/jdk/src/share/classes/java/beans/PropertyDescriptor.java index 91e17e38aa7..45235a14ba6 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); } /** 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 list; + + public List getList() { + return this.list; + } + + public void setList(List list) { + this.list = list; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + } + + public List 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; + } + } +} From 7d367a512351cbb714542efd47962dd503dad52a Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 31 Aug 2012 14:49:23 +0400 Subject: [PATCH 34/53] 7186794: Setter not found. PropertyDescriptor(PropertyDescriptor,PropertyDescriptor) Reviewed-by: rupashka --- .../java/beans/PropertyDescriptor.java | 2 +- .../java/beans/Introspector/Test7186794.java | 55 +++++++++++++++++++ .../java/beans/Introspector/Test7189112.java | 12 +--- 3 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 jdk/test/java/beans/Introspector/Test7186794.java diff --git a/jdk/src/share/classes/java/beans/PropertyDescriptor.java b/jdk/src/share/classes/java/beans/PropertyDescriptor.java index 45235a14ba6..e5b42631fbe 100644 --- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java @@ -593,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/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 value; + + public void setValue(List value) { + this.value = value; + } + } + + public static class MyBean extends BaseBean { + public List 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"); } } From 67b1f9248be2b9e07247c84a2e22c3b1be619c53 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Fri, 31 Aug 2012 16:31:29 +0400 Subject: [PATCH 35/53] 6981400: Tabbing between textfield do not work properly when ALT+TAB 7157015: [macosx] Situation when KeyEventDispatcher doesn't work on AWT but does on Swing 7121442: Regression : Reopen CR 6458497 still reproducible using JDK 7 Reviewed-by: art, leonidr --- .../classes/sun/lwawt/LWComponentPeer.java | 3 - .../classes/sun/lwawt/LWWindowPeer.java | 28 ++- .../swing/plaf/windows/WindowsRootPaneUI.java | 16 +- jdk/src/share/classes/java/awt/Component.java | 37 ++- jdk/src/share/classes/java/awt/Container.java | 2 +- .../java/awt/DefaultKeyboardFocusManager.java | 87 ++++--- jdk/src/share/classes/java/awt/Dialog.java | 2 +- .../share/classes/java/awt/EventQueue.java | 17 ++ .../classes/java/awt/SequencedEvent.java | 12 + .../share/classes/sun/awt/AWTAccessor.java | 33 +++ .../sun/awt/KeyboardFocusManagerPeerImpl.java | 4 +- jdk/src/share/classes/sun/awt/SunToolkit.java | 35 +++ .../classes/sun/awt/TimedWindowEvent.java | 51 ++++ .../classes/sun/awt/X11/XBaseWindow.java | 7 + .../classes/sun/awt/X11/XComponentPeer.java | 27 --- .../windows/native/sun/windows/awt_Window.cpp | 6 +- jdk/test/java/awt/Focus/6981400/Test1.java | 222 ++++++++++++++++++ jdk/test/java/awt/Focus/6981400/Test2.java | 118 ++++++++++ jdk/test/java/awt/Focus/6981400/Test3.java | 141 +++++++++++ 19 files changed, 766 insertions(+), 82 deletions(-) create mode 100644 jdk/src/share/classes/sun/awt/TimedWindowEvent.java create mode 100644 jdk/test/java/awt/Focus/6981400/Test1.java create mode 100644 jdk/test/java/awt/Focus/6981400/Test2.java create mode 100644 jdk/test/java/awt/Focus/6981400/Test3.java diff --git a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java index 7f556aca166..1704b3bdd25 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java @@ -1251,9 +1251,6 @@ public abstract class LWComponentPeer 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); } } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java index 41e266a9be0..8212722dfbc 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -798,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 @@ -914,20 +922,16 @@ public class LWWindowPeer public void dispatchKeyEvent(int id, long when, int modifiers, int keyCode, char keyChar, int keyLocation) { - KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); + 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, id, when, modifiers, - keyCode, keyChar, keyLocation); - LWComponentPeer peer = (LWComponentPeer)focusOwner.getPeer(); - peer.postEvent(event); + if (focusOwner == null) { + focusOwner = kfmPeer.getCurrentFocusedWindow(); + if (focusOwner == null) { + focusOwner = this.getTarget(); + } } + postEvent(new KeyEvent(focusOwner, id, when, modifiers, keyCode, keyChar, keyLocation)); } @@ -1260,7 +1264,7 @@ public class LWWindowPeer 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/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 109e70d9d8a..1d39094bc47 100644 --- a/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java +++ b/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java @@ -40,6 +40,7 @@ import sun.util.logging.PlatformLogger; import sun.awt.AppContext; import sun.awt.SunToolkit; import sun.awt.CausedFocusEvent; +import sun.awt.TimedWindowEvent; /** * The default KeyboardFocusManager for AWT applications. Focus traversal is @@ -71,8 +72,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { private WeakReference realOppositeWindowWR = NULL_WINDOW_WR; private WeakReference realOppositeComponentWR = NULL_COMPONENT_WR; private int inSendMessage; - private LinkedList enqueuedKeyEvents = new LinkedList(), - typeAheadMarkers = new LinkedList(); + private LinkedList enqueuedKeyEvents = new LinkedList(); + private LinkedList typeAheadMarkers = new LinkedList(); private boolean consumeNextKeyTyped; private static class TypeAheadMarker { @@ -259,6 +260,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. @@ -277,6 +303,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(); @@ -636,6 +666,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(); @@ -815,10 +849,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. @@ -847,9 +880,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 iter = typeAheadMarkers.iterator(); while (iter.hasNext()) { - TypeAheadMarker marker = (TypeAheadMarker)iter.next(); + TypeAheadMarker marker = iter.next(); focusLog.finest(" {0}", marker); } } @@ -871,8 +904,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. @@ -905,12 +937,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { synchronized (this) { boolean found = false; if (hasMarker(target)) { - for (Iterator iter = typeAheadMarkers.iterator(); + for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { - if (((TypeAheadMarker)iter.next()).untilFocused == - target) - { + if (iter.next().untilFocused == target) { found = true; } else if (found) { break; @@ -945,8 +975,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 iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { + if (iter.next().untilFocused == comp) { return true; } } @@ -972,11 +1002,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); /** @@ -1164,10 +1193,10 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { int insertionIndex = 0, i = typeAheadMarkers.size(); - ListIterator iter = typeAheadMarkers.listIterator(i); + ListIterator iter = typeAheadMarkers.listIterator(i); for (; i > 0; i--) { - TypeAheadMarker marker = (TypeAheadMarker)iter.previous(); + TypeAheadMarker marker = iter.previous(); if (marker.after <= after) { insertionIndex = i; break; @@ -1203,12 +1232,12 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { after, untilFocused); TypeAheadMarker marker; - ListIterator iter = typeAheadMarkers.listIterator + ListIterator 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(); @@ -1217,7 +1246,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { } } else { while (iter.hasPrevious()) { - marker = (TypeAheadMarker)iter.previous(); + marker = iter.previous(); if (marker.untilFocused == untilFocused && marker.after == after) { @@ -1245,8 +1274,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { long start = -1; - for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { - TypeAheadMarker marker = (TypeAheadMarker)iter.next(); + for (Iterator iter = typeAheadMarkers.iterator(); iter.hasNext(); ) { + TypeAheadMarker marker = iter.next(); Component toTest = marker.untilFocused; boolean match = (toTest == comp); while (!match && toTest != null && !(toTest instanceof Window)) { @@ -1277,8 +1306,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { return; } - for (Iterator iter = enqueuedKeyEvents.iterator(); iter.hasNext(); ) { - KeyEvent ke = (KeyEvent)iter.next(); + for (Iterator 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 c163a9bb447..bb02ae9b70c 100644 --- a/jdk/src/share/classes/java/awt/EventQueue.java +++ b/jdk/src/share/classes/java/awt/EventQueue.java @@ -163,6 +163,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. @@ -1132,6 +1137,15 @@ public class EventQueue { } } + synchronized long getMostRecentKeyEventTime() { + pushPopLock.lock(); + try { + return mostRecentKeyEventTime; + } finally { + pushPopLock.unlock(); + } + } + static void setCurrentEventAndMostRecentTime(AWTEvent e) { Toolkit.getEventQueue().setCurrentEventAndMostRecentTimeImpl(e); } @@ -1156,6 +1170,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/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/sun/awt/AWTAccessor.java b/jdk/src/share/classes/sun/awt/AWTAccessor.java index 04a2799fe5f..024183331fb 100644 --- a/jdk/src/share/classes/sun/awt/AWTAccessor.java +++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java @@ -486,6 +486,21 @@ public final class AWTAccessor { final int type); } + /* + * 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. @@ -502,6 +517,7 @@ public final class AWTAccessor { private static PopupMenuAccessor popupMenuAccessor; private static FileDialogAccessor fileDialogAccessor; private static ScrollPaneAdjustableAccessor scrollPaneAdjustableAccessor; + private static SequencedEventAccessor sequencedEventAccessor; /* * Set an accessor object for the java.awt.Component class. @@ -709,4 +725,21 @@ public final class AWTAccessor { } return scrollPaneAdjustableAccessor; } + + /* + * 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/KeyboardFocusManagerPeerImpl.java b/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java index d0794ffb1ee..2e2350b1c4d 100644 --- a/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java +++ b/jdk/src/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java @@ -128,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, @@ -136,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/SunToolkit.java b/jdk/src/share/classes/sun/awt/SunToolkit.java index 66985835fba..5f72ee31369 100644 --- a/jdk/src/share/classes/sun/awt/SunToolkit.java +++ b/jdk/src/share/classes/sun/awt/SunToolkit.java @@ -513,6 +513,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 @@ -1964,6 +1977,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 map = (WeakHashMap)ctx.get(DEACTIVATION_TIMES_MAP_KEY); + if (map == null) { + map = new WeakHashMap(); + ctx.put(DEACTIVATION_TIMES_MAP_KEY, map); + } + map.put(w, time); + } + + public synchronized long getWindowDeactivationTime(Window w) { + AppContext ctx = getAppContext(w); + WeakHashMap map = (WeakHashMap)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/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 643767068fa..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.getInstance().getCurrentFocusedWindow() != 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/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, "", - "(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/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 gainedList = new ArrayList(); + static List lostList = new ArrayList(); + + 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); + } + } +} + + From ae110cd170aead551756b8578e9aa60feaaf2bcf Mon Sep 17 00:00:00 2001 From: John Coomes Date: Fri, 31 Aug 2012 16:17:41 -0700 Subject: [PATCH 36/53] Added tag hs24-b22 for changeset a83f6d24c373 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index a1346dce9bd..dbc7d6dbedc 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -273,3 +273,4 @@ e3619706a7253540a2d94e9e841acaab8ace7038 jdk8-b49 54240c1b8e87758f28da2c6a569a926fd9e0910a jdk8-b53 9e3ae661284dc04185b029d85440fe7811f1ed07 hs24-b21 e8fb566b94667f88462164defa654203f0ab6820 jdk8-b54 +09ea7e0752b306b8ae74713aeb4eb6263e1c6836 hs24-b22 From 25c0370a8b4466802ddf5ba3b438820f808cb262 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Tue, 4 Sep 2012 13:12:16 +0400 Subject: [PATCH 37/53] 7169395: Exception throws due to the changes in JDK 7 object tranversal and break backward compatibility Reviewed-by: art --- .../share/classes/java/beans/XMLEncoder.java | 19 ++-- .../java/beans/XMLEncoder/Test7169395.java | 101 ++++++++++++++++++ 2 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 jdk/test/java/beans/XMLEncoder/Test7169395.java 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(""); + } + 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 statements = statementList(target); - if (!statements.contains(exp)) { - statements.add(exp); + if (d.name == null) { + getValueData(target).refs++; + List 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/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 map = new TreeMap(); + + public Collection getComponents() { + return new ArrayList(this.map.values()); + } + + public void setComponents(Collection 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); + } + } +} From 2276a386320178e619bd969a725efcfcaf8a421c Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Tue, 4 Sep 2012 20:50:44 +0400 Subject: [PATCH 38/53] 7195106: REGRESSION : There is no way to get Icon inf, once Softreference is released Reviewed-by: rupashka --- .../classes/java/beans/Introspector.java | 23 ++++++- .../Introspector/6380849/TestBeanInfo.java | 10 ++- .../java/beans/Introspector/Test7195106.java | 67 +++++++++++++++++++ 3 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 jdk/test/java/beans/Introspector/Test7195106.java 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 targetBeanInfoRef; + private Reference 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/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/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); + } + } +} From 7dfe1cb86cf803751190d273feae18e9dbdb0c3c Mon Sep 17 00:00:00 2001 From: Jim Holmlund Date: Wed, 5 Sep 2012 08:32:32 -0700 Subject: [PATCH 39/53] 7185778: javah error "Not a valid class name" on class names with dollar signs Reviewed-by: jjg --- .../com/sun/tools/javah/JavahTask.java | 12 +--- langtools/test/tools/javah/T7185778.java | 56 +++++++++++++++++++ 2 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 langtools/test/tools/javah/T7185778.java 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 opts = new ArrayList(); 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 internalize(List classes) { - List l = new ArrayList(); - for (String c: classes) { - l.add(c.replace('$', '.')); - } - return l; - } - private List pathToFiles(String path) { List files = new ArrayList(); for (String f: path.split(File.pathSeparator)) { 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); +} From 2663894371c4497e5acb787d854065fb010c989a Mon Sep 17 00:00:00 2001 From: Scott Kovatch Date: Wed, 5 Sep 2012 09:34:19 -0700 Subject: [PATCH 40/53] 7187834: [macosx] Usage of private API in macosx 2D implementation causes Apple Store rejection Reviewed-by: prr, igor --- jdk/src/macosx/native/sun/awt/ImageSurfaceData.h | 10 ++++------ jdk/src/macosx/native/sun/awt/ImageSurfaceData.m | 10 ++++------ jdk/src/macosx/native/sun/awt/QuartzRenderer.m | 7 ++----- jdk/src/macosx/native/sun/awt/QuartzSurfaceData.m | 9 ++------- 4 files changed, 12 insertions(+), 24 deletions(-) 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 - -// 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 #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; } From 7788603b2ec3af8ff2706269ac81bcaa9915e2b7 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Wed, 5 Sep 2012 21:40:05 +0400 Subject: [PATCH 41/53] 7124523: [macosx] b216: Mising part of applet UI Reviewed-by: denis, alexsch --- jdk/src/share/demo/applets/CardTest/example1.html | 2 +- jdk/src/share/demo/applets/DitherTest/example1.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 @@

Card Test (1.1)


- + alt="Your browser understands the <APPLET> tag but isn't running the applet, for some reason." Your browser is completely ignoring the <APPLET> tag! 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 @@

Dither Test (1.1)


- + alt="Your browser understands the <APPLET> tag but isn't running the applet, for some reason." Your browser is completely ignoring the <APPLET> tag! From 1fc1536a31f2b4da79d2054d1cb511b650b83b7d Mon Sep 17 00:00:00 2001 From: John Coomes Date: Wed, 5 Sep 2012 12:42:26 -0700 Subject: [PATCH 42/53] 7196361: add hotspot/make/closed to hgforest.sh Reviewed-by: ohair --- make/scripts/hgforest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 5802f97caf542f7a98c9e70000a0da16ee35c749 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 6 Sep 2012 17:27:20 -0700 Subject: [PATCH 43/53] Added tag jdk8-b55 for changeset b4f6c05ae88a --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index c25c3e9725a..c1eee4053a2 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -176,3 +176,4 @@ c97b99424815c43818e3cc3ffcdd1a60f3198b52 jdk8-b49 8d24def5ceb3b8f2e857f2e18b2804fc59eecf8d jdk8-b52 febd7ff5280067ca482faaeb9418ae88764c1a35 jdk8-b53 c1a277c6022affbc6855bdfb039511e73fbe2395 jdk8-b54 +b85b44cced2406792cfb9baab1377ff03e7001d8 jdk8-b55 From ef3763175d1fbfa230f247c8d7c6826ae133f332 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 6 Sep 2012 17:27:24 -0700 Subject: [PATCH 44/53] Added tag jdk8-b55 for changeset a180f4cc7c94 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index e19b67b7079..ac231ffd80f 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -176,3 +176,4 @@ d20d9eb9f093adbf392918c703960ad24c93a331 jdk8-b50 80689ff9cb499837513f18a1136dac7f0686cd55 jdk8-b52 63aeb7a2472fb299134ad7388e0a111a5340b02d jdk8-b53 16c82fc74695bab9b9e0fb05c086a5a08ba0082f jdk8-b54 +e8a0e84383d6fbd303ce44bd355fb25972b13286 jdk8-b55 From 2aa10d79aa280c2b29e062bf3d3a595d737b9d44 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 6 Sep 2012 17:27:33 -0700 Subject: [PATCH 45/53] Added tag jdk8-b55 for changeset 49f23700884c --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index dbc7d6dbedc..ab823043132 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -274,3 +274,4 @@ e3619706a7253540a2d94e9e841acaab8ace7038 jdk8-b49 9e3ae661284dc04185b029d85440fe7811f1ed07 hs24-b21 e8fb566b94667f88462164defa654203f0ab6820 jdk8-b54 09ea7e0752b306b8ae74713aeb4eb6263e1c6836 hs24-b22 +af0c8a0808516317333dcf9af15567cdd52761ce jdk8-b55 From 76b8a9a6b73ad4b1cdbdf66b4223a9cf7f906c8e Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 6 Sep 2012 17:27:44 -0700 Subject: [PATCH 46/53] Added tag jdk8-b55 for changeset b5d27d05eea2 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 1c79925a240..55ffe019b2e 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -176,3 +176,4 @@ dc1ea77ed9d9746e0f98bb1268987c3596c8b4b5 jdk8-b51 bd3c00d5761408954cc29ffb82016a76cbc90b43 jdk8-b52 2c566f25c39f0087464b73e3bcf1c1421d0f2a7e jdk8-b53 7dd81ccb7c1134df70969b3068b1e98def701746 jdk8-b54 +7c2363666890c6675194948fbcd74d81ddb84298 jdk8-b55 From 79f7de8d0f9cdc20aa974b413a54554b1df0fec7 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 6 Sep 2012 17:27:48 -0700 Subject: [PATCH 47/53] Added tag jdk8-b55 for changeset 39d1771dd21b --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 45d200468ea..89f54c11cc1 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -176,3 +176,4 @@ bdab72e87b83bcccf3abe6eaaa4cdc7b1cd2d92b jdk8-b50 f62bc618122e87a8bea69865cc02074e9d850426 jdk8-b52 8a35fd644d3c0b75813ff0236adef8a1c6f895c6 jdk8-b53 91970935926a20f19a5cbbf20931745ac1975e91 jdk8-b54 +109c9e1f2d8546e9954e1b7be9a37a4396434544 jdk8-b55 From 1e5b3e3ded649d63e2cdfef589222d37b58a1603 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 6 Sep 2012 17:27:56 -0700 Subject: [PATCH 48/53] Added tag jdk8-b55 for changeset 4efc4ab93edd --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 7b1dd87bd4e..737fd9cd9d4 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -176,3 +176,4 @@ e865efbc71059a414b3b2dd2e0adfcb3d2ab6ff9 jdk8-b51 e8569a473cee7f4955bd9e76a9bdf6c6a07ced27 jdk8-b52 2c6933c5106b81a8578b70996fe5b735fb3adb60 jdk8-b53 70ad0ed1d6cef0e7712690d1bab21e4769708aad jdk8-b54 +1f3f4b333341873f00da3dee85e4879f0e89c9bb jdk8-b55 From 7eb98442e17ed554576e5f0adc71946cb5721a81 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 6 Sep 2012 17:28:10 -0700 Subject: [PATCH 49/53] Added tag jdk8-b55 for changeset bc332057d97a --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 737fc671631..653073cff9c 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -176,3 +176,4 @@ c4cd4cab2220817c88c8c139c9bfc91c36b48826 jdk8-b51 1d2db0e5eabc2eaf865986f7b7ffbf7b14b00232 jdk8-b52 d3d0b9cd76e04bf9e381b402630ac3cfe464bb38 jdk8-b53 9cf72631baf5cb1ebd8736c5efeab7746977ea68 jdk8-b54 +e48e7e1f026b82d921433150180799898c088890 jdk8-b55 From b4f55953e0afdd20b87060f1a3680530e1d52ba2 Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Tue, 11 Sep 2012 13:40:59 -0700 Subject: [PATCH 50/53] 7197771: Adjust jdk sources to avoid use of implementation defined value of __FILE__ 7180608: Sort the order of object files when building shared libraries Reviewed-by: ohrstrom, erikj, tbell --- jdk/make/common/Defs.gmk | 17 ++++++++++++++++- jdk/make/common/Demo.gmk | 4 ++-- jdk/make/common/Library.gmk | 6 +++--- jdk/make/common/Program.gmk | 4 +--- .../macosx/native/com/apple/laf/ScreenMenu.m | 12 ++++++++---- .../media/sound/PLATFORM_API_MacOSX_MidiOut.c | 11 ++++++++--- .../media/sound/PLATFORM_API_MacOSX_MidiUtils.c | 7 ++++++- jdk/src/macosx/native/sun/awt/CSystemColors.m | 7 ++++++- jdk/src/macosx/native/sun/awt/CTextPipe.m | 6 +++++- jdk/src/macosx/native/sun/font/AWTStrike.m | 7 ++++++- jdk/src/share/back/error_messages.h | 13 +++++++++---- jdk/src/share/back/log_messages.h | 8 ++++++-- jdk/src/share/demo/jvmti/hprof/debug_malloc.h | 9 +++++++-- jdk/src/share/demo/jvmti/hprof/hprof_error.h | 17 +++++++++++------ jdk/src/share/demo/jvmti/hprof/hprof_util.h | 9 +++++++-- .../demo/jvmti/java_crw_demo/java_crw_demo.c | 12 ++++++++++-- jdk/src/share/instrument/JPLISAssert.h | 8 ++++++-- .../share/native/sun/awt/debug/debug_assert.h | 9 +++++++-- jdk/src/share/native/sun/awt/debug/debug_mem.c | 7 ++++++- .../share/native/sun/awt/debug/debug_trace.h | 7 ++++++- .../sun/security/pkcs11/wrapper/pkcs11wrapper.h | 9 +++++++-- jdk/src/share/npt/utf.h | 7 ++++++- jdk/src/share/transport/shmem/shmemBase.h | 9 +++++++-- jdk/src/solaris/instrument/EncodingSupport_md.c | 7 ++++++- .../media/sound/PLATFORM_API_WinOS_MidiIn.cpp | 8 +++++++- .../media/sound/PLATFORM_API_WinOS_MidiOut.c | 8 +++++++- .../windows/native/sun/java2d/d3d/D3DPipeline.h | 11 ++++++++--- jdk/src/windows/native/sun/windows/alloc.h | 13 +++++++++---- jdk/src/windows/native/sun/windows/awt_Debug.h | 7 ++++++- .../windows/native/sun/windows/awt_Toolkit.h | 14 ++++++++++---- jdk/src/windows/transport/shmem/shmem_md.c | 7 ++++++- 31 files changed, 215 insertions(+), 65 deletions(-) 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='"$( $@ + @$(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 89765d02fc0..b62c34da0c5 100644 --- a/jdk/make/common/Program.gmk +++ b/jdk/make/common/Program.gmk @@ -242,7 +242,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 @@ -372,8 +372,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/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/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/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/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 #include +/* 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/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/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 + +/* 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 + +/* 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/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 From 298c94f6976cdb5d6bbc9888317907923f2bee31 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 18:20:34 +0200 Subject: [PATCH 51/53] Added tag jdk8-b54 for changeset 7c6aa31ff1b2 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 649cfd98a86..f4a6aaad65c 100644 --- a/.hgtags +++ b/.hgtags @@ -175,3 +175,4 @@ cecd7026f30cbd83b0601925a7a5e059aec98138 jdk8-b49 382651d28f2502d371eca751962232c0e535e57a jdk8-b51 b67041a6cb508da18d2f5c7687e6a31e08bea4fc jdk8-b52 c7aa5cca1c01689a7b1a92411daf83684af05a33 jdk8-b53 +7c6aa31ff1b2ae48c1c686ebe1aadf0c3da5be15 jdk8-b54 From cca26ba2b7544adaff6699bcd5007941f451d574 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 18:21:34 +0200 Subject: [PATCH 52/53] Added tag jdk8-b55 for changeset 319f583f66db --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index f4a6aaad65c..1e380877a67 100644 --- a/.hgtags +++ b/.hgtags @@ -176,3 +176,4 @@ cecd7026f30cbd83b0601925a7a5e059aec98138 jdk8-b49 b67041a6cb508da18d2f5c7687e6a31e08bea4fc jdk8-b52 c7aa5cca1c01689a7b1a92411daf83684af05a33 jdk8-b53 7c6aa31ff1b2ae48c1c686ebe1aadf0c3da5be15 jdk8-b54 +319f583f66db47395fa86127dd3ddb729eb7c64f jdk8-b55 From 04d30a320f46fb9cc63bf69bd2320a0c10316490 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 13 Sep 2012 13:16:04 -0700 Subject: [PATCH 53/53] Added tag jdk8-b56 for changeset 9a3f2acd6f92 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 737fd9cd9d4..3c028e89658 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -177,3 +177,4 @@ e8569a473cee7f4955bd9e76a9bdf6c6a07ced27 jdk8-b52 2c6933c5106b81a8578b70996fe5b735fb3adb60 jdk8-b53 70ad0ed1d6cef0e7712690d1bab21e4769708aad jdk8-b54 1f3f4b333341873f00da3dee85e4879f0e89c9bb jdk8-b55 +2e9eeef2909b33c9224a024afddb61ccb0b77f14 jdk8-b56