# HG changeset patch # User chegar # Date 1368005272 -3600 # Node ID 8074ccd57d89fc62247d3725dbf6f8d29c318e66 # Parent 27cda51347487c6baaba33d78be88e2bd80998cb# Parent ec434cfd2752a7742c875c2fe7d556d8b81c0f3a Merge diff -r 27cda5134748 -r 8074ccd57d89 .hgtags --- a/.hgtags Sun Apr 28 08:16:41 2013 +0100 +++ b/.hgtags Wed May 08 10:27:52 2013 +0100 @@ -209,3 +209,4 @@ 4a48f31735349782ad13980267358c97076adc66 jdk8-b85 6ab578e141dfd17c4dc03869bb204aafa490c9f4 jdk8-b86 1329f9c38d93c8caf339d7687df8371d06fe9e56 jdk8-b87 +a1e10f3adc47c8602a72e43a41403a642e73e0b1 jdk8-b88 diff -r 27cda5134748 -r 8074ccd57d89 make/build.xml --- a/make/build.xml Sun Apr 28 08:16:41 2013 +0100 +++ b/make/build.xml Wed May 08 10:27:52 2013 +0100 @@ -717,6 +717,29 @@ + + + + + + + + + + + + @@ -811,6 +834,31 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -826,6 +874,7 @@ + @@ -868,6 +917,7 @@ + @@ -935,6 +985,32 @@ classpath="${build.toolclasses.dir}/"/> + + + + + + + + + + + + + + + + + currentFieldsToIgnore = + classFieldsToIgnoreMap.get(className); + if (currentFieldsToIgnore != null) { + for (String fieldToIgnore : currentFieldsToIgnore) { + if (field.equals(fieldToIgnore)) { + return true; + } + } + } + return false; + } + + class MutableFieldsVisitor extends TreeScanner { + + @Override + public void visitVarDef(JCVariableDecl tree) { + boolean isJavacPack = tree.sym.outermostClass().fullname.toString() + .contains(packageToCheck); + if (isJavacPack && + (tree.sym.flags() & SYNTHETIC) == 0 && + tree.sym.owner.kind == Kinds.TYP) { + if (!ignoreField(tree.sym.owner.flatName().toString(), + tree.getName().toString())) { + boolean enumClass = (tree.sym.owner.flags() & ENUM) != 0; + boolean nonFinalStaticEnumField = + (tree.sym.flags() & (ENUM | FINAL)) == 0; + boolean nonFinalStaticField = + (tree.sym.flags() & STATIC) != 0 && + (tree.sym.flags() & FINAL) == 0; + if (enumClass ? nonFinalStaticEnumField : nonFinalStaticField) { + messages.error(tree, "crules.err.var.must.be.final", tree); + } + } + } + super.visitVarDef(tree); + } + + } + + private static final String packageToCheck = "com.sun.tools.javac"; + + private static final Map> classFieldsToIgnoreMap = + new HashMap>(); + + static { + classFieldsToIgnoreMap. + put("com.sun.tools.javac.util.JCDiagnostic", + Arrays.asList("fragmentFormatter")); + classFieldsToIgnoreMap. + put("com.sun.tools.javac.util.JavacMessages", + Arrays.asList("defaultBundle", "defaultMessages")); + classFieldsToIgnoreMap. + put("com.sun.tools.javac.file.ZipFileIndexCache", + Arrays.asList("sharedInstance")); + classFieldsToIgnoreMap. + put("com.sun.tools.javac.main.JavaCompiler", + Arrays.asList("versionRB")); + classFieldsToIgnoreMap. + put("com.sun.tools.javac.code.Type", + Arrays.asList("moreInfo")); + classFieldsToIgnoreMap. + put("com.sun.tools.javac.util.SharedNameTable", + Arrays.asList("freelist")); + classFieldsToIgnoreMap. + put("com.sun.tools.javac.util.Log", + Arrays.asList("useRawMessages")); + } + +} diff -r 27cda5134748 -r 8074ccd57d89 make/tools/crules/resources/crules.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/crules/resources/crules.properties Wed May 08 10:27:52 2013 +0100 @@ -0,0 +1,28 @@ +# +# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +# 0: symbol +crules.err.var.must.be.final=\ + Static variable {0} must be final diff -r 27cda5134748 -r 8074ccd57d89 src/share/classes/com/sun/tools/classfile/Dependencies.java --- a/src/share/classes/com/sun/tools/classfile/Dependencies.java Sun Apr 28 08:16:41 2013 +0100 +++ b/src/share/classes/com/sun/tools/classfile/Dependencies.java Wed May 08 10:27:52 2013 +0100 @@ -315,7 +315,7 @@ static class SimpleLocation implements Location { public SimpleLocation(String name) { this.name = name; - this.className = name.replace('/', '.').replace('$', '.'); + this.className = name.replace('/', '.'); } public String getName() { diff -r 27cda5134748 -r 8074ccd57d89 src/share/classes/com/sun/tools/classfile/ReferenceFinder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/classfile/ReferenceFinder.java Wed May 08 10:27:52 2013 +0100 @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * 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.classfile; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import com.sun.tools.classfile.Instruction.TypeKind; +import static com.sun.tools.classfile.ConstantPool.*; + +/** + * A utility class to find where in a ClassFile references + * a {@link CONSTANT_Methodref_info method}, + * a {@link CONSTANT_InterfaceMethodref_info interface method, + * or a {@link CONSTANT_Fieldref_info field}. + */ +public final class ReferenceFinder { + /** + * Filter for ReferenceFinder of what constant pool entries for reference lookup. + */ + public interface Filter { + /** + * Decides if the given CPRefInfo entry should be accepted or filtered. + * + * @param cpool ConstantPool of the ClassFile being parsed + * @param cpref constant pool entry representing a reference to + * a fields method, and interface method. + * @return {@code true} if accepted; otherwise {@code false} + */ + boolean accept(ConstantPool cpool, CPRefInfo cpref); + } + + /** + * Visitor of individual method of a ClassFile that references the + * accepted field, method, or interface method references. + */ + public interface Visitor { + /** + * Invoked for a method containing one or more accepted CPRefInfo entries + * + * @param cf ClassFile + * @param method Method that does the references the accepted references + * @param refs Accepted constant pool method/field reference + */ + void visit(ClassFile cf, Method method, List refConstantPool); + } + + private final Filter filter; + private final Visitor visitor; + + /** + * Constructor. + */ + public ReferenceFinder(Filter filter, Visitor visitor) { + this.filter = Objects.requireNonNull(filter); + this.visitor = Objects.requireNonNull(visitor); + } + + /** + * Parses a given ClassFile and invoke the visitor if there is any reference + * to the constant pool entries referencing field, method, or + * interface method that are accepted. This method will return + * {@code true} if there is one or more accepted constant pool entries + * to lookup; otherwise, it will return {@code false}. + * + * @param cf ClassFile + * @return {@code true} if the given class file is processed to lookup + * references + * @throws ConstantPoolException if an error of the constant pool + */ + public boolean parse(ClassFile cf) throws ConstantPoolException { + List cprefs = new ArrayList(); + int index = 1; + for (ConstantPool.CPInfo cpInfo : cf.constant_pool.entries()) { + if (cpInfo.accept(cpVisitor, cf.constant_pool)) { + cprefs.add(index); + } + index += cpInfo.size(); + } + + if (cprefs.isEmpty()) { + return false; + } + + for (Method m : cf.methods) { + Set ids = new HashSet(); + Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code); + if (c_attr != null) { + for (Instruction instr : c_attr.getInstructions()) { + int idx = instr.accept(codeVisitor, cprefs); + if (idx > 0) { + ids.add(idx); + } + } + } + if (ids.size() > 0) { + List refInfos = new ArrayList(ids.size()); + for (int id : ids) { + refInfos.add(CPRefInfo.class.cast(cf.constant_pool.get(id))); + } + visitor.visit(cf, m, refInfos); + } + } + return true; + } + + private ConstantPool.Visitor cpVisitor = + new ConstantPool.Visitor() + { + public Boolean visitClass(CONSTANT_Class_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ConstantPool cpool) { + return filter.accept(cpool, info); + } + + public Boolean visitMethodref(CONSTANT_Methodref_info info, ConstantPool cpool) { + return filter.accept(cpool, info); + } + + public Boolean visitFieldref(CONSTANT_Fieldref_info info, ConstantPool cpool) { + return filter.accept(cpool, info); + } + + public Boolean visitDouble(CONSTANT_Double_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitFloat(CONSTANT_Float_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitInteger(CONSTANT_Integer_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitLong(CONSTANT_Long_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitNameAndType(CONSTANT_NameAndType_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitMethodHandle(CONSTANT_MethodHandle_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitMethodType(CONSTANT_MethodType_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitString(CONSTANT_String_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitUtf8(CONSTANT_Utf8_info info, ConstantPool cpool) { + return false; + } + }; + + private Instruction.KindVisitor> codeVisitor = + new Instruction.KindVisitor>() + { + public Integer visitNoOperands(Instruction instr, List p) { + return 0; + } + + public Integer visitArrayType(Instruction instr, TypeKind kind, List p) { + return 0; + } + + public Integer visitBranch(Instruction instr, int offset, List p) { + return 0; + } + + public Integer visitConstantPoolRef(Instruction instr, int index, List p) { + return p.contains(index) ? index : 0; + } + + public Integer visitConstantPoolRefAndValue(Instruction instr, int index, int value, List p) { + return p.contains(index) ? index : 0; + } + + public Integer visitLocal(Instruction instr, int index, List p) { + return 0; + } + + public Integer visitLocalAndValue(Instruction instr, int index, int value, List p) { + return 0; + } + + public Integer visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, List p) { + return 0; + } + + public Integer visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, List p) { + return 0; + } + + public Integer visitValue(Instruction instr, int value, List p) { + return 0; + } + + public Integer visitUnknown(Instruction instr, List p) { + return 0; + } + }; +} + diff -r 27cda5134748 -r 8074ccd57d89 src/share/classes/com/sun/tools/javac/comp/Check.java --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Sun Apr 28 08:16:41 2013 +0100 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Wed May 08 10:27:52 2013 +0100 @@ -1078,7 +1078,8 @@ mask = MethodFlags; } // Imply STRICTFP if owner has STRICTFP set. - if (((flags|implicit) & Flags.ABSTRACT) == 0) + if (((flags|implicit) & Flags.ABSTRACT) == 0 || + ((flags) & Flags.DEFAULT) != 0) implicit |= sym.owner.flags_field & STRICTFP; break; case TYP: diff -r 27cda5134748 -r 8074ccd57d89 src/share/classes/com/sun/tools/javac/comp/Flow.java --- a/src/share/classes/com/sun/tools/javac/comp/Flow.java Sun Apr 28 08:16:41 2013 +0100 +++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java Wed May 08 10:27:52 2013 +0100 @@ -35,7 +35,6 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.code.Symbol.*; -import com.sun.tools.javac.comp.Resolve; import com.sun.tools.javac.tree.JCTree.*; import static com.sun.tools.javac.code.Flags.*; @@ -277,6 +276,15 @@ } /** + * Utility method to reset several Bits instances. + */ + private void resetBits(Bits... bits) { + for (Bits b : bits) { + b.reset(); + } + } + + /** * Base visitor class for all visitors implementing dataflow analysis logic. * This class define the shared logic for handling jumps (break/continue statements). */ @@ -1294,11 +1302,11 @@ /** The set of definitely assigned variables. */ - Bits inits; + final Bits inits; /** The set of definitely unassigned variables. */ - Bits uninits; + final Bits uninits; /** The set of variables that are definitely unassigned everywhere * in current try block. This variable is maintained lazily; it is @@ -1308,15 +1316,15 @@ * anywhere in current try block, intersect uninitsTry and * uninits. */ - Bits uninitsTry; + final Bits uninitsTry; /** When analyzing a condition, inits and uninits are null. * Instead we have: */ - Bits initsWhenTrue; - Bits initsWhenFalse; - Bits uninitsWhenTrue; - Bits uninitsWhenFalse; + final Bits initsWhenTrue; + final Bits initsWhenFalse; + final Bits uninitsWhenTrue; + final Bits uninitsWhenFalse; /** A mapping from addresses to variable symbols. */ @@ -1348,15 +1356,25 @@ /** The starting position of the analysed tree */ int startPos; + AssignAnalyzer() { + inits = new Bits(); + uninits = new Bits(); + uninitsTry = new Bits(); + initsWhenTrue = new Bits(true); + initsWhenFalse = new Bits(true); + uninitsWhenTrue = new Bits(true); + uninitsWhenFalse = new Bits(true); + } + class AssignPendingExit extends BaseAnalyzer.PendingExit { - Bits exit_inits; - Bits exit_uninits; + final Bits exit_inits = new Bits(true); + final Bits exit_uninits = new Bits(true); - AssignPendingExit(JCTree tree, Bits inits, Bits uninits) { + AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { super(tree); - this.exit_inits = inits.dup(); - this.exit_uninits = uninits.dup(); + this.exit_inits.assign(inits); + this.exit_uninits.assign(uninits); } void resolveJump() { @@ -1476,19 +1494,20 @@ /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets */ void split(boolean setToNull) { - initsWhenFalse = inits.dup(); - uninitsWhenFalse = uninits.dup(); - initsWhenTrue = inits; - uninitsWhenTrue = uninits; - if (setToNull) - inits = uninits = null; + initsWhenFalse.assign(inits); + uninitsWhenFalse.assign(uninits); + initsWhenTrue.assign(inits); + uninitsWhenTrue.assign(uninits); + if (setToNull) { + resetBits(inits, uninits); + } } /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets. */ void merge() { - inits = initsWhenFalse.andSet(initsWhenTrue); - uninits = uninitsWhenFalse.andSet(uninitsWhenTrue); + inits.assign(initsWhenFalse.andSet(initsWhenTrue)); + uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue)); } /* ************************************************************************ @@ -1501,7 +1520,7 @@ void scanExpr(JCTree tree) { if (tree != null) { scan(tree); - if (inits == null) merge(); + if (inits.isReset()) merge(); } } @@ -1518,28 +1537,29 @@ */ void scanCond(JCTree tree) { if (tree.type.isFalse()) { - if (inits == null) merge(); - initsWhenTrue = inits.dup(); + if (inits.isReset()) merge(); + initsWhenTrue.assign(inits); initsWhenTrue.inclRange(firstadr, nextadr); - uninitsWhenTrue = uninits.dup(); + uninitsWhenTrue.assign(uninits); uninitsWhenTrue.inclRange(firstadr, nextadr); - initsWhenFalse = inits; - uninitsWhenFalse = uninits; + initsWhenFalse.assign(inits); + uninitsWhenFalse.assign(uninits); } else if (tree.type.isTrue()) { - if (inits == null) merge(); - initsWhenFalse = inits.dup(); + if (inits.isReset()) merge(); + initsWhenFalse.assign(inits); initsWhenFalse.inclRange(firstadr, nextadr); - uninitsWhenFalse = uninits.dup(); + uninitsWhenFalse.assign(uninits); uninitsWhenFalse.inclRange(firstadr, nextadr); - initsWhenTrue = inits; - uninitsWhenTrue = uninits; + initsWhenTrue.assign(inits); + uninitsWhenTrue.assign(uninits); } else { scan(tree); - if (inits != null) + if (!inits.isReset()) split(tree.type != syms.unknownType); } - if (tree.type != syms.unknownType) - inits = uninits = null; + if (tree.type != syms.unknownType) { + resetBits(inits, uninits); + } } /* ------------ Visitor methods for various sorts of trees -------------*/ @@ -1619,8 +1639,8 @@ public void visitMethodDef(JCMethodDecl tree) { if (tree.body == null) return; - Bits initsPrev = inits.dup(); - Bits uninitsPrev = uninits.dup(); + final Bits initsPrev = new Bits(inits); + final Bits uninitsPrev = new Bits(uninits); int nextadrPrev = nextadr; int firstadrPrev = firstadr; int returnadrPrev = returnadr; @@ -1658,14 +1678,14 @@ exits = exits.tail; Assert.check(exit.tree.hasTag(RETURN), exit.tree); if (isInitialConstructor) { - inits = exit.exit_inits; + inits.assign(exit.exit_inits); for (int i = firstadr; i < nextadr; i++) checkInit(exit.tree.pos(), vars[i]); } } } finally { - inits = initsPrev; - uninits = uninitsPrev; + inits.assign(initsPrev); + uninits.assign(uninitsPrev); nextadr = nextadrPrev; firstadr = firstadrPrev; returnadr = returnadrPrev; @@ -1698,31 +1718,31 @@ ListBuffer prevPendingExits = pendingExits; FlowKind prevFlowKind = flowKind; flowKind = FlowKind.NORMAL; - Bits initsSkip = null; - Bits uninitsSkip = null; + final Bits initsSkip = new Bits(true); + final Bits uninitsSkip = new Bits(true); pendingExits = new ListBuffer(); int prevErrors = log.nerrors; do { - Bits uninitsEntry = uninits.dup(); + final Bits uninitsEntry = new Bits(uninits); uninitsEntry.excludeFrom(nextadr); scan(tree.body); resolveContinues(tree); scanCond(tree.cond); if (!flowKind.isFinal()) { - initsSkip = initsWhenFalse; - uninitsSkip = uninitsWhenFalse; + initsSkip.assign(initsWhenFalse); + uninitsSkip.assign(uninitsWhenFalse); } if (log.nerrors != prevErrors || flowKind.isFinal() || - uninitsEntry.dup().diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) + new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) break; - inits = initsWhenTrue; - uninits = uninitsEntry.andSet(uninitsWhenTrue); + inits.assign(initsWhenTrue); + uninits.assign(uninitsEntry.andSet(uninitsWhenTrue)); flowKind = FlowKind.SPECULATIVE_LOOP; } while (true); flowKind = prevFlowKind; - inits = initsSkip; - uninits = uninitsSkip; + inits.assign(initsSkip); + uninits.assign(uninitsSkip); resolveBreaks(tree, prevPendingExits); } @@ -1730,34 +1750,34 @@ ListBuffer prevPendingExits = pendingExits; FlowKind prevFlowKind = flowKind; flowKind = FlowKind.NORMAL; - Bits initsSkip = null; - Bits uninitsSkip = null; + final Bits initsSkip = new Bits(true); + final Bits uninitsSkip = new Bits(true); pendingExits = new ListBuffer(); int prevErrors = log.nerrors; - Bits uninitsEntry = uninits.dup(); + final Bits uninitsEntry = new Bits(uninits); uninitsEntry.excludeFrom(nextadr); do { scanCond(tree.cond); if (!flowKind.isFinal()) { - initsSkip = initsWhenFalse; - uninitsSkip = uninitsWhenFalse; + initsSkip.assign(initsWhenFalse) ; + uninitsSkip.assign(uninitsWhenFalse); } - inits = initsWhenTrue; - uninits = uninitsWhenTrue; + inits.assign(initsWhenTrue); + uninits.assign(uninitsWhenTrue); scan(tree.body); resolveContinues(tree); if (log.nerrors != prevErrors || flowKind.isFinal() || - uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) + new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) break; - uninits = uninitsEntry.andSet(uninits); + uninits.assign(uninitsEntry.andSet(uninits)); flowKind = FlowKind.SPECULATIVE_LOOP; } while (true); flowKind = prevFlowKind; //a variable is DA/DU after the while statement, if it's DA/DU assuming the //branch is not taken AND if it's DA/DU before any break statement - inits = initsSkip; - uninits = uninitsSkip; + inits.assign(initsSkip); + uninits.assign(uninitsSkip); resolveBreaks(tree, prevPendingExits); } @@ -1767,25 +1787,25 @@ flowKind = FlowKind.NORMAL; int nextadrPrev = nextadr; scan(tree.init); - Bits initsSkip = null; - Bits uninitsSkip = null; + final Bits initsSkip = new Bits(true); + final Bits uninitsSkip = new Bits(true); pendingExits = new ListBuffer(); int prevErrors = log.nerrors; do { - Bits uninitsEntry = uninits.dup(); + final Bits uninitsEntry = new Bits(uninits); uninitsEntry.excludeFrom(nextadr); if (tree.cond != null) { scanCond(tree.cond); if (!flowKind.isFinal()) { - initsSkip = initsWhenFalse; - uninitsSkip = uninitsWhenFalse; + initsSkip.assign(initsWhenFalse); + uninitsSkip.assign(uninitsWhenFalse); } - inits = initsWhenTrue; - uninits = uninitsWhenTrue; + inits.assign(initsWhenTrue); + uninits.assign(uninitsWhenTrue); } else if (!flowKind.isFinal()) { - initsSkip = inits.dup(); + initsSkip.assign(inits); initsSkip.inclRange(firstadr, nextadr); - uninitsSkip = uninits.dup(); + uninitsSkip.assign(uninits); uninitsSkip.inclRange(firstadr, nextadr); } scan(tree.body); @@ -1793,16 +1813,16 @@ scan(tree.step); if (log.nerrors != prevErrors || flowKind.isFinal() || - uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) + new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) break; - uninits = uninitsEntry.andSet(uninits); + uninits.assign(uninitsEntry.andSet(uninits)); flowKind = FlowKind.SPECULATIVE_LOOP; } while (true); flowKind = prevFlowKind; //a variable is DA/DU after a for loop, if it's DA/DU assuming the //branch is not taken AND if it's DA/DU before any break statement - inits = initsSkip; - uninits = uninitsSkip; + inits.assign(initsSkip); + uninits.assign(uninitsSkip); resolveBreaks(tree, prevPendingExits); nextadr = nextadrPrev; } @@ -1815,27 +1835,27 @@ flowKind = FlowKind.NORMAL; int nextadrPrev = nextadr; scan(tree.expr); - Bits initsStart = inits.dup(); - Bits uninitsStart = uninits.dup(); + final Bits initsStart = new Bits(inits); + final Bits uninitsStart = new Bits(uninits); letInit(tree.pos(), tree.var.sym); pendingExits = new ListBuffer(); int prevErrors = log.nerrors; do { - Bits uninitsEntry = uninits.dup(); + final Bits uninitsEntry = new Bits(uninits); uninitsEntry.excludeFrom(nextadr); scan(tree.body); resolveContinues(tree); if (log.nerrors != prevErrors || flowKind.isFinal() || - uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) + new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) break; - uninits = uninitsEntry.andSet(uninits); + uninits.assign(uninitsEntry.andSet(uninits)); flowKind = FlowKind.SPECULATIVE_LOOP; } while (true); flowKind = prevFlowKind; - inits = initsStart; - uninits = uninitsStart.andSet(uninits); + inits.assign(initsStart); + uninits.assign(uninitsStart.andSet(uninits)); resolveBreaks(tree, prevPendingExits); nextadr = nextadrPrev; } @@ -1852,12 +1872,12 @@ pendingExits = new ListBuffer(); int nextadrPrev = nextadr; scanExpr(tree.selector); - Bits initsSwitch = inits; - Bits uninitsSwitch = uninits.dup(); + final Bits initsSwitch = new Bits(inits); + final Bits uninitsSwitch = new Bits(uninits); boolean hasDefault = false; for (List l = tree.cases; l.nonEmpty(); l = l.tail) { - inits = initsSwitch.dup(); - uninits = uninits.andSet(uninitsSwitch); + inits.assign(initsSwitch); + uninits.assign(uninits.andSet(uninitsSwitch)); JCCase c = l.head; if (c.pat == null) hasDefault = true; @@ -1875,8 +1895,8 @@ } // where /** Add any variables defined in stats to inits and uninits. */ - private void addVars(List stats, Bits inits, - Bits uninits) { + private void addVars(List stats, final Bits inits, + final Bits uninits) { for (;stats.nonEmpty(); stats = stats.tail) { JCTree stat = stats.head; if (stat.hasTag(VARDEF)) { @@ -1889,11 +1909,11 @@ public void visitTry(JCTry tree) { ListBuffer resourceVarDecls = ListBuffer.lb(); - Bits uninitsTryPrev = uninitsTry; + final Bits uninitsTryPrev = new Bits(uninitsTry); ListBuffer prevPendingExits = pendingExits; pendingExits = new ListBuffer(); - Bits initsTry = inits.dup(); - uninitsTry = uninits.dup(); + final Bits initsTry = new Bits(inits); + uninitsTry.assign(uninits); for (JCTree resource : tree.resources) { if (resource instanceof JCVariableDecl) { JCVariableDecl vdecl = (JCVariableDecl) resource; @@ -1908,8 +1928,8 @@ } scan(tree.body); uninitsTry.andSet(uninits); - Bits initsEnd = inits; - Bits uninitsEnd = uninits; + final Bits initsEnd = new Bits(inits); + final Bits uninitsEnd = new Bits(uninits); int nextadrCatch = nextadr; if (!resourceVarDecls.isEmpty() && @@ -1925,8 +1945,8 @@ for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { JCVariableDecl param = l.head.param; - inits = initsTry.dup(); - uninits = uninitsTry.dup(); + inits.assign(initsTry); + uninits.assign(uninitsTry); scan(param); inits.incl(param.sym.adr); uninits.excl(param.sym.adr); @@ -1936,8 +1956,8 @@ nextadr = nextadrCatch; } if (tree.finalizer != null) { - inits = initsTry.dup(); - uninits = uninitsTry.dup(); + inits.assign(initsTry); + uninits.assign(uninitsTry); ListBuffer exits = pendingExits; pendingExits = prevPendingExits; scan(tree.finalizer); @@ -1958,8 +1978,8 @@ inits.orSet(initsEnd); } } else { - inits = initsEnd; - uninits = uninitsEnd; + inits.assign(initsEnd); + uninits.assign(uninitsEnd); ListBuffer exits = pendingExits; pendingExits = prevPendingExits; while (exits.nonEmpty()) pendingExits.append(exits.next()); @@ -1969,10 +1989,10 @@ public void visitConditional(JCConditional tree) { scanCond(tree.cond); - Bits initsBeforeElse = initsWhenFalse; - Bits uninitsBeforeElse = uninitsWhenFalse; - inits = initsWhenTrue; - uninits = uninitsWhenTrue; + final Bits initsBeforeElse = new Bits(initsWhenFalse); + final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); + inits.assign(initsWhenTrue); + uninits.assign(uninitsWhenTrue); if (tree.truepart.type.hasTag(BOOLEAN) && tree.falsepart.type.hasTag(BOOLEAN)) { // if b and c are boolean valued, then @@ -1980,12 +2000,12 @@ // v is (un)assigned after b when true and // v is (un)assigned after c when true scanCond(tree.truepart); - Bits initsAfterThenWhenTrue = initsWhenTrue.dup(); - Bits initsAfterThenWhenFalse = initsWhenFalse.dup(); - Bits uninitsAfterThenWhenTrue = uninitsWhenTrue.dup(); - Bits uninitsAfterThenWhenFalse = uninitsWhenFalse.dup(); - inits = initsBeforeElse; - uninits = uninitsBeforeElse; + final Bits initsAfterThenWhenTrue = new Bits(initsWhenTrue); + final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse); + final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue); + final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse); + inits.assign(initsBeforeElse); + uninits.assign(uninitsBeforeElse); scanCond(tree.falsepart); initsWhenTrue.andSet(initsAfterThenWhenTrue); initsWhenFalse.andSet(initsAfterThenWhenFalse); @@ -1993,10 +2013,10 @@ uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse); } else { scanExpr(tree.truepart); - Bits initsAfterThen = inits.dup(); - Bits uninitsAfterThen = uninits.dup(); - inits = initsBeforeElse; - uninits = uninitsBeforeElse; + final Bits initsAfterThen = new Bits(inits); + final Bits uninitsAfterThen = new Bits(uninits); + inits.assign(initsBeforeElse); + uninits.assign(uninitsBeforeElse); scanExpr(tree.falsepart); inits.andSet(initsAfterThen); uninits.andSet(uninitsAfterThen); @@ -2005,16 +2025,16 @@ public void visitIf(JCIf tree) { scanCond(tree.cond); - Bits initsBeforeElse = initsWhenFalse; - Bits uninitsBeforeElse = uninitsWhenFalse; - inits = initsWhenTrue; - uninits = uninitsWhenTrue; + final Bits initsBeforeElse = new Bits(initsWhenFalse); + final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); + inits.assign(initsWhenTrue); + uninits.assign(uninitsWhenTrue); scan(tree.thenpart); if (tree.elsepart != null) { - Bits initsAfterThen = inits.dup(); - Bits uninitsAfterThen = uninits.dup(); - inits = initsBeforeElse; - uninits = uninitsBeforeElse; + final Bits initsAfterThen = new Bits(inits); + final Bits uninitsAfterThen = new Bits(uninits); + inits.assign(initsBeforeElse); + uninits.assign(uninitsBeforeElse); scan(tree.elsepart); inits.andSet(initsAfterThen); uninits.andSet(uninitsAfterThen); @@ -2055,8 +2075,8 @@ @Override public void visitLambda(JCLambda tree) { - Bits prevUninits = uninits; - Bits prevInits = inits; + final Bits prevUninits = new Bits(uninits); + final Bits prevInits = new Bits(inits); int returnadrPrev = returnadr; ListBuffer prevPending = pendingExits; try { @@ -2076,8 +2096,8 @@ } finally { returnadr = returnadrPrev; - uninits = prevUninits; - inits = prevInits; + uninits.assign(prevUninits); + inits.assign(prevInits); pendingExits = prevPending; } } @@ -2088,17 +2108,17 @@ } public void visitAssert(JCAssert tree) { - Bits initsExit = inits.dup(); - Bits uninitsExit = uninits.dup(); + final Bits initsExit = new Bits(inits); + final Bits uninitsExit = new Bits(uninits); scanCond(tree.cond); uninitsExit.andSet(uninitsWhenTrue); if (tree.detail != null) { - inits = initsWhenFalse; - uninits = uninitsWhenFalse; + inits.assign(initsWhenFalse); + uninits.assign(uninitsWhenFalse); scanExpr(tree.detail); } - inits = initsExit; - uninits = uninitsExit; + inits.assign(initsExit); + uninits.assign(uninitsExit); } public void visitAssign(JCAssign tree) { @@ -2120,12 +2140,12 @@ switch (tree.getTag()) { case NOT: scanCond(tree.arg); - Bits t = initsWhenFalse; - initsWhenFalse = initsWhenTrue; - initsWhenTrue = t; - t = uninitsWhenFalse; - uninitsWhenFalse = uninitsWhenTrue; - uninitsWhenTrue = t; + final Bits t = new Bits(initsWhenFalse); + initsWhenFalse.assign(initsWhenTrue); + initsWhenTrue.assign(t); + t.assign(uninitsWhenFalse); + uninitsWhenFalse.assign(uninitsWhenTrue); + uninitsWhenTrue.assign(t); break; case PREINC: case POSTINC: case PREDEC: case POSTDEC: @@ -2141,20 +2161,20 @@ switch (tree.getTag()) { case AND: scanCond(tree.lhs); - Bits initsWhenFalseLeft = initsWhenFalse; - Bits uninitsWhenFalseLeft = uninitsWhenFalse; - inits = initsWhenTrue; - uninits = uninitsWhenTrue; + final Bits initsWhenFalseLeft = new Bits(initsWhenFalse); + final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse); + inits.assign(initsWhenTrue); + uninits.assign(uninitsWhenTrue); scanCond(tree.rhs); initsWhenFalse.andSet(initsWhenFalseLeft); uninitsWhenFalse.andSet(uninitsWhenFalseLeft); break; case OR: scanCond(tree.lhs); - Bits initsWhenTrueLeft = initsWhenTrue; - Bits uninitsWhenTrueLeft = uninitsWhenTrue; - inits = initsWhenFalse; - uninits = uninitsWhenFalse; + final Bits initsWhenTrueLeft = new Bits(initsWhenTrue); + final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue); + inits.assign(initsWhenFalse); + uninits.assign(uninitsWhenFalse); scanCond(tree.rhs); initsWhenTrue.andSet(initsWhenTrueLeft); uninitsWhenTrue.andSet(uninitsWhenTrueLeft); @@ -2200,11 +2220,7 @@ attrEnv = env; Flow.this.make = make; startPos = tree.pos().getStartPosition(); - inits = new Bits(); - uninits = new Bits(); - uninitsTry = new Bits(); - initsWhenTrue = initsWhenFalse = - uninitsWhenTrue = uninitsWhenFalse = null; + if (vars == null) vars = new VarSymbol[32]; else @@ -2219,9 +2235,8 @@ } finally { // note that recursive invocations of this method fail hard startPos = -1; - inits = uninits = uninitsTry = null; - initsWhenTrue = initsWhenFalse = - uninitsWhenTrue = uninitsWhenFalse = null; + resetBits(inits, uninits, uninitsTry, initsWhenTrue, + initsWhenFalse, uninitsWhenTrue, uninitsWhenFalse); if (vars != null) for (int i=0; i attrEnv; /** the analyzer scanner */ - private LambdaAnalyzer analyzer; + private LambdaAnalyzerPreprocessor analyzer; /** map from lambda trees to translation contexts */ private Map> contextMap; @@ -156,7 +155,7 @@ make = TreeMaker.instance(context); types = Types.instance(context); transTypes = TransTypes.instance(context); - analyzer = new LambdaAnalyzer(); + analyzer = new LambdaAnalyzerPreprocessor(); } // @@ -206,7 +205,7 @@ public void visitClassDef(JCClassDecl tree) { if (tree.sym.owner.kind == PCK) { //analyze class - analyzer.analyzeClass(tree); + tree = analyzer.analyzeAndPreprocessClass(tree); } KlassInfo prevKlassInfo = kInfo; try { @@ -531,16 +530,25 @@ /** Make an attributed class instance creation expression. * @param ctype The class type. * @param args The constructor arguments. + * @param cons The constructor symbol */ - JCNewClass makeNewClass(Type ctype, List args) { + JCNewClass makeNewClass(Type ctype, List args, Symbol cons) { JCNewClass tree = make.NewClass(null, null, make.QualIdent(ctype.tsym), args, null); - tree.constructor = rs.resolveConstructor( - null, attrEnv, ctype, TreeInfo.types(args), List.nil()); + tree.constructor = cons; tree.type = ctype; return tree; } + /** Make an attributed class instance creation expression. + * @param ctype The class type. + * @param args The constructor arguments. + */ + JCNewClass makeNewClass(Type ctype, List args) { + return makeNewClass(ctype, args, + rs.resolveConstructor(null, attrEnv, ctype, TreeInfo.types(args), List.nil())); + } + private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym, DiagnosticPosition pos, List staticArgs, MethodType indyType) { String functionalInterfaceClass = classSig(targetType); @@ -1019,8 +1027,9 @@ * This visitor collects information about translation of a lambda expression. * More specifically, it keeps track of the enclosing contexts and captured locals * accessed by the lambda being translated (as well as other useful info). + * It also translates away problems for LambdaToMethod. */ - class LambdaAnalyzer extends TreeScanner { + class LambdaAnalyzerPreprocessor extends TreeTranslator { /** the frame stack - used to reconstruct translation info about enclosing scopes */ private List frameStack; @@ -1047,10 +1056,10 @@ private Map clinits = new HashMap(); - private void analyzeClass(JCClassDecl tree) { + private JCClassDecl analyzeAndPreprocessClass(JCClassDecl tree) { frameStack = List.nil(); localClassDefs = new HashMap(); - scan(tree); + return translate(tree); } @Override @@ -1154,7 +1163,7 @@ frameStack.head.addLocal(param.sym); } contextMap.put(tree, context); - scan(tree.body); + super.visitLambda(tree); context.complete(); } finally { @@ -1220,12 +1229,47 @@ }; fvc.scan(localCDef); } - } + } + /** + * Method references to local class constructors, may, if the local + * class references local variables, have implicit constructor + * parameters added in Lower; As a result, the invokedynamic bootstrap + * information added in the LambdaToMethod pass will have the wrong + * signature. Hooks between Lower and LambdaToMethod have been added to + * handle normal "new" in this case. This visitor converts potentially + * effected method references into a lambda containing a normal "new" of + * the class. + * + * @param tree + */ @Override public void visitReference(JCMemberReference tree) { - scan(tree.getQualifierExpression()); - contextMap.put(tree, makeReferenceContext(tree)); + if (tree.getMode() == ReferenceMode.NEW + && tree.kind != ReferenceKind.ARRAY_CTOR + && tree.sym.owner.isLocal()) { + MethodSymbol consSym = (MethodSymbol) tree.sym; + List ptypes = ((MethodType) consSym.type).getParameterTypes(); + Type classType = consSym.owner.type; + + // Make new-class call + List params = make.Params(ptypes, owner()); + JCNewClass nc = makeNewClass(classType, make.Idents(params)); + nc.pos = tree.pos; + + // Make lambda holding the new-class call + JCLambda slam = make.Lambda(params, nc); + slam.descriptorType = tree.descriptorType; + slam.targets = tree.targets; + slam.type = tree.type; + slam.pos = tree.pos; + + // Now it is a lambda, process as such + visitLambda(slam); + } else { + super.visitReference(tree); + contextMap.put(tree, makeReferenceContext(tree)); + } } @Override @@ -1240,10 +1284,8 @@ } localContext = localContext.prev; } - scan(tree.selected); - } else { - super.visitSelect(tree); } + super.visitSelect(tree); } @Override diff -r 27cda5134748 -r 8074ccd57d89 src/share/classes/com/sun/tools/javac/jvm/Code.java --- a/src/share/classes/com/sun/tools/javac/jvm/Code.java Sun Apr 28 08:16:41 2013 +0100 +++ b/src/share/classes/com/sun/tools/javac/jvm/Code.java Wed May 08 10:27:52 2013 +0100 @@ -1647,7 +1647,7 @@ State dup() { try { State state = (State)super.clone(); - state.defined = defined.dup(); + state.defined = new Bits(defined); state.stack = stack.clone(); if (locks != null) state.locks = locks.clone(); if (debugCode) { @@ -1775,7 +1775,7 @@ } State join(State other) { - defined = defined.andSet(other.defined); + defined.andSet(other.defined); Assert.check(stacksize == other.stacksize && nlocks == other.nlocks); for (int i=0; i= 0; adr = diff.nextBit(adr+1)) { diff -r 27cda5134748 -r 8074ccd57d89 src/share/classes/com/sun/tools/javac/util/Bits.java --- a/src/share/classes/com/sun/tools/javac/util/Bits.java Sun Apr 28 08:16:41 2013 +0100 +++ b/src/share/classes/com/sun/tools/javac/util/Bits.java Wed May 08 10:27:52 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * 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,8 @@ import java.util.Arrays; +import static com.sun.tools.javac.util.Bits.BitsOpKind.*; + /** A class for extensible, mutable bit sets. * *

