8008648: Lazy JIT scope and callee semantics bugfixes. Broke out wallclock timer.

Thu, 21 Feb 2013 16:57:21 +0100

author
lagergren
date
Thu, 21 Feb 2013 16:57:21 +0100
changeset 108
a971adb68f38
parent 107
671852e35ced
child 109
ae1c9716685b

8008648: Lazy JIT scope and callee semantics bugfixes. Broke out wallclock timer.
Reviewed-by: attila, hannesw

src/jdk/internal/dynalink/beans/BeansLinker.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/CodeGenerator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/CompilationException.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/CompilationPhase.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/Compiler.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/FinalizeTypes.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/Lower.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/MethodEmitter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/Splitter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/FunctionNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/ir/TernaryNode.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/ScriptFunctionTrampolineImpl.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/parser/Parser.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/NashornLoader.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptingFunctions.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/Timing.java file | annotate | diff | comparison | revisions
test/script/trusted/JDK-8006529.js file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/internal/dynalink/beans/BeansLinker.java	Wed Feb 20 16:43:21 2013 +0100
     1.2 +++ b/src/jdk/internal/dynalink/beans/BeansLinker.java	Thu Feb 21 16:57:21 2013 +0100
     1.3 @@ -159,7 +159,7 @@
     1.4          return linkers.get(clazz);
     1.5      }
     1.6  
     1.7 -    /*
     1.8 +    /**
     1.9       * Returns true if the object is a Dynalink Java dynamic method.
    1.10       *
    1.11       * @param obj the object we want to test for being a dynamic method
     2.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Feb 20 16:43:21 2013 +0100
     2.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Thu Feb 21 16:57:21 2013 +0100
     2.3 @@ -850,7 +850,7 @@
     2.4               * Determine if function is varargs and consequently variables have to
     2.5               * be in the scope.
     2.6               */
     2.7 -            final boolean varsInScope = function.varsInScope();
     2.8 +            final boolean varsInScope = function.allVarsInScope();
     2.9  
    2.10              // TODO for LET we can do better: if *block* does not contain any eval/with, we don't need its vars in scope.
    2.11  
    2.12 @@ -2040,7 +2040,6 @@
    2.13          }
    2.14  
    2.15          final Symbol varSymbol = varNode.getSymbol();
    2.16 -
    2.17          assert varSymbol != null : "variable node " + varNode + " requires a symbol";
    2.18  
    2.19          assert method != null;
    2.20 @@ -2058,7 +2057,7 @@
    2.21              }
    2.22              final IdentNode identNode = varNode.getName();
    2.23              final Type type = identNode.getType();
    2.24 -            if(varSymbol.isFastScope(getCurrentFunctionNode())) {
    2.25 +            if (varSymbol.isFastScope(getCurrentFunctionNode())) {
    2.26                  storeFastScopeVar(type, varSymbol, flags);
    2.27              } else {
    2.28                  method.dynamicSet(type, identNode.getName(), flags);
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/jdk/nashorn/internal/codegen/CompilationException.java	Thu Feb 21 16:57:21 2013 +0100
     3.3 @@ -0,0 +1,41 @@
     3.4 +/*
     3.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + *
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.  Oracle designates this
    3.11 + * particular file as subject to the "Classpath" exception as provided
    3.12 + * by Oracle in the LICENSE file that accompanied this code.
    3.13 + *
    3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.17 + * version 2 for more details (a copy is included in the LICENSE file that
    3.18 + * accompanied this code).
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License version
    3.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.23 + *
    3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    3.25 + * or visit www.oracle.com if you need additional information or have any
    3.26 + * questions.
    3.27 + */
    3.28 +package jdk.nashorn.internal.codegen;
    3.29 +
    3.30 +/**
    3.31 + * Exception when something in the compiler breaks down. Can only
    3.32 + * be instantiated by the codegen package
    3.33 + */
    3.34 +@SuppressWarnings("serial")
    3.35 +public class CompilationException extends RuntimeException {
    3.36 +
    3.37 +    CompilationException(final String description) {
    3.38 +        super(description);
    3.39 +    }
    3.40 +
    3.41 +    CompilationException(final Exception cause) {
    3.42 +        super(cause);
    3.43 +    }
    3.44 +}
     4.1 --- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Wed Feb 20 16:43:21 2013 +0100
     4.2 +++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java	Thu Feb 21 16:57:21 2013 +0100
     4.3 @@ -12,15 +12,21 @@
     4.4  import java.io.FileOutputStream;
     4.5  import java.io.IOException;
     4.6  import java.util.EnumSet;
     4.7 +import java.util.HashSet;
     4.8 +import java.util.Set;
     4.9 +
    4.10  import jdk.nashorn.internal.codegen.types.Type;
    4.11 +import jdk.nashorn.internal.ir.CallNode;
    4.12  import jdk.nashorn.internal.ir.FunctionNode;
    4.13  import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
    4.14  import jdk.nashorn.internal.ir.Node;
    4.15 +import jdk.nashorn.internal.ir.ReferenceNode;
    4.16 +import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    4.17  import jdk.nashorn.internal.ir.debug.ASTWriter;
    4.18  import jdk.nashorn.internal.ir.debug.PrintVisitor;
    4.19 -import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    4.20  import jdk.nashorn.internal.runtime.Context;
    4.21  import jdk.nashorn.internal.runtime.ECMAErrors;
    4.22 +import jdk.nashorn.internal.runtime.Timing;
    4.23  
    4.24  /**
    4.25   * A compilation phase is a step in the processes of turning a JavaScript FunctionNode
    4.26 @@ -35,7 +41,7 @@
    4.27       */
    4.28      LAZY_INITIALIZATION_PHASE(EnumSet.of(FunctionNode.CompilationState.INITIALIZED)) {
    4.29          @Override
    4.30 -        boolean transform(final Compiler compiler, final FunctionNode fn) {
    4.31 +        void transform(final Compiler compiler, final FunctionNode fn) {
    4.32  
    4.33              /*
    4.34               * For lazy compilation, we might be given a node previously marked as lazy
    4.35 @@ -53,15 +59,48 @@
    4.36              outermostFunctionNode.setIsLazy(false);
    4.37              outermostFunctionNode.setReturnType(Type.UNKNOWN);
    4.38  
    4.39 +            final Set<FunctionNode> neverLazy = new HashSet<>();
    4.40 +            final Set<FunctionNode> lazy = new HashSet<>();
    4.41 +
    4.42              outermostFunctionNode.accept(new NodeVisitor() {
    4.43 +                // self references are done with invokestatic and thus cannot have trampolines - never lazy
    4.44 +                @Override
    4.45 +                public Node enter(final CallNode node) {
    4.46 +                    final Node callee = node.getFunction();
    4.47 +                    if (callee instanceof ReferenceNode) {
    4.48 +                        neverLazy.add(((ReferenceNode)callee).getReference());
    4.49 +                        return null;
    4.50 +                    }
    4.51 +                    return node;
    4.52 +                }
    4.53 +
    4.54                  @Override
    4.55                  public Node enter(final FunctionNode node) {
    4.56 +                    if (node == outermostFunctionNode) {
    4.57 +                        return node;
    4.58 +                    }
    4.59                      assert Compiler.LAZY_JIT;
    4.60 -                    node.setIsLazy(node != outermostFunctionNode);
    4.61 +                    lazy.add(node);
    4.62 +
    4.63                      return node;
    4.64                  }
    4.65              });
    4.66 -            return true;
    4.67 +
    4.68 +            for (final FunctionNode node : neverLazy) {
    4.69 +                Compiler.LOG.fine("Marking " + node.getName() + " as non lazy, as it's a self reference");
    4.70 +                node.setIsLazy(false);
    4.71 +                lazy.remove(node);
    4.72 +            }
    4.73 +
    4.74 +            for (final FunctionNode node : lazy) {
    4.75 +                Compiler.LOG.fine("Marking " + node.getName() + " as lazy");
    4.76 +                node.setIsLazy(true);
    4.77 +                final FunctionNode parent = node.findParentFunction();
    4.78 +                if (parent != null) {
    4.79 +                    Compiler.LOG.fine("Marking " + parent.getName() + " as having lazy children - it needs scope for all variables");
    4.80 +                    parent.setHasLazyChildren();
    4.81 +                }
    4.82 +            }
    4.83          }
    4.84  
    4.85          @Override
    4.86 @@ -76,9 +115,8 @@
    4.87       */
    4.88      CONSTANT_FOLDING_PHASE(EnumSet.of(INITIALIZED), CONSTANT_FOLDED) {
    4.89          @Override
    4.90 -        boolean transform(final Compiler compiler, final FunctionNode fn) {
    4.91 +        void transform(final Compiler compiler, final FunctionNode fn) {
    4.92              fn.accept(new FoldConstants());
    4.93 -            return true;
    4.94          }
    4.95  
    4.96          @Override
    4.97 @@ -98,9 +136,8 @@
    4.98       */
    4.99      LOWERING_PHASE(EnumSet.of(INITIALIZED, CONSTANT_FOLDED), LOWERED) {
   4.100          @Override
   4.101 -        boolean transform(final Compiler compiler, final FunctionNode fn) {
   4.102 +        void transform(final Compiler compiler, final FunctionNode fn) {
   4.103              fn.accept(new Lower());
   4.104 -            return true;
   4.105          }
   4.106  
   4.107          @Override
   4.108 @@ -115,20 +152,17 @@
   4.109       */
   4.110      ATTRIBUTION_PHASE(EnumSet.of(INITIALIZED, CONSTANT_FOLDED, LOWERED), ATTR) {
   4.111          @Override
   4.112 -        boolean transform(final Compiler compiler, final FunctionNode fn) {
   4.113 +        void transform(final Compiler compiler, final FunctionNode fn) {
   4.114              final Context context = compiler.getContext();
   4.115 -            try {
   4.116 -                fn.accept(new Attr(context));
   4.117 -                return true;
   4.118 -            } finally {
   4.119 -                if (context._print_lower_ast) {
   4.120 -                    context.getErr().println(new ASTWriter(fn));
   4.121 -                }
   4.122  
   4.123 -                if (context._print_lower_parse) {
   4.124 -                    context.getErr().println(new PrintVisitor(fn));
   4.125 -               }
   4.126 +            fn.accept(new Attr(context));
   4.127 +            if (context._print_lower_ast) {
   4.128 +                context.getErr().println(new ASTWriter(fn));
   4.129              }
   4.130 +
   4.131 +            if (context._print_lower_parse) {
   4.132 +                context.getErr().println(new PrintVisitor(fn));
   4.133 +           }
   4.134          }
   4.135  
   4.136          @Override
   4.137 @@ -146,7 +180,7 @@
   4.138       */
   4.139      SPLITTING_PHASE(EnumSet.of(INITIALIZED, CONSTANT_FOLDED, LOWERED, ATTR), SPLIT) {
   4.140          @Override
   4.141 -        boolean transform(final Compiler compiler, final FunctionNode fn) {
   4.142 +        void transform(final Compiler compiler, final FunctionNode fn) {
   4.143              final CompileUnit outermostCompileUnit = compiler.addCompileUnit(compiler.firstCompileUnitName());
   4.144  
   4.145              new Splitter(compiler, fn, outermostCompileUnit).split();
   4.146 @@ -157,7 +191,6 @@
   4.147                  assert compiler.getStrictMode();
   4.148                  compiler.setStrictMode(true);
   4.149              }
   4.150 -            return true;
   4.151          }
   4.152  
   4.153          @Override
   4.154 @@ -181,9 +214,8 @@
   4.155       */
   4.156      TYPE_FINALIZATION_PHASE(EnumSet.of(INITIALIZED, CONSTANT_FOLDED, LOWERED, ATTR, SPLIT), FINALIZED) {
   4.157          @Override
   4.158 -        boolean transform(final Compiler compiler, final FunctionNode fn) {
   4.159 +        void transform(final Compiler compiler, final FunctionNode fn) {
   4.160              fn.accept(new FinalizeTypes());
   4.161 -            return true;
   4.162          }
   4.163  
   4.164          @Override
   4.165 @@ -199,7 +231,7 @@
   4.166       */
   4.167      BYTECODE_GENERATION_PHASE(EnumSet.of(INITIALIZED, CONSTANT_FOLDED, LOWERED, ATTR, SPLIT, FINALIZED), EMITTED) {
   4.168          @Override
   4.169 -        boolean transform(final Compiler compiler, final FunctionNode fn) {
   4.170 +        void transform(final Compiler compiler, final FunctionNode fn) {
   4.171              final Context context = compiler.getContext();
   4.172  
   4.173              try {
   4.174 @@ -253,7 +285,7 @@
   4.175                          final File dir = new File(fileName.substring(0, index));
   4.176                          try {
   4.177                              if (!dir.exists() && !dir.mkdirs()) {
   4.178 -                                throw new IOException();
   4.179 +                                throw new IOException(dir.toString());
   4.180                              }
   4.181                              final File file = new File(context._dest_dir, fileName);
   4.182                              try (final FileOutputStream fos = new FileOutputStream(file)) {
   4.183 @@ -265,8 +297,6 @@
   4.184                      }
   4.185                  }
   4.186              }
   4.187 -
   4.188 -            return true;
   4.189          }
   4.190  
   4.191          @Override
   4.192 @@ -281,8 +311,6 @@
   4.193      private long endTime;
   4.194      private boolean isFinished;
   4.195  
   4.196 -    private static final long[] accumulatedTime = new long[CompilationPhase.values().length];
   4.197 -
   4.198      private CompilationPhase(final EnumSet<CompilationState> pre) {
   4.199          this(pre, null);
   4.200      }
   4.201 @@ -313,7 +341,7 @@
   4.202  
   4.203      protected void end(final FunctionNode functionNode) {
   4.204          endTime = System.currentTimeMillis();
   4.205 -        accumulatedTime[ordinal()] += (endTime - startTime);
   4.206 +        Timing.accumulateTime(toString(), endTime - startTime);
   4.207  
   4.208          if (post != null) {
   4.209              functionNode.setState(post);
   4.210 @@ -334,23 +362,15 @@
   4.211          return endTime;
   4.212      }
   4.213  
   4.214 -    public static long getAccumulatedTime(final CompilationPhase phase) {
   4.215 -        return accumulatedTime[phase.ordinal()];
   4.216 -    }
   4.217 +    abstract void transform(final Compiler compiler, final FunctionNode functionNode) throws CompilationException;
   4.218  
   4.219 -    abstract boolean transform(final Compiler compiler, final FunctionNode functionNode);
   4.220 -
   4.221 -    final boolean apply(final Compiler compiler, final FunctionNode functionNode) {
   4.222 -        try {
   4.223 -            if (!isApplicable(functionNode)) {
   4.224 -                return false;
   4.225 -            }
   4.226 -            begin(functionNode);
   4.227 -            transform(compiler, functionNode);
   4.228 -            return true;
   4.229 -        } finally {
   4.230 -            end(functionNode);
   4.231 +    final void apply(final Compiler compiler, final FunctionNode functionNode) throws CompilationException {
   4.232 +        if (!isApplicable(functionNode)) {
   4.233 +            throw new CompilationException("compile phase not applicable: " + this);
   4.234          }
   4.235 +        begin(functionNode);
   4.236 +        transform(compiler, functionNode);
   4.237 +        end(functionNode);
   4.238      }
   4.239  
   4.240  }
     5.1 --- a/src/jdk/nashorn/internal/codegen/Compiler.java	Wed Feb 20 16:43:21 2013 +0100
     5.2 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java	Thu Feb 21 16:57:21 2013 +0100
     5.3 @@ -54,6 +54,7 @@
     5.4  import jdk.nashorn.internal.runtime.Context;
     5.5  import jdk.nashorn.internal.runtime.DebugLogger;
     5.6  import jdk.nashorn.internal.runtime.Source;
     5.7 +import jdk.nashorn.internal.runtime.Timing;
     5.8  import jdk.nashorn.internal.runtime.options.Options;
     5.9  
    5.10  /**
    5.11 @@ -72,8 +73,6 @@
    5.12  
    5.13      static final boolean LAZY_JIT = Options.getBooleanProperty("nashorn.compiler.lazy");
    5.14  
    5.15 -    static final boolean TIME_COMPILATION = Options.getBooleanProperty("nashorn.compiler.time");
    5.16 -
    5.17      private final Map<String, byte[]> bytecode;
    5.18  
    5.19      private final Set<CompileUnit> compileUnits;
    5.20 @@ -92,7 +91,9 @@
    5.21  
    5.22      private CodeInstaller<Context> installer;
    5.23  
    5.24 -    static final DebugLogger LOG = new DebugLogger("compiler");
    5.25 +    /** logger for compiler, trampolines, splits and related code generation events
    5.26 +     *  that affect classes */
    5.27 +    public static final DebugLogger LOG = new DebugLogger("compiler");
    5.28  
    5.29      /**
    5.30       * This array contains names that need to be reserved at the start
    5.31 @@ -179,6 +180,13 @@
    5.32              SEQUENCE_LAZY :
    5.33              SEQUENCE_NORMAL;
    5.34  
    5.35 +    private static String lazyTag(final FunctionNode functionNode) {
    5.36 +        if (functionNode.isLazy()) {
    5.37 +            return '$' + LAZY.tag() + '$' + functionNode.getName();
    5.38 +        }
    5.39 +        return "";
    5.40 +    }
    5.41 +
    5.42      /**
    5.43       * Constructor
    5.44       *
    5.45 @@ -187,6 +195,7 @@
    5.46       * @param sequence     {@link Compiler#CompilationSequence} of {@link CompilationPhase}s to apply as this compilation
    5.47       * @param strict       should this compilation use strict mode semantics
    5.48       */
    5.49 +    //TODO support an array of FunctionNodes for batch lazy compilation
    5.50      Compiler(final Context context, final CodeInstaller<Context> installer, final FunctionNode functionNode, final CompilationSequence sequence, final boolean strict) {
    5.51          this.context       = context;
    5.52          this.functionNode  = functionNode;
    5.53 @@ -198,14 +207,16 @@
    5.54          this.bytecode      = new HashMap<>();
    5.55  
    5.56          final StringBuilder sb = new StringBuilder();
    5.57 -        sb.append(functionNode.uniqueName(DEFAULT_SCRIPT_NAME.tag())).
    5.58 +        sb.append(functionNode.uniqueName(DEFAULT_SCRIPT_NAME.tag() + lazyTag(functionNode))).
    5.59                  append('$').
    5.60 -                append(safeSourceName(functionNode.getSource())).
    5.61 -                append(functionNode.isLazy() ? LAZY.tag() : "");
    5.62 +                append(safeSourceName(functionNode.getSource()));
    5.63  
    5.64          this.scriptName = sb.toString();
    5.65  
    5.66 -        LOG.info("Initializing compiler for scriptName = " + scriptName + ", root function: '" + functionNode.getName() + "'");
    5.67 +        LOG.info("Initializing compiler for '" + functionNode.getName() + "' scriptName = " + scriptName + ", root function: '" + functionNode.getName() + "'");
    5.68 +        if (functionNode.isLazy()) {
    5.69 +            LOG.info(">>> This is a lazy recompilation triggered by a trampoline");
    5.70 +        }
    5.71      }
    5.72  
    5.73      /**
    5.74 @@ -241,22 +252,23 @@
    5.75  
    5.76      /**
    5.77       * Execute the compilation this Compiler was created with
    5.78 -     * @return true if compilation succeeds.
    5.79 +     * @throws CompilationException if something goes wrong
    5.80       */
    5.81 -    public boolean compile() {
    5.82 +    public void compile() throws CompilationException {
    5.83          for (final String reservedName : RESERVED_NAMES) {
    5.84              functionNode.uniqueName(reservedName);
    5.85          }
    5.86  
    5.87          for (final CompilationPhase phase : sequence) {
    5.88 -            LOG.info("Entering compile phase " + phase + " for function '" + functionNode.getName() + "'");
    5.89 -            if (phase.isApplicable(functionNode)) {
    5.90 -                if (!phase.apply(this, functionNode)) { //TODO exceptions, error logging
    5.91 -                    return false;
    5.92 -                }
    5.93 +            phase.apply(this, functionNode);
    5.94 +            final String end = phase.toString() + " done for function '" + functionNode.getName() + "'";
    5.95 +            if (Timing.isEnabled()) {
    5.96 +                final long duration = phase.getEndTime() - phase.getStartTime();
    5.97 +                LOG.info(end + " in " + duration + " ms");
    5.98 +            } else {
    5.99 +                LOG.info(end);
   5.100              }
   5.101          }
   5.102 -        return true;
   5.103      }
   5.104  
   5.105      /**
   5.106 @@ -264,11 +276,15 @@
   5.107       * @return root script class - if there are several compile units they will also be installed
   5.108       */
   5.109      public Class<?> install() {
   5.110 +        final long t0 = Timing.isEnabled() ? System.currentTimeMillis() : 0L;
   5.111 +
   5.112 +        assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " has no bytecode and cannot be installed";
   5.113 +
   5.114          Class<?> rootClass = null;
   5.115  
   5.116          for (final Entry<String, byte[]> entry : bytecode.entrySet()) {
   5.117              final String     className = entry.getKey();
   5.118 -            LOG.info("Installing class " + className);
   5.119 +            LOG.fine("Installing class " + className);
   5.120  
   5.121              final byte[]     code  = entry.getValue();
   5.122              final Class<?>   clazz = installer.install(Compiler.binaryName(className), code);
   5.123 @@ -299,7 +315,13 @@
   5.124              }
   5.125          }
   5.126  
   5.127 -        LOG.info("Root class: " + rootClass);
   5.128 +        LOG.info("Installed root class: " + rootClass + " and " + bytecode.size() + " compile unit classes");
   5.129 +        if (Timing.isEnabled()) {
   5.130 +            final long duration = System.currentTimeMillis() - t0;
   5.131 +            Timing.accumulateTime("[Code Installation]", duration);
   5.132 +            LOG.info("Installation time: " + duration + " ms");
   5.133 +        }
   5.134 +
   5.135          return rootClass;
   5.136      }
   5.137  
   5.138 @@ -376,7 +398,7 @@
   5.139      private CompileUnit addCompileUnit(final String unitClassName, final long initialWeight) {
   5.140          final CompileUnit compileUnit = initCompileUnit(unitClassName, initialWeight);
   5.141          compileUnits.add(compileUnit);
   5.142 -        LOG.info("Added compile unit " + compileUnit);
   5.143 +        LOG.fine("Added compile unit " + compileUnit);
   5.144          return compileUnit;
   5.145      }
   5.146  
   5.147 @@ -438,24 +460,4 @@
   5.148          assert !USE_INT_ARITH : "Integer arithmetic is not enabled";
   5.149      }
   5.150  
   5.151 -    static {
   5.152 -        if (TIME_COMPILATION) {
   5.153 -            Runtime.getRuntime().addShutdownHook(new Thread() {
   5.154 -                @Override
   5.155 -                public void run() {
   5.156 -                    for (final CompilationPhase phase : CompilationPhase.values()) {
   5.157 -                        final StringBuilder sb = new StringBuilder();
   5.158 -                        sb.append(phase);
   5.159 -                        while (sb.length() < 32) {
   5.160 -                            sb.append(' ');
   5.161 -                        }
   5.162 -                        sb.append(CompilationPhase.getAccumulatedTime(phase));
   5.163 -                        sb.append(' ');
   5.164 -                        sb.append(" ms");
   5.165 -                        System.err.println(sb.toString()); //Context err is gone by shutdown TODO
   5.166 -                    }
   5.167 -                }
   5.168 -            });
   5.169 -        }
   5.170 -    }
   5.171  }
     6.1 --- a/src/jdk/nashorn/internal/codegen/FinalizeTypes.java	Wed Feb 20 16:43:21 2013 +0100
     6.2 +++ b/src/jdk/nashorn/internal/codegen/FinalizeTypes.java	Thu Feb 21 16:57:21 2013 +0100
     6.3 @@ -562,7 +562,7 @@
     6.4  
     6.5          final FunctionNode functionNode   = block.getFunction();
     6.6          final List<Symbol> symbols        = block.getFrame().getSymbols();
     6.7 -        final boolean      allVarsInScope = functionNode.varsInScope();
     6.8 +        final boolean      allVarsInScope = functionNode.allVarsInScope();
     6.9          final boolean      isVarArg       = functionNode.isVarArg();
    6.10  
    6.11          for (final Symbol symbol : symbols) {
     7.1 --- a/src/jdk/nashorn/internal/codegen/Lower.java	Wed Feb 20 16:43:21 2013 +0100
     7.2 +++ b/src/jdk/nashorn/internal/codegen/Lower.java	Thu Feb 21 16:57:21 2013 +0100
     7.3 @@ -709,7 +709,6 @@
     7.4       * @return eval location
     7.5       */
     7.6      private static String evalLocation(final IdentNode node) {
     7.7 -        //final StringBuilder sb = new StringBuilder(node.getSource().getName());
     7.8          return new StringBuilder().
     7.9              append(node.getSource().getName()).
    7.10              append('#').
     8.1 --- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Wed Feb 20 16:43:21 2013 +0100
     8.2 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Thu Feb 21 16:57:21 2013 +0100
     8.3 @@ -203,7 +203,7 @@
     8.4  
     8.5      @Override
     8.6      public String toString() {
     8.7 -        return "methodEmitter: " + (functionNode == null ? method : functionNode.getName()).toString();
     8.8 +        return "methodEmitter: " + (functionNode == null ? method : functionNode.getName()).toString() + ' ' + stack;
     8.9      }
    8.10  
    8.11      /**
     9.1 --- a/src/jdk/nashorn/internal/codegen/Splitter.java	Wed Feb 20 16:43:21 2013 +0100
     9.2 +++ b/src/jdk/nashorn/internal/codegen/Splitter.java	Thu Feb 21 16:57:21 2013 +0100
     9.3 @@ -92,15 +92,15 @@
     9.4       */
     9.5      void split() {
     9.6          if (functionNode.isLazy()) {
     9.7 -            LOG.info("Postponing split of '" + functionNode.getName() + "' as it's lazy");
     9.8 +            LOG.fine("Postponing split of '" + functionNode.getName() + "' as it's lazy");
     9.9              return;
    9.10          }
    9.11 -        LOG.info("Initiating split of '" + functionNode.getName() + "'");
    9.12 +        LOG.fine("Initiating split of '" + functionNode.getName() + "'");
    9.13  
    9.14          long weight = WeighNodes.weigh(functionNode);
    9.15  
    9.16          if (weight >= SPLIT_THRESHOLD) {
    9.17 -            LOG.info("Splitting '" + functionNode.getName() + "' as its weight " + weight + " exceeds split threshold " + SPLIT_THRESHOLD);
    9.18 +            LOG.fine("Splitting '" + functionNode.getName() + "' as its weight " + weight + " exceeds split threshold " + SPLIT_THRESHOLD);
    9.19  
    9.20              functionNode.accept(this);
    9.21  
    10.1 --- a/src/jdk/nashorn/internal/ir/FunctionNode.java	Wed Feb 20 16:43:21 2013 +0100
    10.2 +++ b/src/jdk/nashorn/internal/ir/FunctionNode.java	Thu Feb 21 16:57:21 2013 +0100
    10.3 @@ -188,25 +188,27 @@
    10.4      private static final int IS_LOWERED                  = 0b0000_0000_0001_0000;
    10.5      /** Has this node been split because it was too large? */
    10.6      private static final int IS_SPLIT                    = 0b0000_0000_0010_0000;
    10.7 +    /** Does the function call eval? */
    10.8 +    private static final int HAS_EVAL                    = 0b0000_0000_0100_0000;
    10.9 +    /** Does the function contain a with block ? */
   10.10 +    private static final int HAS_WITH                    = 0b0000_0000_1000_0000;
   10.11 +    /** Does a descendant function contain a with or eval? */
   10.12 +    private static final int HAS_DESCENDANT_WITH_OR_EVAL = 0b0000_0001_0000_0000;
   10.13 +    /** Does the function define "arguments" identifier as a parameter of nested function name? */
   10.14 +    private static final int DEFINES_ARGUMENTS           = 0b0000_0010_0000_0000;
   10.15 +    /** Does the function need a self symbol? */
   10.16 +    private static final int NEEDS_SELF_SYMBOL           = 0b0000_0100_0000_0000;
   10.17 +    /** Does this function or any of its descendants use variables from an ancestor function's scope (incl. globals)? */
   10.18 +    private static final int USES_ANCESTOR_SCOPE         = 0b0000_1000_0000_0000;
   10.19      /** Is this function lazily compiled? */
   10.20 -    private static final int IS_LAZY                     = 0b0000_0000_0100_0000;
   10.21 -    /** Does the function call eval? */
   10.22 -    private static final int HAS_EVAL                    = 0b0000_0000_1000_0000;
   10.23 -    /** Does the function contain a with block ? */
   10.24 -    private static final int HAS_WITH                    = 0b0000_0001_0000_0000;
   10.25 -    /** Does a descendant function contain a with or eval? */
   10.26 -    private static final int HAS_DESCENDANT_WITH_OR_EVAL = 0b0000_0010_0000_0000;
   10.27 -    /** Does the function define "arguments" identifier as a parameter of nested function name? */
   10.28 -    private static final int DEFINES_ARGUMENTS           = 0b0000_0100_0000_0000;
   10.29 -    /** Does the function need a self symbol? */
   10.30 -    private static final int NEEDS_SELF_SYMBOL           = 0b0000_1000_0000_0000;
   10.31 -    /** Does this function or any of its descendants use variables from an ancestor function's scope (incl. globals)? */
   10.32 -    private static final int USES_ANCESTOR_SCOPE         = 0b0001_0000_0000_0000;
   10.33 +    private static final int IS_LAZY                     = 0b0001_0000_0000_0000;
   10.34 +    /** Does this function have lazy, yet uncompiled children */
   10.35 +    private static final int HAS_LAZY_CHILDREN           = 0b0010_0000_0000_0000;
   10.36  
   10.37      /** Does this function or any nested functions contain a with or an eval? */
   10.38      private static final int HAS_DEEP_WITH_OR_EVAL = HAS_EVAL | HAS_WITH | HAS_DESCENDANT_WITH_OR_EVAL;
   10.39      /** Does this function need to store all its variables in scope? */
   10.40 -    private static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_WITH_OR_EVAL | IS_SPLIT;
   10.41 +    private static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_WITH_OR_EVAL | IS_SPLIT | HAS_LAZY_CHILDREN;
   10.42      /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */
   10.43      private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL;
   10.44      /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep with or eval. */
   10.45 @@ -862,7 +864,7 @@
   10.46       *
   10.47       * @return true if all variables should be in scope
   10.48       */
   10.49 -    public boolean varsInScope() {
   10.50 +    public boolean allVarsInScope() {
   10.51          return isScript() || (flags & HAS_ALL_VARS_IN_SCOPE) != 0;
   10.52      }
   10.53  
   10.54 @@ -884,6 +886,23 @@
   10.55      }
   10.56  
   10.57      /**
   10.58 +     * Checks if this function has yet-to-be-generated child functions
   10.59 +     *
   10.60 +     * @return true if there are lazy child functions
   10.61 +     */
   10.62 +    public boolean hasLazyChildren() {
   10.63 +        return (flags & HAS_LAZY_CHILDREN) != 0;
   10.64 +    }
   10.65 +
   10.66 +    /**
   10.67 +     * Flag this function node as having yet-to-be-generated child functions
   10.68 +     */
   10.69 +    public void setHasLazyChildren() {
   10.70 +        this.flags |= HAS_LAZY_CHILDREN;
   10.71 +        setNeedsScope();
   10.72 +    }
   10.73 +
   10.74 +    /**
   10.75       * Get the parameters to this function
   10.76       * @return a list of IdentNodes which represent the function parameters, in order
   10.77       */
    11.1 --- a/src/jdk/nashorn/internal/ir/TernaryNode.java	Wed Feb 20 16:43:21 2013 +0100
    11.2 +++ b/src/jdk/nashorn/internal/ir/TernaryNode.java	Thu Feb 21 16:57:21 2013 +0100
    11.3 @@ -54,7 +54,7 @@
    11.4      private TernaryNode(final TernaryNode ternaryNode, final CopyState cs) {
    11.5          super(ternaryNode, cs);
    11.6  
    11.7 -        third = cs.existingOrCopy(ternaryNode.third);
    11.8 +        this.third = cs.existingOrCopy(ternaryNode.third);
    11.9      }
   11.10  
   11.11      @Override
    12.1 --- a/src/jdk/nashorn/internal/objects/ScriptFunctionTrampolineImpl.java	Wed Feb 20 16:43:21 2013 +0100
    12.2 +++ b/src/jdk/nashorn/internal/objects/ScriptFunctionTrampolineImpl.java	Thu Feb 21 16:57:21 2013 +0100
    12.3 @@ -5,6 +5,7 @@
    12.4  import java.lang.invoke.MethodHandle;
    12.5  import java.lang.invoke.MethodHandles;
    12.6  import java.lang.invoke.MethodType;
    12.7 +import jdk.nashorn.internal.codegen.CompilationException;
    12.8  import jdk.nashorn.internal.codegen.Compiler;
    12.9  import jdk.nashorn.internal.codegen.FunctionSignature;
   12.10  import jdk.nashorn.internal.codegen.types.Type;
   12.11 @@ -77,12 +78,10 @@
   12.12          return super.makeBoundFunction(data);
   12.13      }
   12.14  
   12.15 -    private MethodHandle compile() {
   12.16 +    private MethodHandle compile() throws CompilationException {
   12.17          final Compiler compiler = new Compiler(installer, functionNode);
   12.18 -        if (!compiler.compile()) {
   12.19 -            assert false : "compilation error in trampoline for " + functionNode.getName();
   12.20 -            return null;
   12.21 -        }
   12.22 +
   12.23 +        compiler.compile();
   12.24  
   12.25          final Class<?> clazz = compiler.install();
   12.26          /* compute function signature for lazy method. this can be done first after compilation, as only then do we know
   12.27 @@ -91,7 +90,9 @@
   12.28          final MethodType        mt        = signature.getMethodType();
   12.29  
   12.30          MethodHandle mh = MH.findStatic(MethodHandles.publicLookup(), clazz, functionNode.getName(), mt);
   12.31 -        mh = MH.bindTo(mh, this);
   12.32 +        if (functionNode.needsCallee()) {
   12.33 +            mh = MH.bindTo(mh, this);
   12.34 +        }
   12.35  
   12.36          // now the invoker method looks like the one our superclass is expecting
   12.37          resetInvoker(mh);
   12.38 @@ -100,11 +101,11 @@
   12.39      }
   12.40  
   12.41      @SuppressWarnings("unused")
   12.42 -    private Object trampoline(final Object... args) {
   12.43 -        /** Create a new compiler for the lazy node, using the same installation policy as the old one */
   12.44 -
   12.45 +    private Object trampoline(final Object... args) throws CompilationException {
   12.46 +        Compiler.LOG.info(">>> TRAMPOLINE: Hitting trampoline for '" + functionNode.getName() + "'");
   12.47          MethodHandle mh = compile();
   12.48  
   12.49 +        Compiler.LOG.info("<<< COMPILED TO: " + mh);
   12.50          // spread the array to invididual args of the correct type
   12.51          mh = MH.asSpreader(mh, Object[].class, mh.type().parameterCount());
   12.52  
    13.1 --- a/src/jdk/nashorn/internal/parser/Parser.java	Wed Feb 20 16:43:21 2013 +0100
    13.2 +++ b/src/jdk/nashorn/internal/parser/Parser.java	Thu Feb 21 16:57:21 2013 +0100
    13.3 @@ -97,15 +97,16 @@
    13.4  import jdk.nashorn.internal.ir.WhileNode;
    13.5  import jdk.nashorn.internal.ir.WithNode;
    13.6  import jdk.nashorn.internal.runtime.Context;
    13.7 +import jdk.nashorn.internal.runtime.DebugLogger;
    13.8  import jdk.nashorn.internal.runtime.ErrorManager;
    13.9  import jdk.nashorn.internal.runtime.JSErrorType;
   13.10  import jdk.nashorn.internal.runtime.ParserException;
   13.11  import jdk.nashorn.internal.runtime.ScriptingFunctions;
   13.12  import jdk.nashorn.internal.runtime.Source;
   13.13 +import jdk.nashorn.internal.runtime.Timing;
   13.14  
   13.15  /**
   13.16   * Builds the IR.
   13.17 - *
   13.18   */
   13.19  public class Parser extends AbstractParser {
   13.20      /** Current context. */
   13.21 @@ -126,6 +127,8 @@
   13.22      /** Namespace for function names where not explicitly given */
   13.23      private final Namespace namespace;
   13.24  
   13.25 +    private static DebugLogger LOG = new DebugLogger("parser");
   13.26 +
   13.27      /**
   13.28       * Constructor
   13.29       *
   13.30 @@ -176,6 +179,9 @@
   13.31       * @return function node resulting from successful parse
   13.32       */
   13.33      public FunctionNode parse(final String scriptName) {
   13.34 +        final long t0 = Timing.isEnabled() ? System.currentTimeMillis() : 0L;
   13.35 +        LOG.info(this + " begin for '" + scriptName + "'");
   13.36 +
   13.37          try {
   13.38              stream = new TokenStream();
   13.39              lexer  = new Lexer(source, stream, scripting && !context._no_syntax_extensions);
   13.40 @@ -208,6 +214,14 @@
   13.41              }
   13.42  
   13.43              return null;
   13.44 +         } finally {
   13.45 +             final String end = this + " end '" + scriptName + "'";
   13.46 +             if (Timing.isEnabled()) {
   13.47 +                 Timing.accumulateTime(toString(), System.currentTimeMillis() - t0);
   13.48 +                 LOG.info(end + "' in " + (System.currentTimeMillis() - t0) + " ms");
   13.49 +             } else {
   13.50 +                 LOG.info(end);
   13.51 +             }
   13.52           }
   13.53      }
   13.54  
   13.55 @@ -3064,4 +3078,8 @@
   13.56          return null;
   13.57      }
   13.58  
   13.59 +    @Override
   13.60 +    public String toString() {
   13.61 +        return "[JavaScript Parsing]";
   13.62 +    }
   13.63  }
    14.1 --- a/src/jdk/nashorn/internal/runtime/NashornLoader.java	Wed Feb 20 16:43:21 2013 +0100
    14.2 +++ b/src/jdk/nashorn/internal/runtime/NashornLoader.java	Thu Feb 21 16:57:21 2013 +0100
    14.3 @@ -57,7 +57,7 @@
    14.4       * @param name name of the class to be loaded
    14.5       * @param resolve whether the class should be resolved or not
    14.6       * @return Class object
    14.7 -     * @throws ClassNotFoundException
    14.8 +     * @throws ClassNotFoundException if class cannot be loaded
    14.9       */
   14.10      protected final Class<?> loadClassTrusted(final String name, final boolean resolve) throws ClassNotFoundException {
   14.11          return super.loadClass(name, resolve);
    15.1 --- a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Wed Feb 20 16:43:21 2013 +0100
    15.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Thu Feb 21 16:57:21 2013 +0100
    15.3 @@ -121,11 +121,11 @@
    15.4       *
    15.5       * @param self   self reference
    15.6       * @param string string to execute
    15.7 -     * @param input
    15.8 +     * @param input  input
    15.9       *
   15.10       * @return output string from the request
   15.11 -     * @throws IOException
   15.12 -     * @throws InterruptedException
   15.13 +     * @throws IOException           if any stream access fails
   15.14 +     * @throws InterruptedException  if execution is interrupted
   15.15       */
   15.16      public static Object exec(final Object self, final Object string, final Object input) throws IOException, InterruptedException {
   15.17          // Current global is need to fetch additional inputs and for additional results.
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/src/jdk/nashorn/internal/runtime/Timing.java	Thu Feb 21 16:57:21 2013 +0100
    16.3 @@ -0,0 +1,109 @@
    16.4 +/*
    16.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    16.7 + *
    16.8 + * This code is free software; you can redistribute it and/or modify it
    16.9 + * under the terms of the GNU General Public License version 2 only, as
   16.10 + * published by the Free Software Foundation.  Oracle designates this
   16.11 + * particular file as subject to the "Classpath" exception as provided
   16.12 + * by Oracle in the LICENSE file that accompanied this code.
   16.13 + *
   16.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   16.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   16.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   16.17 + * version 2 for more details (a copy is included in the LICENSE file that
   16.18 + * accompanied this code).
   16.19 + *
   16.20 + * You should have received a copy of the GNU General Public License version
   16.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   16.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   16.23 + *
   16.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   16.25 + * or visit www.oracle.com if you need additional information or have any
   16.26 + * questions.
   16.27 + */
   16.28 +package jdk.nashorn.internal.runtime;
   16.29 +
   16.30 +import java.util.LinkedHashMap;
   16.31 +import java.util.Map;
   16.32 +
   16.33 +import jdk.nashorn.internal.runtime.options.Options;
   16.34 +
   16.35 +/**
   16.36 + * Simple wallclock timing framework
   16.37 + */
   16.38 +public final class Timing {
   16.39 +    private static final boolean ENABLED = Options.getBooleanProperty("nashorn.time");
   16.40 +    private static final Map<String, Long> TIMINGS;
   16.41 +    private static final long START_TIME;
   16.42 +
   16.43 +    static {
   16.44 +        if (ENABLED) {
   16.45 +            TIMINGS    = new LinkedHashMap<>();
   16.46 +            START_TIME = System.currentTimeMillis();
   16.47 +            Runtime.getRuntime().addShutdownHook(new Thread() {
   16.48 +                @Override
   16.49 +                public void run() {
   16.50 +                    final long t = System.currentTimeMillis();
   16.51 +                    long knownTime = 0L;
   16.52 +                    int  maxLength = 0;
   16.53 +
   16.54 +                    for (final Map.Entry<String, Long> entry : TIMINGS.entrySet()) {
   16.55 +                        maxLength = Math.max(maxLength, entry.getKey().length());
   16.56 +                    }
   16.57 +                    maxLength++;
   16.58 +
   16.59 +                    for (final Map.Entry<String, Long> entry : TIMINGS.entrySet()) {
   16.60 +                        final StringBuilder sb = new StringBuilder();
   16.61 +
   16.62 +                        sb.append(entry.getKey());
   16.63 +                        while (sb.length() < maxLength) {
   16.64 +                            sb.append(' ');
   16.65 +                        }
   16.66 +
   16.67 +                        final long duration = entry.getValue();
   16.68 +                        sb.append(duration);
   16.69 +                        sb.append(' ');
   16.70 +                        sb.append(" ms");
   16.71 +
   16.72 +                        knownTime += duration;
   16.73 +
   16.74 +                        System.err.println(sb.toString()); //Context err is gone by shutdown TODO
   16.75 +                    }
   16.76 +
   16.77 +                    final long total = t - START_TIME;
   16.78 +                    System.err.println("Total runtime: " + total + " ms (Non-runtime: " + knownTime + " ms [" + (int)(knownTime * 100.0 / total) + "%])");
   16.79 +                }
   16.80 +            });
   16.81 +        } else {
   16.82 +            TIMINGS = null;
   16.83 +            START_TIME = 0L;
   16.84 +        }
   16.85 +    }
   16.86 +
   16.87 +    /**
   16.88 +     * Check if timing is inabled
   16.89 +     * @return true if timing is enabled
   16.90 +     */
   16.91 +    public static boolean isEnabled() {
   16.92 +        return ENABLED;
   16.93 +    }
   16.94 +
   16.95 +    /**
   16.96 +     * When timing, this can be called to register a new module for timing
   16.97 +     * or add to its accumulated time
   16.98 +     *
   16.99 +     * @param module   module name
  16.100 +     * @param duration duration to add to accumulated time for module
  16.101 +     */
  16.102 +    public static void accumulateTime(final String module, final long duration) {
  16.103 +        if (Timing.isEnabled()) {
  16.104 +            Long accumulatedTime = TIMINGS.get(module);
  16.105 +            if (accumulatedTime == null) {
  16.106 +                accumulatedTime = 0L;
  16.107 +            }
  16.108 +            TIMINGS.put(module, accumulatedTime + duration);
  16.109 +        }
  16.110 +    }
  16.111 +
  16.112 +}
    17.1 --- a/test/script/trusted/JDK-8006529.js	Wed Feb 20 16:43:21 2013 +0100
    17.2 +++ b/test/script/trusted/JDK-8006529.js	Thu Feb 21 16:57:21 2013 +0100
    17.3 @@ -60,7 +60,7 @@
    17.4  var getFunctionsMethod = FunctionNode.class.getMethod("getFunctions");
    17.5  
    17.6  // These are method names of methods in FunctionNode class
    17.7 -var allAssertionList = ['isVarArg', 'needsParentScope', 'needsCallee', 'needsScope', 'needsSelfSymbol', 'isSplit', 'hasEval', 'hasWith', 'hasDeepWithOrEval', 'varsInScope', 'isStrictMode']
    17.8 +var allAssertionList = ['isVarArg', 'needsParentScope', 'needsCallee', 'needsScope', 'needsSelfSymbol', 'isSplit', 'hasEval', 'hasWith', 'hasDeepWithOrEval', 'allVarsInScope', 'isStrictMode']
    17.9  
   17.10  // corresponding Method objects of FunctionNode class
   17.11  var functionNodeMethods = {};
   17.12 @@ -189,18 +189,18 @@
   17.13  // and all variables in scope. Actually, we could make "with" less wasteful,
   17.14  // and only put those variables in scope that it actually references, similar
   17.15  // to what nested functions do with variables in their parents.
   17.16 -testFirstFn("(function f() { var o; with(o) {} })", 'needsParentScope', 'needsCallee', 'needsScope', 'hasWith', 'hasDeepWithOrEval', 'varsInScope')
   17.17 +testFirstFn("(function f() { var o; with(o) {} })", 'needsParentScope', 'needsCallee', 'needsScope', 'hasWith', 'hasDeepWithOrEval', 'allVarsInScope')
   17.18  
   17.19  // Using "eval" is as bad as using "with" with the added requirement of
   17.20  // being vararg, 'cause we don't know if eval will be using "arguments".
   17.21 -testFirstFn("(function f() { eval() })", 'needsParentScope', 'needsCallee', 'needsScope', 'hasEval', 'isVarArg', 'hasDeepWithOrEval', 'varsInScope')
   17.22 +testFirstFn("(function f() { eval() })", 'needsParentScope', 'needsCallee', 'needsScope', 'hasEval', 'isVarArg', 'hasDeepWithOrEval', 'allVarsInScope')
   17.23  
   17.24  // Nested function using "with" is pretty much the same as the parent
   17.25  // function needing with.
   17.26 -testFirstFn("(function f() { function g() { var o; with(o) {} } })", 'needsParentScope', 'needsCallee', 'needsScope', 'hasDeepWithOrEval', 'varsInScope')
   17.27 +testFirstFn("(function f() { function g() { var o; with(o) {} } })", 'needsParentScope', 'needsCallee', 'needsScope', 'hasDeepWithOrEval', 'allVarsInScope')
   17.28  // Nested function using "eval" is almost the same as parent function using
   17.29  // eval, but at least the parent doesn't have to be vararg.
   17.30 -testFirstFn("(function f() { function g() { eval() } })", 'needsParentScope', 'needsCallee', 'needsScope', 'hasDeepWithOrEval', 'varsInScope')
   17.31 +testFirstFn("(function f() { function g() { eval() } })", 'needsParentScope', 'needsCallee', 'needsScope', 'hasDeepWithOrEval', 'allVarsInScope')
   17.32  
   17.33  // Function with 250 named parameters is ordinary
   17.34  testFirstFn("function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97, p98, p99, p100, p101, p102, p103, p104, p105, p106, p107, p108, p109, p110, p111, p112, p113, p114, p115, p116, p117, p118, p119, p120, p121, p122, p123, p124, p125, p126, p127, p128, p129, p130, p131, p132, p133, p134, p135, p136, p137, p138, p139, p140, p141, p142, p143, p144, p145, p146, p147, p148, p149, p150, p151, p152, p153, p154, p155, p156, p157, p158, p159, p160, p161, p162, p163, p164, p165, p166, p167, p168, p169, p170, p171, p172, p173, p174, p175, p176, p177, p178, p179, p180, p181, p182, p183, p184, p185, p186, p187, p188, p189, p190, p191, p192, p193, p194, p195, p196, p197, p198, p199, p200, p201, p202, p203, p204, p205, p206, p207, p208, p209, p210, p211, p212, p213, p214, p215, p216, p217, p218, p219, p220, p221, p222, p223, p224, p225, p226, p227, p228, p229, p230, p231, p232, p233, p234, p235, p236, p237, p238, p239, p240, p241, p242, p243, p244, p245, p246, p247, p248, p249, p250) { p250 = p249 }")

mercurial