8057588: Lots of trivial (empty) classes were generated by the Nashorn compiler as part of restOf-method generation

Fri, 05 Sep 2014 16:28:17 +0200

author
lagergren
date
Fri, 05 Sep 2014 16:28:17 +0200
changeset 1003
3f49db18721f
parent 1002
afdad86ffdde
child 1004
698280da463a

8057588: Lots of trivial (empty) classes were generated by the Nashorn compiler as part of restOf-method generation
Reviewed-by: attila, sundar, hannesw

src/jdk/nashorn/internal/codegen/CompilationPhase.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/CompileUnit.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/Compiler.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/CompileUnitHolder.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/FunctionNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/LiteralNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/SplitNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/CompiledFunction.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Fri Sep 05 16:28:02 2014 +0200
     1.2 +++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Fri Sep 05 16:28:17 2014 +0200
     1.3 @@ -48,10 +48,12 @@
     1.4  import java.util.Map;
     1.5  import java.util.Map.Entry;
     1.6  import java.util.Set;
     1.7 +
     1.8  import jdk.nashorn.internal.AssertsEnabled;
     1.9  import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
    1.10  import jdk.nashorn.internal.ir.FunctionNode;
    1.11  import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
    1.12 +import jdk.nashorn.internal.ir.CompileUnitHolder;
    1.13  import jdk.nashorn.internal.ir.LexicalContext;
    1.14  import jdk.nashorn.internal.ir.LiteralNode;
    1.15  import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
    1.16 @@ -301,6 +303,71 @@
    1.17      },
    1.18  
    1.19      /**
    1.20 +     * Mark compile units used in the method tree. Used for non-rest compilation only
    1.21 +     */
    1.22 +    MARK_USED_COMPILE_UNITS(
    1.23 +            EnumSet.of(
    1.24 +                    INITIALIZED,
    1.25 +                    PARSED,
    1.26 +                    CONSTANT_FOLDED,
    1.27 +                    LOWERED,
    1.28 +                    BUILTINS_TRANSFORMED,
    1.29 +                    SPLIT,
    1.30 +                    SYMBOLS_ASSIGNED,
    1.31 +                    SCOPE_DEPTHS_COMPUTED,
    1.32 +                    OPTIMISTIC_TYPES_ASSIGNED,
    1.33 +                    LOCAL_VARIABLE_TYPES_CALCULATED)) {
    1.34 +
    1.35 +        @Override
    1.36 +        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
    1.37 +            final FunctionNode newFunctionNode = (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
    1.38 +                private void tagUsed(final CompileUnitHolder node) {
    1.39 +                    assert node.getCompileUnit() != null : "no compile unit in " + node;
    1.40 +                    node.getCompileUnit().setUsed();
    1.41 +                }
    1.42 +
    1.43 +                @Override
    1.44 +                public Node leaveFunctionNode(final FunctionNode node) {
    1.45 +                    tagUsed(node);
    1.46 +                    return node;
    1.47 +                }
    1.48 +
    1.49 +                @Override
    1.50 +                public Node leaveSplitNode(final SplitNode node) {
    1.51 +                    tagUsed(node);
    1.52 +                    return node;
    1.53 +                }
    1.54 +
    1.55 +                @Override
    1.56 +                public Node leaveLiteralNode(final LiteralNode<?> node) {
    1.57 +                    if (node instanceof ArrayLiteralNode) {
    1.58 +                        final ArrayLiteralNode aln = (ArrayLiteralNode)node;
    1.59 +                        if (aln.getUnits() != null) {
    1.60 +                            for (final ArrayUnit au : aln.getUnits()) {
    1.61 +                                tagUsed(au);
    1.62 +                            }
    1.63 +                        }
    1.64 +                        return aln;
    1.65 +                    }
    1.66 +                    return node;
    1.67 +                }
    1.68 +
    1.69 +                @Override
    1.70 +                public Node leaveDefault(final Node node) {
    1.71 +                    return node.ensureUniqueLabels(lc);
    1.72 +                }
    1.73 +            });
    1.74 +
    1.75 +            return newFunctionNode;
    1.76 +        }
    1.77 +
    1.78 +        @Override
    1.79 +        public String toString() {
    1.80 +            return "'Tag Compile Units Used'";
    1.81 +        }
    1.82 +    },
    1.83 +
    1.84 +    /**
    1.85       * Reuse compile units, if they are already present. We are using the same compiler
    1.86       * to recompile stuff
    1.87       */
    1.88 @@ -358,6 +425,7 @@
    1.89                      assert newUnit != null : "old unit has no mapping to new unit " + oldUnit;
    1.90  
    1.91                      log.fine("Replacing compile unit: ", oldUnit, " => ", newUnit, " in ", quote(node.getName()));
    1.92 +                    newUnit.setUsed();
    1.93                      return node.setCompileUnit(lc, newUnit).setState(lc, CompilationState.COMPILE_UNITS_REUSED);
    1.94                  }
    1.95  
    1.96 @@ -370,6 +438,7 @@
    1.97                      assert newUnit != null : "old unit has no mapping to new unit " + oldUnit;
    1.98  
    1.99                      log.fine("Replacing compile unit: ", oldUnit, " => ", newUnit, " in ", quote(node.getName()));
   1.100 +                    newUnit.setUsed();
   1.101                      return node.setCompileUnit(lc, newUnit);
   1.102                  }
   1.103  
   1.104 @@ -384,6 +453,7 @@
   1.105                          for (final ArrayUnit au : aln.getUnits()) {
   1.106                              final CompileUnit newUnit = map.get(au.getCompileUnit());
   1.107                              assert newUnit != null;
   1.108 +                            newUnit.setUsed();
   1.109                              newArrayUnits.add(new ArrayUnit(newUnit, au.getLo(), au.getHi()));
   1.110                          }
   1.111                          return aln.setUnits(lc, newArrayUnits);
   1.112 @@ -452,6 +522,11 @@
   1.113              }
   1.114  
   1.115              for (final CompileUnit compileUnit : compiler.getCompileUnits()) {
   1.116 +                if (!compileUnit.isUsed()) {
   1.117 +                    compiler.getLogger().fine("Skipping unused compile unit ", compileUnit);
   1.118 +                    continue;
   1.119 +                }
   1.120 +
   1.121                  final ClassEmitter classEmitter = compileUnit.getClassEmitter();
   1.122                  classEmitter.end();
   1.123  
   1.124 @@ -459,7 +534,6 @@
   1.125                  assert bytecode != null;
   1.126  
   1.127                  final String className = compileUnit.getUnitClassName();
   1.128 -
   1.129                  compiler.addClass(className, bytecode);
   1.130  
   1.131                  // should we verify the generated code?
   1.132 @@ -536,6 +610,9 @@
   1.133  
   1.134              // initialize function in the compile units
   1.135              for (final CompileUnit unit : compiler.getCompileUnits()) {
   1.136 +                if (!unit.isUsed()) {
   1.137 +                    continue;
   1.138 +                }
   1.139                  unit.setCode(installedClasses.get(unit.getUnitClassName()));
   1.140              }
   1.141  
     2.1 --- a/src/jdk/nashorn/internal/codegen/CompileUnit.java	Fri Sep 05 16:28:02 2014 +0200
     2.2 +++ b/src/jdk/nashorn/internal/codegen/CompileUnit.java	Fri Sep 05 16:28:17 2014 +0200
     2.3 @@ -42,6 +42,8 @@
     2.4  
     2.5      private Class<?> clazz;
     2.6  
     2.7 +    private boolean isUsed;
     2.8 +
     2.9      CompileUnit(final String className, final ClassEmitter classEmitter, final long initialWeight) {
    2.10          this.className    = className;
    2.11          this.weight       = initialWeight;
    2.12 @@ -53,6 +55,21 @@
    2.13      }
    2.14  
    2.15      /**
    2.16 +     * Check if this compile unit is used
    2.17 +     * @return true if tagged as in use - i.e active code that needs to be generated
    2.18 +     */
    2.19 +    public boolean isUsed() {
    2.20 +        return isUsed;
    2.21 +    }
    2.22 +
    2.23 +    /**
    2.24 +     * Tag this compile unit as used
    2.25 +     */
    2.26 +    public void setUsed() {
    2.27 +        this.isUsed = true;
    2.28 +    }
    2.29 +
    2.30 +    /**
    2.31       * Return the class that contains the code for this unit, null if not
    2.32       * generated yet
    2.33       *
     3.1 --- a/src/jdk/nashorn/internal/codegen/Compiler.java	Fri Sep 05 16:28:02 2014 +0200
     3.2 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java	Fri Sep 05 16:28:17 2014 +0200
     3.3 @@ -173,13 +173,14 @@
     3.4                          CompilationPhase.SCOPE_DEPTH_COMPUTATION_PHASE,
     3.5                          CompilationPhase.OPTIMISTIC_TYPE_ASSIGNMENT_PHASE,
     3.6                          CompilationPhase.LOCAL_VARIABLE_TYPE_CALCULATION_PHASE,
     3.7 +                        CompilationPhase.MARK_USED_COMPILE_UNITS,
     3.8                          CompilationPhase.BYTECODE_GENERATION_PHASE,
     3.9                          CompilationPhase.INSTALL_PHASE
    3.10                  });
    3.11  
    3.12          /** Compile all for a rest of method */
    3.13          public final static CompilationPhases COMPILE_ALL_RESTOF =
    3.14 -                COMPILE_ALL.setDescription("Compile all, rest of").addAfter(CompilationPhase.LOCAL_VARIABLE_TYPE_CALCULATION_PHASE, CompilationPhase.REUSE_COMPILE_UNITS_PHASE);
    3.15 +                COMPILE_ALL.setDescription("Compile all, rest of").replace(CompilationPhase.MARK_USED_COMPILE_UNITS, CompilationPhase.REUSE_COMPILE_UNITS_PHASE);
    3.16  
    3.17          /** Singleton that describes a standard eager compilation, but no installation, for example used by --compile-only */
    3.18          public final static CompilationPhases COMPILE_ALL_NO_INSTALL =
    3.19 @@ -250,6 +251,15 @@
    3.20              return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()]));
    3.21          }
    3.22  
    3.23 +        private CompilationPhases replace(final CompilationPhase phase, final CompilationPhase newPhase) {
    3.24 +            final LinkedList<CompilationPhase> list = new LinkedList<>();
    3.25 +            for (final CompilationPhase p : phases) {
    3.26 +                list.add(p == phase ? newPhase : p);
    3.27 +            }
    3.28 +            return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()]));
    3.29 +        }
    3.30 +
    3.31 +        @SuppressWarnings("unused") //TODO I'll use this soon
    3.32          private CompilationPhases addAfter(final CompilationPhase phase, final CompilationPhase newPhase) {
    3.33              final LinkedList<CompilationPhase> list = new LinkedList<>();
    3.34              for (final CompilationPhase p : phases) {
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/jdk/nashorn/internal/ir/CompileUnitHolder.java	Fri Sep 05 16:28:17 2014 +0200
     4.3 @@ -0,0 +1,40 @@
     4.4 +/*
     4.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.7 + *
     4.8 + * This code is free software; you can redistribute it and/or modify it
     4.9 + * under the terms of the GNU General Public License version 2 only, as
    4.10 + * published by the Free Software Foundation.  Oracle designates this
    4.11 + * particular file as subject to the "Classpath" exception as provided
    4.12 + * by Oracle in the LICENSE file that accompanied this code.
    4.13 + *
    4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    4.17 + * version 2 for more details (a copy is included in the LICENSE file that
    4.18 + * accompanied this code).
    4.19 + *
    4.20 + * You should have received a copy of the GNU General Public License version
    4.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    4.23 + *
    4.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    4.25 + * or visit www.oracle.com if you need additional information or have any
    4.26 + * questions.
    4.27 + */
    4.28 +
    4.29 +package jdk.nashorn.internal.ir;
    4.30 +
    4.31 +import jdk.nashorn.internal.codegen.CompileUnit;
    4.32 +
    4.33 +/**
    4.34 + * Marker interface for things in the IR that can hold compile units.
    4.35 + * {@link CompileUnit}
    4.36 + */
    4.37 +public interface CompileUnitHolder {
    4.38 +    /**
    4.39 +     * Return the compile unit held by this instance
    4.40 +     * @return compile unit
    4.41 +     */
    4.42 +    public CompileUnit getCompileUnit();
    4.43 +}
     5.1 --- a/src/jdk/nashorn/internal/ir/FunctionNode.java	Fri Sep 05 16:28:02 2014 +0200
     5.2 +++ b/src/jdk/nashorn/internal/ir/FunctionNode.java	Fri Sep 05 16:28:17 2014 +0200
     5.3 @@ -34,10 +34,8 @@
     5.4  
     5.5  import java.util.Collections;
     5.6  import java.util.EnumSet;
     5.7 -import java.util.HashSet;
     5.8  import java.util.Iterator;
     5.9  import java.util.List;
    5.10 -import java.util.Set;
    5.11  import java.util.function.Function;
    5.12  import jdk.nashorn.internal.AssertsEnabled;
    5.13  import jdk.nashorn.internal.codegen.CompileUnit;
    5.14 @@ -58,7 +56,7 @@
    5.15   * IR representation for function (or script.)
    5.16   */
    5.17  @Immutable
    5.18 -public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode> {
    5.19 +public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder {
    5.20      /** Type used for all FunctionNodes */
    5.21      public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class);
    5.22  
    5.23 @@ -1158,6 +1156,7 @@
    5.24       * @see Compiler
    5.25       * @return the compile unit
    5.26       */
    5.27 +    @Override
    5.28      public CompileUnit getCompileUnit() {
    5.29          return compileUnit;
    5.30      }
     6.1 --- a/src/jdk/nashorn/internal/ir/LiteralNode.java	Fri Sep 05 16:28:02 2014 +0200
     6.2 +++ b/src/jdk/nashorn/internal/ir/LiteralNode.java	Fri Sep 05 16:28:17 2014 +0200
     6.3 @@ -603,7 +603,7 @@
     6.4           * An ArrayUnit is a range in an ArrayLiteral. ArrayLiterals can
     6.5           * be split if they are too large, for bytecode generation reasons
     6.6           */
     6.7 -        public static final class ArrayUnit {
     6.8 +        public static final class ArrayUnit implements CompileUnitHolder {
     6.9              /** Compile unit associated with the postsets range. */
    6.10              private final CompileUnit compileUnit;
    6.11  
    6.12 @@ -642,6 +642,7 @@
    6.13               * The array compile unit
    6.14               * @return array compile unit
    6.15               */
    6.16 +            @Override
    6.17              public CompileUnit getCompileUnit() {
    6.18                  return compileUnit;
    6.19              }
     7.1 --- a/src/jdk/nashorn/internal/ir/SplitNode.java	Fri Sep 05 16:28:02 2014 +0200
     7.2 +++ b/src/jdk/nashorn/internal/ir/SplitNode.java	Fri Sep 05 16:28:17 2014 +0200
     7.3 @@ -39,7 +39,7 @@
     7.4   * Node indicating code is split across classes.
     7.5   */
     7.6  @Immutable
     7.7 -public class SplitNode extends LexicalContextStatement implements Labels {
     7.8 +public class SplitNode extends LexicalContextStatement implements Labels, CompileUnitHolder {
     7.9      /** Split node method name. */
    7.10      private final String name;
    7.11  
    7.12 @@ -116,6 +116,7 @@
    7.13       * Get the compile unit for this split node
    7.14       * @return compile unit
    7.15       */
    7.16 +    @Override
    7.17      public CompileUnit getCompileUnit() {
    7.18          return compileUnit;
    7.19      }
     8.1 --- a/src/jdk/nashorn/internal/runtime/CompiledFunction.java	Fri Sep 05 16:28:02 2014 +0200
     8.2 +++ b/src/jdk/nashorn/internal/runtime/CompiledFunction.java	Fri Sep 05 16:28:17 2014 +0200
     8.3 @@ -38,6 +38,7 @@
     8.4  import java.util.TreeMap;
     8.5  import java.util.function.Supplier;
     8.6  import java.util.logging.Level;
     8.7 +
     8.8  import jdk.internal.dynalink.linker.GuardedInvocation;
     8.9  import jdk.nashorn.internal.codegen.Compiler;
    8.10  import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;

mercurial