src/share/classes/com/sun/tools/javac/comp/Attr.java

changeset 2222
8832b6048e65
parent 2210
a746587a1ff1
child 2253
afb6642d0603
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Dec 12 19:19:07 2013 -0800
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Dec 13 14:13:03 2013 +0000
     1.3 @@ -2590,15 +2590,61 @@
     1.4              }
     1.5          }
     1.6  
     1.7 +        /* Map to hold 'fake' clinit methods. If a lambda is used to initialize a
     1.8 +         * static field and that lambda has type annotations, these annotations will
     1.9 +         * also be stored at these fake clinit methods.
    1.10 +         *
    1.11 +         * LambdaToMethod also use fake clinit methods so they can be reused.
    1.12 +         * Also as LTM is a phase subsequent to attribution, the methods from
    1.13 +         * clinits can be safely removed by LTM to save memory.
    1.14 +         */
    1.15 +        private Map<ClassSymbol, MethodSymbol> clinits = new HashMap<>();
    1.16 +
    1.17 +        public MethodSymbol removeClinit(ClassSymbol sym) {
    1.18 +            return clinits.remove(sym);
    1.19 +        }
    1.20 +
    1.21 +        /* This method returns an environment to be used to attribute a lambda
    1.22 +         * expression.
    1.23 +         *
    1.24 +         * The owner of this environment is a method symbol. If the current owner
    1.25 +         * is not a method, for example if the lambda is used to initialize
    1.26 +         * a field, then if the field is:
    1.27 +         *
    1.28 +         * - an instance field, we use the first constructor.
    1.29 +         * - a static field, we create a fake clinit method.
    1.30 +         */
    1.31          private Env<AttrContext> lambdaEnv(JCLambda that, Env<AttrContext> env) {
    1.32              Env<AttrContext> lambdaEnv;
    1.33              Symbol owner = env.info.scope.owner;
    1.34              if (owner.kind == VAR && owner.owner.kind == TYP) {
    1.35                  //field initializer
    1.36                  lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dupUnshared()));
    1.37 -                lambdaEnv.info.scope.owner =
    1.38 -                    new MethodSymbol((owner.flags() & STATIC) | BLOCK, names.empty, null,
    1.39 -                                     env.info.scope.owner);
    1.40 +                ClassSymbol enclClass = owner.enclClass();
    1.41 +                /* if the field isn't static, then we can get the first constructor
    1.42 +                 * and use it as the owner of the environment. This is what
    1.43 +                 * LTM code is doing to look for type annotations so we are fine.
    1.44 +                 */
    1.45 +                if ((owner.flags() & STATIC) == 0) {
    1.46 +                    for (Symbol s : enclClass.members_field.getElementsByName(names.init)) {
    1.47 +                        lambdaEnv.info.scope.owner = s;
    1.48 +                        break;
    1.49 +                    }
    1.50 +                } else {
    1.51 +                    /* if the field is static then we need to create a fake clinit
    1.52 +                     * method, this method can later be reused by LTM.
    1.53 +                     */
    1.54 +                    MethodSymbol clinit = clinits.get(enclClass);
    1.55 +                    if (clinit == null) {
    1.56 +                        Type clinitType = new MethodType(List.<Type>nil(),
    1.57 +                                syms.voidType, List.<Type>nil(), syms.methodClass);
    1.58 +                        clinit = new MethodSymbol(STATIC | SYNTHETIC | PRIVATE,
    1.59 +                                names.clinit, clinitType, enclClass);
    1.60 +                        clinit.params = List.<VarSymbol>nil();
    1.61 +                        clinits.put(enclClass, clinit);
    1.62 +                    }
    1.63 +                    lambdaEnv.info.scope.owner = clinit;
    1.64 +                }
    1.65              } else {
    1.66                  lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup()));
    1.67              }

mercurial