This is NOT part of any supported API. @@ -36,31 +38,114 @@ */ public class Bits { + public enum BitsOpKind { + INIT, + CLEAR, + INCL_BIT, + EXCL_BIT, + ASSIGN, + AND_SET, + OR_SET, + DIFF_SET, + XOR_SET, + INCL_RANGE, + EXCL_RANGE, + } + + // ____________ reset _________ + // / UNKNOWN \ <-------- / UNINIT \ + // \____________/ | \_________/ + // | | | + // |assign | | any + // | ___________ | + // ------> / NORMAL \ <---- + // \___________/ | + // | | + // | | + // ----------- + // any + private enum BitsState { + /* A Bits instance is in UNKNOWN state if it has been explicitly reset. + * It is possible to get to this state from any other by calling the + * reset method. An instance in the UNKNOWN state can pass to the + * NORMAL state after being assigned another Bits instance. + */ + UNKNOWN, + /* A Bits instance is in UNINIT when it is created with the default + * constructor but it isn't explicitly reset. The main objective of this + * internal state is to save some memory. + */ + UNINIT, + /* The normal state is reached after creating a Bits instance from an + * existing one or after applying any operation to an instance on UNINIT + * or NORMAL state. From this state a bits instance can pass to the + * UNKNOWN state by calling the reset method. + */ + NORMAL; + + static BitsState getState(int[] someBits, boolean reset) { + if (reset) { + return UNKNOWN; + } else { + if (someBits != unassignedBits) { + return NORMAL; + } else { + return UNINIT; + } + } + } + + } private final static int wordlen = 32; private final static int wordshift = 5; private final static int wordmask = wordlen - 1; - private int[] bits; + public int[] bits = null; + // This field will store last version of bits after every change. + public int[] oldBits = null; + + public BitsOpKind lastOperation = null; + + private static final int[] unassignedBits = new int[0]; + + private BitsState currentState; /** Construct an initially empty set. */ public Bits() { - this(new int[1]); + this(false); + } + + public Bits(Bits someBits) { + this(someBits.dup().bits, BitsState.getState(someBits.bits, false)); + } + + public Bits(boolean reset) { + this(unassignedBits, BitsState.getState(unassignedBits, reset)); } /** Construct a set consisting initially of given bit vector. */ - public Bits(int[] bits) { + private Bits(int[] bits, BitsState initState) { this.bits = bits; + this.currentState = initState; + switch (initState) { + case UNKNOWN: + reset(); //this will also set current state; + break; + case NORMAL: + Assert.check(bits != unassignedBits); + lastOperation = INIT; + break; + } } - /** Construct a set consisting initially of given range. + /** This method will be called after any operation that causes a change to + * the bits. Subclasses can thus override it in order to extract information + * from the changes produced to the bits by the given operation. */ - public Bits(int start, int limit) { - this(); - inclRange(start, limit); - } + public void changed() {} private void sizeTo(int len) { if (bits.length < len) { @@ -71,57 +156,110 @@ /** This set = {}. */ public void clear() { + Assert.check(currentState != BitsState.UNKNOWN); + oldBits = bits; + lastOperation = CLEAR; for (int i = 0; i < bits.length; i++) bits[i] = 0; + changed(); + currentState = BitsState.NORMAL; + } + + public void reset() { + bits = null; + oldBits = null; + currentState = BitsState.UNKNOWN; + } + + public boolean isReset() { + return currentState == BitsState.UNKNOWN; + } + + public Bits assign(Bits someBits) { + lastOperation = ASSIGN; + oldBits = bits; + bits = someBits.dup().bits; + changed(); + currentState = BitsState.NORMAL; + return this; } /** Return a copy of this set. */ - public Bits dup() { - int[] newbits = new int[bits.length]; - System.arraycopy(bits, 0, newbits, 0, bits.length); - return new Bits(newbits); + private Bits dup() { + Assert.check(currentState != BitsState.UNKNOWN); + Bits tmp = new Bits(); + if (currentState != BitsState.NORMAL) { + tmp.bits = bits; + } else { + tmp.bits = new int[bits.length]; + System.arraycopy(bits, 0, tmp.bits, 0, bits.length); + } + currentState = BitsState.NORMAL; + return tmp; } /** Include x in this set. */ public void incl(int x) { + Assert.check(currentState != BitsState.UNKNOWN); Assert.check(x >= 0); + oldBits = bits; + lastOperation = INCL_BIT; sizeTo((x >>> wordshift) + 1); bits[x >>> wordshift] = bits[x >>> wordshift] | (1 << (x & wordmask)); + changed(); + currentState = BitsState.NORMAL; } /** Include [start..limit) in this set. */ public void inclRange(int start, int limit) { + Assert.check(currentState != BitsState.UNKNOWN); + oldBits = bits; + lastOperation = INCL_RANGE; sizeTo((limit >>> wordshift) + 1); - for (int x = start; x < limit; x++) + for (int x = start; x < limit; x++) { bits[x >>> wordshift] = bits[x >>> wordshift] | (1 << (x & wordmask)); + } + changed(); + currentState = BitsState.NORMAL; } /** Exclude [start...end] from this set. */ public void excludeFrom(int start) { + Assert.check(currentState != BitsState.UNKNOWN); + oldBits = bits; + lastOperation = EXCL_RANGE; Bits temp = new Bits(); temp.sizeTo(bits.length); temp.inclRange(0, start); - andSet(temp); + internalAndSet(temp); + changed(); + currentState = BitsState.NORMAL; } /** Exclude x from this set. */ public void excl(int x) { + Assert.check(currentState != BitsState.UNKNOWN); Assert.check(x >= 0); + oldBits = bits; + lastOperation = EXCL_BIT; sizeTo((x >>> wordshift) + 1); bits[x >>> wordshift] = bits[x >>> wordshift] & ~(1 << (x & wordmask)); + changed(); + currentState = BitsState.NORMAL; } /** Is x an element of this set? */ public boolean isMember(int x) { + Assert.check(currentState != BitsState.UNKNOWN); return 0 <= x && x < (bits.length << wordshift) && (bits[x >>> wordshift] & (1 << (x & wordmask))) != 0; @@ -130,38 +268,66 @@ /** {@literal this set = this set & xs}. */ public Bits andSet(Bits xs) { + Assert.check(currentState != BitsState.UNKNOWN); + oldBits = bits; + lastOperation = AND_SET; + internalAndSet(xs); + changed(); + currentState = BitsState.NORMAL; + return this; + } + + private void internalAndSet(Bits xs) { + Assert.check(currentState != BitsState.UNKNOWN); sizeTo(xs.bits.length); - for (int i = 0; i < xs.bits.length; i++) + for (int i = 0; i < xs.bits.length; i++) { bits[i] = bits[i] & xs.bits[i]; - return this; + } } /** this set = this set | xs. */ public Bits orSet(Bits xs) { + Assert.check(currentState != BitsState.UNKNOWN); + oldBits = bits; + lastOperation = OR_SET; sizeTo(xs.bits.length); - for (int i = 0; i < xs.bits.length; i++) + for (int i = 0; i < xs.bits.length; i++) { bits[i] = bits[i] | xs.bits[i]; + } + changed(); + currentState = BitsState.NORMAL; return this; } /** this set = this set \ xs. */ public Bits diffSet(Bits xs) { + Assert.check(currentState != BitsState.UNKNOWN); + oldBits = bits; + lastOperation = DIFF_SET; for (int i = 0; i < bits.length; i++) { if (i < xs.bits.length) { bits[i] = bits[i] & ~xs.bits[i]; } } + changed(); + currentState = BitsState.NORMAL; return this; } /** this set = this set ^ xs. */ public Bits xorSet(Bits xs) { + Assert.check(currentState != BitsState.UNKNOWN); + oldBits = bits; + lastOperation = XOR_SET; sizeTo(xs.bits.length); - for (int i = 0; i < xs.bits.length; i++) + for (int i = 0; i < xs.bits.length; i++) { bits[i] = bits[i] ^ xs.bits[i]; + } + changed(); + currentState = BitsState.NORMAL; return this; } @@ -187,6 +353,7 @@ * } */ public int nextBit(int x) { + Assert.check(currentState != BitsState.UNKNOWN); int windex = x >>> wordshift; if (windex >= bits.length) return -1; int word = bits[windex] & ~((1 << (x & wordmask))-1); @@ -202,17 +369,20 @@ /** a string representation of this set. */ public String toString() { - char[] digits = new char[bits.length * wordlen]; - for (int i = 0; i < bits.length * wordlen; i++) - digits[i] = isMember(i) ? '1' : '0'; - return new String(digits); + if (bits.length > 0) { + char[] digits = new char[bits.length * wordlen]; + for (int i = 0; i < bits.length * wordlen; i++) + digits[i] = isMember(i) ? '1' : '0'; + return new String(digits); + } else { + return "[]"; + } } /** Test Bits.nextBit(int). */ public static void main(String[] args) { java.util.Random r = new java.util.Random(); Bits bits = new Bits(); - int dupCount = 0; for (int i=0; i<125; i++) { int k; do { diff -r 27cda5134748 -r 8074ccd57d89 test/tools/javac/api/TestJavacTaskScanner.java --- a/test/tools/javac/api/TestJavacTaskScanner.java Sun Apr 28 08:16:41 2013 +0100 +++ b/test/tools/javac/api/TestJavacTaskScanner.java Wed May 08 10:27:52 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,7 +93,7 @@ System.out.println("#allMembers: " + numAllMembers); check(numTokens, "#Tokens", 1222); - check(numParseTypeElements, "#parseTypeElements", 136); + check(numParseTypeElements, "#parseTypeElements", 158); check(numAllMembers, "#allMembers", 52); } diff -r 27cda5134748 -r 8074ccd57d89 test/tools/javac/defaultMethods/CheckACC_STRICTFlagOnDefaultMethodTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/defaultMethods/CheckACC_STRICTFlagOnDefaultMethodTest.java Wed May 08 10:27:52 2013 +0100 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * 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 8012723 + * @summary strictfp interface misses strictfp modifer on default method + * @run main CheckACC_STRICTFlagOnDefaultMethodTest + */ + +import java.util.ArrayList; +import java.util.List; +import java.io.File; +import java.io.IOException; + +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.Descriptor; +import com.sun.tools.classfile.Descriptor.InvalidDescriptor; +import com.sun.tools.classfile.Method; + +import static com.sun.tools.classfile.AccessFlags.ACC_STRICT; + +public class CheckACC_STRICTFlagOnDefaultMethodTest { + private static final String AssertionErrorMessage = + "All methods should have the ACC_STRICT access flag " + + "please check output"; + private static final String offendingMethodErrorMessage = + "Method %s of class %s doesn't have the ACC_STRICT access flag"; + + private List errors = new ArrayList<>(); + + public static void main(String[] args) + throws IOException, ConstantPoolException, InvalidDescriptor { + new CheckACC_STRICTFlagOnDefaultMethodTest().run(); + } + + private void run() + throws IOException, ConstantPoolException, InvalidDescriptor { + String testClasses = System.getProperty("test.classes"); + check(testClasses, + "CheckACC_STRICTFlagOnDefaultMethodTest$StrictfpInterface.class"); + if (errors.size() > 0) { + for (String error: errors) { + System.err.println(error); + } + throw new AssertionError(AssertionErrorMessage); + } + } + + void check(String dir, String... fileNames) + throws + IOException, + ConstantPoolException, + Descriptor.InvalidDescriptor { + for (String fileName : fileNames) { + ClassFile classFileToCheck = ClassFile.read(new File(dir, fileName)); + + for (Method method : classFileToCheck.methods) { + if ((method.access_flags.flags & ACC_STRICT) == 0) { + errors.add(String.format(offendingMethodErrorMessage, + method.getName(classFileToCheck.constant_pool), + classFileToCheck.getName())); + } + } + } + } + + strictfp interface StrictfpInterface { + default void default_interface_method() {} + static void static_interface_method() {} + } + +} diff -r 27cda5134748 -r 8074ccd57d89 test/tools/javac/lambda/methodReferenceExecution/MethodReferenceTestNewInnerImplicitArgs.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReferenceExecution/MethodReferenceTestNewInnerImplicitArgs.java Wed May 08 10:27:52 2013 +0100 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * 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 8011591 + * @summary BootstrapMethodError when capturing constructor ref to local classes + * @run testng MethodReferenceTestNewInnerImplicitArgs + */ + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * Test the case that a constructor has implicit parameters added to + * access local variables and that this constructor is used in a + * method reference. + * @author Robert Field + */ + +@Test +public class MethodReferenceTestNewInnerImplicitArgs { + + + static class S { + String b; + S(String s, String s2) { b = s + s2; } + } + + interface I { + S m(); + } + + interface I2 { + S m(int i, int j); + } + + public static void testConstructorReferenceImplicitParameters() { + String title = "Hey"; + String a2 = "!!!"; + class MS extends S { + MS() { + super(title, a2); + } + } + + I result = MS::new; + assertEquals(result.m().b, "Hey!!!"); + + class MS2 extends S { + MS2(int x, int y) { + super(title+x, a2+y); + } + } + + I2 result2 = MS2::new; + assertEquals(result2.m(8, 4).b, "Hey8!!!4"); + } +}