Merge

Wed, 17 Dec 2014 12:51:46 -0800

author
asaha
date
Wed, 17 Dec 2014 12:51:46 -0800
changeset 1175
26f5d69bd533
parent 1174
e907206f50f5
parent 1129
4d240320929f
child 1177
a24ec0deb4a8
child 1288
7b12e3b9f274

Merge

.hgtags file | annotate | diff | comparison | revisions
     1.1 --- a/.hgtags	Tue Dec 16 14:46:13 2014 -0800
     1.2 +++ b/.hgtags	Wed Dec 17 12:51:46 2014 -0800
     1.3 @@ -354,3 +354,4 @@
     1.4  e079f3f6d536510b1ab3589b1038d893d78302ac jdk8u40-b16
     1.5  88e22262fdb26e3154a1034c2413415e97b9a86a jdk8u40-b17
     1.6  653739706172ae94e999731a3a9f10f8ce11ffca jdk8u40-b18
     1.7 +6ec61d2494283fbaca6df227f1a5b45487dc1ca7 jdk8u40-b19
     2.1 --- a/THIRD_PARTY_README	Tue Dec 16 14:46:13 2014 -0800
     2.2 +++ b/THIRD_PARTY_README	Wed Dec 17 12:51:46 2014 -0800
     2.3 @@ -3385,7 +3385,7 @@
     2.4  included with JRE 8, JDK 8, and OpenJDK 8.
     2.5  
     2.6    Apache Commons Math 3.2
     2.7 -  Apache Derby 10.10.1.3        
     2.8 +  Apache Derby 10.11.1.2
     2.9    Apache Jakarta BCEL 5.1 
    2.10    Apache Jakarta Regexp 1.4 
    2.11    Apache Santuario XML Security for Java 1.5.4
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/samples/browser_dom.js	Wed Dec 17 12:51:46 2014 -0800
     3.3 @@ -0,0 +1,91 @@
     3.4 +#// Usage: jjs -fx browser.js
     3.5 +
     3.6 +/*
     3.7 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
     3.8 + *
     3.9 + * Redistribution and use in source and binary forms, with or without
    3.10 + * modification, are permitted provided that the following conditions
    3.11 + * are met:
    3.12 + *
    3.13 + *   - Redistributions of source code must retain the above copyright
    3.14 + *     notice, this list of conditions and the following disclaimer.
    3.15 + *
    3.16 + *   - Redistributions in binary form must reproduce the above copyright
    3.17 + *     notice, this list of conditions and the following disclaimer in the
    3.18 + *     documentation and/or other materials provided with the distribution.
    3.19 + *
    3.20 + *   - Neither the name of Oracle nor the names of its
    3.21 + *     contributors may be used to endorse or promote products derived
    3.22 + *     from this software without specific prior written permission.
    3.23 + *
    3.24 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
    3.25 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    3.26 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    3.27 + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    3.28 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    3.29 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    3.30 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    3.31 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    3.32 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    3.33 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    3.34 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    3.35 + */
    3.36 +
    3.37 +if (!$OPTIONS._fx) {
    3.38 +    print("Usage: jjs -fx browser.js");
    3.39 +    exit(1);
    3.40 +}
    3.41 +
    3.42 +// JavaFX classes used
    3.43 +var ChangeListener = Java.type("javafx.beans.value.ChangeListener");
    3.44 +var Scene     = Java.type("javafx.scene.Scene");
    3.45 +var WebView   = Java.type("javafx.scene.web.WebView");
    3.46 +var EventListener = Java.type("org.w3c.dom.events.EventListener");
    3.47 +
    3.48 +// JavaFX start method
    3.49 +function start(stage) {
    3.50 +    start.title = "Web View";
    3.51 +    var wv = new WebView();
    3.52 +    wv.engine.loadContent(<<EOF
    3.53 +<html>
    3.54 +<head>
    3.55 +<title>
    3.56 +This is the title
    3.57 +</title>
    3.58 +<script>
    3.59 +// click count for OK button
    3.60 +var okCount = 0;
    3.61 +</script>
    3.62 +</head>
    3.63 +<body>
    3.64 +Button from the input html<br>
    3.65 +<button type="button" onclick="okCount++">OK</button><br>
    3.66 +</body>
    3.67 +</html>
    3.68 +EOF, "text/html");
    3.69 +
    3.70 +    // attach onload handler
    3.71 +    wv.engine.loadWorker.stateProperty().addListener(
    3.72 +        new ChangeListener() {
    3.73 +            changed: function() {
    3.74 +               // DOM document element
    3.75 +               var document = wv.engine.document;
    3.76 +               // DOM manipulation
    3.77 +               var btn = document.createElement("button");
    3.78 +               var n = 0;
    3.79 +               // attach a button handler - nashorn function!
    3.80 +               btn.onclick = new EventListener(function() {
    3.81 +                   n++; print("You clicked " + n + " time(s)");
    3.82 +                   print("you clicked OK " + wv.engine.executeScript("okCount"));
    3.83 +               });
    3.84 +               // attach text to button
    3.85 +               var t = document.createTextNode("Click Me!"); 
    3.86 +               btn.appendChild(t);
    3.87 +               // attach button to the document
    3.88 +               document.body.appendChild(btn); 
    3.89 +           }
    3.90 +        }
    3.91 +    );
    3.92 +    stage.scene = new Scene(wv, 750, 500);
    3.93 +    stage.show();
    3.94 +}
     4.1 --- a/src/jdk/nashorn/internal/codegen/AssignSymbols.java	Tue Dec 16 14:46:13 2014 -0800
     4.2 +++ b/src/jdk/nashorn/internal/codegen/AssignSymbols.java	Wed Dec 17 12:51:46 2014 -0800
     4.3 @@ -910,7 +910,7 @@
     4.4      @Override
     4.5      public Node leaveSwitchNode(final SwitchNode switchNode) {
     4.6          // We only need a symbol for the tag if it's not an integer switch node
     4.7 -        if(!switchNode.isInteger()) {
     4.8 +        if(!switchNode.isUniqueInteger()) {
     4.9              switchNode.setTag(newObjectInternal(SWITCH_TAG_PREFIX));
    4.10          }
    4.11          return switchNode;
     5.1 --- a/src/jdk/nashorn/internal/codegen/AstSerializer.java	Tue Dec 16 14:46:13 2014 -0800
     5.2 +++ b/src/jdk/nashorn/internal/codegen/AstSerializer.java	Wed Dec 17 12:51:46 2014 -0800
     5.3 @@ -48,11 +48,13 @@
     5.4      private static final int COMPRESSION_LEVEL = Options.getIntProperty("nashorn.serialize.compression", 4);
     5.5      static byte[] serialize(final FunctionNode fn) {
     5.6          final ByteArrayOutputStream out = new ByteArrayOutputStream();
     5.7 -        try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out,
     5.8 -                new Deflater(COMPRESSION_LEVEL)))) {
     5.9 +        final Deflater deflater = new Deflater(COMPRESSION_LEVEL);
    5.10 +        try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out, deflater))) {
    5.11              oout.writeObject(removeInnerFunctionBodies(fn));
    5.12          } catch (final IOException e) {
    5.13              throw new AssertionError("Unexpected exception serializing function", e);
    5.14 +        } finally {
    5.15 +            deflater.end();
    5.16          }
    5.17          return out.toByteArray();
    5.18      }
     6.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Tue Dec 16 14:46:13 2014 -0800
     6.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Dec 17 12:51:46 2014 -0800
     6.3 @@ -465,10 +465,10 @@
     6.4              // If this is either __FILE__, __DIR__, or __LINE__ then load the property initially as Object as we'd convert
     6.5              // it anyway for replaceLocationPropertyPlaceholder.
     6.6              if(identNode.isCompileTimePropertyName()) {
     6.7 -                method.dynamicGet(Type.OBJECT, identNode.getSymbol().getName(), flags, identNode.isFunction());
     6.8 +                method.dynamicGet(Type.OBJECT, identNode.getSymbol().getName(), flags, identNode.isFunction(), false);
     6.9                  replaceCompileTimeProperty();
    6.10              } else {
    6.11 -                dynamicGet(identNode.getSymbol().getName(), flags, identNode.isFunction());
    6.12 +                dynamicGet(identNode.getSymbol().getName(), flags, identNode.isFunction(), false);
    6.13              }
    6.14          }
    6.15      }
    6.16 @@ -486,7 +486,7 @@
    6.17  
    6.18      private MethodEmitter storeFastScopeVar(final Symbol symbol, final int flags) {
    6.19          loadFastScopeProto(symbol, true);
    6.20 -        method.dynamicSet(symbol.getName(), flags | CALLSITE_FAST_SCOPE);
    6.21 +        method.dynamicSet(symbol.getName(), flags | CALLSITE_FAST_SCOPE, false);
    6.22          return method;
    6.23      }
    6.24  
    6.25 @@ -571,9 +571,11 @@
    6.26  
    6.27          // Operands' load type should not be narrower than the narrowest of the individual operand types, nor narrower
    6.28          // than the lower explicit bound, but it should also not be wider than
    6.29 -        final Type narrowestOperandType = Type.narrowest(Type.widest(lhs.getType(), rhs.getType()), explicitOperandBounds.widest);
    6.30 +        final Type lhsType = undefinedToNumber(lhs.getType());
    6.31 +        final Type rhsType = undefinedToNumber(rhs.getType());
    6.32 +        final Type narrowestOperandType = Type.narrowest(Type.widest(lhsType, rhsType), explicitOperandBounds.widest);
    6.33          final TypeBounds operandBounds = explicitOperandBounds.notNarrowerThan(narrowestOperandType);
    6.34 -        if (noToPrimitiveConversion(lhs.getType(), explicitOperandBounds.widest) || rhs.isLocal()) {
    6.35 +        if (noToPrimitiveConversion(lhsType, explicitOperandBounds.widest) || rhs.isLocal()) {
    6.36              // Can reorder. We might still need to separate conversion, but at least we can do it with reordering
    6.37              if (forceConversionSeparation) {
    6.38                  // Can reorder, but can't move conversion into the operand as the operation depends on operands
    6.39 @@ -594,10 +596,10 @@
    6.40              // Can't reorder. Load and convert separately.
    6.41              final TypeBounds safeConvertBounds = TypeBounds.UNBOUNDED.notNarrowerThan(narrowestOperandType);
    6.42              loadExpression(lhs, safeConvertBounds, baseAlreadyOnStack);
    6.43 -            final Type lhsType = method.peekType();
    6.44 +            final Type lhsLoadedType = method.peekType();
    6.45              loadExpression(rhs, safeConvertBounds, false);
    6.46              final Type convertedLhsType = operandBounds.within(method.peekType());
    6.47 -            if (convertedLhsType != lhsType) {
    6.48 +            if (convertedLhsType != lhsLoadedType) {
    6.49                  // Do it conditionally, so that if conversion is a no-op we don't introduce a SWAP, SWAP.
    6.50                  method.swap().convert(convertedLhsType).swap();
    6.51              }
    6.52 @@ -609,6 +611,10 @@
    6.53          return method;
    6.54      }
    6.55  
    6.56 +    private static final Type undefinedToNumber(final Type type) {
    6.57 +        return type == Type.UNDEFINED ? Type.NUMBER : type;
    6.58 +    }
    6.59 +
    6.60      private static final class TypeBounds {
    6.61          final Type narrowest;
    6.62          final Type widest;
    6.63 @@ -739,7 +745,7 @@
    6.64                      @Override
    6.65                      void consumeStack() {
    6.66                          final int flags = getCallSiteFlags();
    6.67 -                        dynamicGet(accessNode.getProperty(), flags, accessNode.isFunction());
    6.68 +                        dynamicGet(accessNode.getProperty(), flags, accessNode.isFunction(), accessNode.isIndex());
    6.69                      }
    6.70                  }.emit(baseAlreadyOnStack ? 1 : 0);
    6.71                  return false;
    6.72 @@ -1443,7 +1449,7 @@
    6.73                          // NOTE: not using a nested OptimisticOperation on this dynamicGet, as we expect to get back
    6.74                          // a callable object. Nobody in their right mind would optimistically type this call site.
    6.75                          assert !node.isOptimistic();
    6.76 -                        method.dynamicGet(node.getType(), node.getProperty(), flags, true);
    6.77 +                        method.dynamicGet(node.getType(), node.getProperty(), flags, true, node.isIndex());
    6.78                          method.swap();
    6.79                          argCount = loadArgs(args);
    6.80                      }
    6.81 @@ -2015,6 +2021,19 @@
    6.82          final Expression test = ifNode.getTest();
    6.83          final Block pass = ifNode.getPass();
    6.84          final Block fail = ifNode.getFail();
    6.85 +
    6.86 +        if (Expression.isAlwaysTrue(test)) {
    6.87 +            loadAndDiscard(test);
    6.88 +            pass.accept(this);
    6.89 +            return false;
    6.90 +        } else if (Expression.isAlwaysFalse(test)) {
    6.91 +            loadAndDiscard(test);
    6.92 +            if (fail != null) {
    6.93 +                fail.accept(this);
    6.94 +            }
    6.95 +            return false;
    6.96 +        }
    6.97 +
    6.98          final boolean hasFailConversion = LocalVariableConversion.hasLiveConversion(ifNode);
    6.99  
   6.100          final Label failLabel  = new Label("if_fail");
   6.101 @@ -2034,7 +2053,7 @@
   6.102              method.beforeJoinPoint(ifNode);
   6.103          }
   6.104  
   6.105 -        if(afterLabel != null) {
   6.106 +        if(afterLabel != null && afterLabel.isReachable()) {
   6.107              method.label(afterLabel);
   6.108          }
   6.109  
   6.110 @@ -2811,7 +2830,7 @@
   6.111          Label defaultLabel = defaultCase != null ? defaultCase.getEntry() : breakLabel;
   6.112          final boolean hasSkipConversion = LocalVariableConversion.hasLiveConversion(switchNode);
   6.113  
   6.114 -        if (switchNode.isInteger()) {
   6.115 +        if (switchNode.isUniqueInteger()) {
   6.116              // Tree for sorting values.
   6.117              final TreeMap<Integer, Label> tree = new TreeMap<>();
   6.118  
   6.119 @@ -3145,14 +3164,13 @@
   6.120              if (isFastScope(identSymbol)) {
   6.121                  storeFastScopeVar(identSymbol, flags);
   6.122              } else {
   6.123 -                method.dynamicSet(identNode.getName(), flags);
   6.124 +                method.dynamicSet(identNode.getName(), flags, false);
   6.125              }
   6.126          } else {
   6.127              final Type identType = identNode.getType();
   6.128              if(identType == Type.UNDEFINED) {
   6.129 -                // The symbol must not be slotted; the initializer is either itself undefined (explicit assignment of
   6.130 -                // undefined to undefined), or the left hand side is a dead variable.
   6.131 -                assert !identNode.getSymbol().isScope();
   6.132 +                // The initializer is either itself undefined (explicit assignment of undefined to undefined),
   6.133 +                // or the left hand side is a dead variable.
   6.134                  assert init.getType() == Type.UNDEFINED || identNode.getSymbol().slotCount() == 0;
   6.135                  loadAndDiscard(init);
   6.136                  return false;
   6.137 @@ -3264,7 +3282,7 @@
   6.138              emitContinueLabel(continueLabel, liveLocalsOnContinue);
   6.139          }
   6.140  
   6.141 -        if (loopNode.hasPerIterationScope() && lc.getParentBlock().needsScope()) {
   6.142 +        if (loopNode.hasPerIterationScope() && lc.getCurrentBlock().needsScope()) {
   6.143              // ES6 for loops with LET init need a new scope for each iteration. We just create a shallow copy here.
   6.144              method.loadCompilerConstant(SCOPE);
   6.145              method.invoke(virtualCallNoLookup(ScriptObject.class, "copy", ScriptObject.class));
   6.146 @@ -3575,9 +3593,9 @@
   6.147                      operandBounds = new TypeBounds(binaryNode.getType(), Type.OBJECT);
   6.148                  } else {
   6.149                      // Non-optimistic, non-FP +. Allow it to overflow.
   6.150 -                    operandBounds = new TypeBounds(Type.narrowest(binaryNode.getWidestOperandType(), resultBounds.widest),
   6.151 -                            Type.OBJECT);
   6.152 -                    forceConversionSeparation = binaryNode.getWidestOperationType().narrowerThan(resultBounds.widest);
   6.153 +                    final Type widestOperationType = binaryNode.getWidestOperationType();
   6.154 +                    operandBounds = new TypeBounds(Type.narrowest(binaryNode.getWidestOperandType(), resultBounds.widest), widestOperationType);
   6.155 +                    forceConversionSeparation = widestOperationType.narrowerThan(resultBounds.widest);
   6.156                  }
   6.157                  loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), operandBounds, false, forceConversionSeparation);
   6.158              }
   6.159 @@ -3692,8 +3710,7 @@
   6.160              final Expression lhs = assignNode.lhs();
   6.161              final Expression rhs = assignNode.rhs();
   6.162              final Type widestOperationType = assignNode.getWidestOperationType();
   6.163 -            final Type widest = assignNode.isTokenType(TokenType.ASSIGN_ADD) ? Type.OBJECT : widestOperationType;
   6.164 -            final TypeBounds bounds = new TypeBounds(assignNode.getType(), widest);
   6.165 +            final TypeBounds bounds = new TypeBounds(assignNode.getType(), widestOperationType);
   6.166              new OptimisticOperation(assignNode, bounds) {
   6.167                  @Override
   6.168                  void loadStack() {
   6.169 @@ -4251,7 +4268,7 @@
   6.170                          if (isFastScope(symbol)) {
   6.171                              storeFastScopeVar(symbol, flags);
   6.172                          } else {
   6.173 -                            method.dynamicSet(node.getName(), flags);
   6.174 +                            method.dynamicSet(node.getName(), flags, false);
   6.175                          }
   6.176                      } else {
   6.177                          final Type storeType = assignNode.getType();
   6.178 @@ -4268,7 +4285,7 @@
   6.179  
   6.180                  @Override
   6.181                  public boolean enterAccessNode(final AccessNode node) {
   6.182 -                    method.dynamicSet(node.getProperty(), getCallSiteFlags());
   6.183 +                    method.dynamicSet(node.getProperty(), getCallSiteFlags(), node.isIndex());
   6.184                      return false;
   6.185                  }
   6.186  
   6.187 @@ -4606,11 +4623,11 @@
   6.188           * @param isMethod whether we're preferrably retrieving a function
   6.189           * @return the current method emitter
   6.190           */
   6.191 -        MethodEmitter dynamicGet(final String name, final int flags, final boolean isMethod) {
   6.192 +        MethodEmitter dynamicGet(final String name, final int flags, final boolean isMethod, final boolean isIndex) {
   6.193              if(isOptimistic) {
   6.194 -                return method.dynamicGet(getOptimisticCoercedType(), name, getOptimisticFlags(flags), isMethod);
   6.195 -            }
   6.196 -            return method.dynamicGet(resultBounds.within(expression.getType()), name, nonOptimisticFlags(flags), isMethod);
   6.197 +                return method.dynamicGet(getOptimisticCoercedType(), name, getOptimisticFlags(flags), isMethod, isIndex);
   6.198 +            }
   6.199 +            return method.dynamicGet(resultBounds.within(expression.getType()), name, nonOptimisticFlags(flags), isMethod, isIndex);
   6.200          }
   6.201  
   6.202          MethodEmitter dynamicGetIndex(final int flags, final boolean isMethod) {
     7.1 --- a/src/jdk/nashorn/internal/codegen/FoldConstants.java	Tue Dec 16 14:46:13 2014 -0800
     7.2 +++ b/src/jdk/nashorn/internal/codegen/FoldConstants.java	Wed Dec 17 12:51:46 2014 -0800
     7.3 @@ -26,12 +26,16 @@
     7.4  package jdk.nashorn.internal.codegen;
     7.5  
     7.6  import java.util.ArrayList;
     7.7 +import java.util.HashSet;
     7.8  import java.util.List;
     7.9 +import java.util.Set;
    7.10  import jdk.nashorn.internal.codegen.types.Type;
    7.11  import jdk.nashorn.internal.ir.BinaryNode;
    7.12  import jdk.nashorn.internal.ir.Block;
    7.13  import jdk.nashorn.internal.ir.BlockStatement;
    7.14 +import jdk.nashorn.internal.ir.CaseNode;
    7.15  import jdk.nashorn.internal.ir.EmptyNode;
    7.16 +import jdk.nashorn.internal.ir.Expression;
    7.17  import jdk.nashorn.internal.ir.FunctionNode;
    7.18  import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
    7.19  import jdk.nashorn.internal.ir.IfNode;
    7.20 @@ -40,6 +44,7 @@
    7.21  import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
    7.22  import jdk.nashorn.internal.ir.Node;
    7.23  import jdk.nashorn.internal.ir.Statement;
    7.24 +import jdk.nashorn.internal.ir.SwitchNode;
    7.25  import jdk.nashorn.internal.ir.TernaryNode;
    7.26  import jdk.nashorn.internal.ir.UnaryNode;
    7.27  import jdk.nashorn.internal.ir.VarNode;
    7.28 @@ -126,11 +131,37 @@
    7.29      public Node leaveTernaryNode(final TernaryNode ternaryNode) {
    7.30          final Node test = ternaryNode.getTest();
    7.31          if (test instanceof LiteralNode.PrimitiveLiteralNode) {
    7.32 -            return ((LiteralNode.PrimitiveLiteralNode<?>)test).isTrue() ? ternaryNode.getTrueExpression() : ternaryNode.getFalseExpression();
    7.33 +            return (((LiteralNode.PrimitiveLiteralNode<?>)test).isTrue() ? ternaryNode.getTrueExpression() : ternaryNode.getFalseExpression()).getExpression();
    7.34          }
    7.35          return ternaryNode;
    7.36      }
    7.37  
    7.38 +    @Override
    7.39 +    public Node leaveSwitchNode(final SwitchNode switchNode) {
    7.40 +        return switchNode.setUniqueInteger(lc, isUniqueIntegerSwitchNode(switchNode));
    7.41 +    }
    7.42 +
    7.43 +    private static boolean isUniqueIntegerSwitchNode(final SwitchNode switchNode) {
    7.44 +        final Set<Integer> alreadySeen = new HashSet<>();
    7.45 +        for (final CaseNode caseNode : switchNode.getCases()) {
    7.46 +            final Expression test = caseNode.getTest();
    7.47 +            if (test != null && !isUniqueIntegerLiteral(test, alreadySeen)) {
    7.48 +                return false;
    7.49 +            }
    7.50 +        }
    7.51 +        return true;
    7.52 +    }
    7.53 +
    7.54 +    private static boolean isUniqueIntegerLiteral(final Expression expr, final Set<Integer> alreadySeen) {
    7.55 +        if (expr instanceof LiteralNode) {
    7.56 +            final Object value = ((LiteralNode<?>)expr).getValue();
    7.57 +            if (value instanceof Integer) {
    7.58 +                return alreadySeen.add((Integer)value);
    7.59 +            }
    7.60 +        }
    7.61 +        return false;
    7.62 +    }
    7.63 +
    7.64      /**
    7.65       * Helper class to evaluate constant expressions at compile time This is
    7.66       * also a simplifier used by BinaryNode visits, UnaryNode visits and
     8.1 --- a/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Tue Dec 16 14:46:13 2014 -0800
     8.2 +++ b/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java	Wed Dec 17 12:51:46 2014 -0800
     8.3 @@ -28,6 +28,7 @@
     8.4  import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
     8.5  import static jdk.nashorn.internal.ir.Expression.isAlwaysFalse;
     8.6  import static jdk.nashorn.internal.ir.Expression.isAlwaysTrue;
     8.7 +
     8.8  import java.util.ArrayDeque;
     8.9  import java.util.ArrayList;
    8.10  import java.util.Collections;
    8.11 @@ -82,7 +83,6 @@
    8.12  import jdk.nashorn.internal.ir.VarNode;
    8.13  import jdk.nashorn.internal.ir.WhileNode;
    8.14  import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    8.15 -import jdk.nashorn.internal.parser.Token;
    8.16  import jdk.nashorn.internal.parser.TokenType;
    8.17  
    8.18  /**
    8.19 @@ -93,6 +93,13 @@
    8.20   * variable to its widest used type after the join point. That would eliminate some widenings of undefined variables to
    8.21   * object, most notably those used only in loops. We need a full liveness analysis for that. Currently, we can establish
    8.22   * per-type liveness, which eliminates most of unwanted dead widenings.
    8.23 + * NOTE: the way this class is implemented, it actually processes the AST in two passes. The first pass is top-down and
    8.24 + * implemented in {@code enterXxx} methods. This pass does not mutate the AST (except for one occurrence, noted below),
    8.25 + * as being able to find relevant labels for control flow joins is sensitive to their reference identity, and mutated
    8.26 + * label-carrying nodes will create copies of their labels. A second bottom-up pass applying the changes is implemented
    8.27 + * in the separate visitor sitting in {@link #leaveFunctionNode(FunctionNode)}. This visitor will also instantiate new
    8.28 + * instances of the calculator to be run on nested functions (when not lazy compiling).
    8.29 + *
    8.30   */
    8.31  final class LocalVariableTypesCalculator extends NodeVisitor<LexicalContext>{
    8.32  
    8.33 @@ -398,48 +405,53 @@
    8.34  
    8.35      @Override
    8.36      public boolean enterBinaryNode(final BinaryNode binaryNode) {
    8.37 +        // NOTE: regardless of operator's lexical associativity, lhs is always evaluated first.
    8.38          final Expression lhs = binaryNode.lhs();
    8.39 -        final Expression rhs = binaryNode.rhs();
    8.40          final boolean isAssignment = binaryNode.isAssignment();
    8.41 -
    8.42 -        final TokenType tokenType = Token.descType(binaryNode.getToken());
    8.43 -        if(tokenType.isLeftAssociative()) {
    8.44 -            assert !isAssignment;
    8.45 -            final boolean isLogical = binaryNode.isLogical();
    8.46 -            final Label joinLabel = isLogical ? new Label("") : null;
    8.47 -            lhs.accept(this);
    8.48 -            if(isLogical) {
    8.49 -                jumpToLabel((JoinPredecessor)lhs, joinLabel);
    8.50 -            }
    8.51 -            rhs.accept(this);
    8.52 -            if(isLogical) {
    8.53 -                jumpToLabel((JoinPredecessor)rhs, joinLabel);
    8.54 -            }
    8.55 -            joinOnLabel(joinLabel);
    8.56 -        } else {
    8.57 -            rhs.accept(this);
    8.58 -            if(isAssignment) {
    8.59 -                if(lhs instanceof BaseNode) {
    8.60 -                    ((BaseNode)lhs).getBase().accept(this);
    8.61 -                    if(lhs instanceof IndexNode) {
    8.62 -                        ((IndexNode)lhs).getIndex().accept(this);
    8.63 -                    } else {
    8.64 -                        assert lhs instanceof AccessNode;
    8.65 -                    }
    8.66 +        LvarType lhsTypeOnLoad = null;
    8.67 +        if(isAssignment) {
    8.68 +            if(lhs instanceof BaseNode) {
    8.69 +                ((BaseNode)lhs).getBase().accept(this);
    8.70 +                if(lhs instanceof IndexNode) {
    8.71 +                    ((IndexNode)lhs).getIndex().accept(this);
    8.72                  } else {
    8.73 -                    assert lhs instanceof IdentNode;
    8.74 -                    if(binaryNode.isSelfModifying()) {
    8.75 -                        ((IdentNode)lhs).accept(this);
    8.76 -                    }
    8.77 +                    assert lhs instanceof AccessNode;
    8.78                  }
    8.79              } else {
    8.80 -                lhs.accept(this);
    8.81 +                assert lhs instanceof IdentNode;
    8.82 +                if(binaryNode.isSelfModifying()) {
    8.83 +                    final IdentNode ident = ((IdentNode)lhs);
    8.84 +                    ident.accept(this);
    8.85 +                    // Self-assignment can cause a change in the type of the variable. For purposes of evaluating
    8.86 +                    // the type of the operation, we must use its type as it was when it was loaded. If we didn't
    8.87 +                    // do this, some awkward expressions would end up being calculated incorrectly, e.g.
    8.88 +                    // "var x; x += x = 0;". In this case we have undefined+int so the result type is double (NaN).
    8.89 +                    // However, if we used the type of "x" on LHS after we evaluated RHS, we'd see int+int, so the
    8.90 +                    // result type would be either optimistic int or pessimistic long, which would be wrong.
    8.91 +                    lhsTypeOnLoad = getLocalVariableTypeIfBytecode(ident.getSymbol());
    8.92 +                }
    8.93              }
    8.94 +        } else {
    8.95 +            lhs.accept(this);
    8.96          }
    8.97  
    8.98 +        final boolean isLogical = binaryNode.isLogical();
    8.99 +        assert !(isAssignment && isLogical); // there are no logical assignment operators in JS
   8.100 +        final Label joinLabel = isLogical ? new Label("") : null;
   8.101 +        if(isLogical) {
   8.102 +            jumpToLabel((JoinPredecessor)lhs, joinLabel);
   8.103 +        }
   8.104 +
   8.105 +        final Expression rhs = binaryNode.rhs();
   8.106 +        rhs.accept(this);
   8.107 +        if(isLogical) {
   8.108 +            jumpToLabel((JoinPredecessor)rhs, joinLabel);
   8.109 +        }
   8.110 +        joinOnLabel(joinLabel);
   8.111 +
   8.112          if(isAssignment && lhs instanceof IdentNode) {
   8.113              if(binaryNode.isSelfModifying()) {
   8.114 -                onSelfAssignment((IdentNode)lhs, binaryNode);
   8.115 +                onSelfAssignment((IdentNode)lhs, binaryNode, lhsTypeOnLoad);
   8.116              } else {
   8.117                  onAssignment((IdentNode)lhs, rhs);
   8.118              }
   8.119 @@ -704,7 +716,7 @@
   8.120  
   8.121          // Control flow is different for all-integer cases where we dispatch by switch table, and for all other cases
   8.122          // where we do sequential comparison. Note that CaseNode objects act as join points.
   8.123 -        final boolean isInteger = switchNode.isInteger();
   8.124 +        final boolean isInteger = switchNode.isUniqueInteger();
   8.125          final Label breakLabel = switchNode.getBreakLabel();
   8.126          final boolean hasDefault = switchNode.getDefaultCase() != null;
   8.127  
   8.128 @@ -919,7 +931,8 @@
   8.129  
   8.130          if(unaryNode.isSelfModifying()) {
   8.131              if(expr instanceof IdentNode) {
   8.132 -                onSelfAssignment((IdentNode)expr, unaryNode);
   8.133 +                final IdentNode ident = (IdentNode)expr;
   8.134 +                onSelfAssignment(ident, unaryNode, getLocalVariableTypeIfBytecode(ident.getSymbol()));
   8.135              }
   8.136          }
   8.137          return false;
   8.138 @@ -973,12 +986,41 @@
   8.139          return types;
   8.140      }
   8.141  
   8.142 +    /**
   8.143 +     * Returns the current type of the local variable represented by the symbol. This is the most strict of all
   8.144 +     * {@code getLocalVariableType*} methods, as it will throw an assertion if the type is null. Therefore, it is only
   8.145 +     * safe to be invoked on symbols known to be bytecode locals, and only after they have been initialized.
   8.146 +     * Regardless, it is recommended to use this method in majority of cases, as because of its strictness it is the
   8.147 +     * best suited for catching missing type calculation bugs early.
   8.148 +     * @param symbol a symbol representing a bytecode local variable.
   8.149 +     * @return the current type of the local variable represented by the symbol
   8.150 +     */
   8.151      private LvarType getLocalVariableType(final Symbol symbol) {
   8.152          final LvarType type = getLocalVariableTypeOrNull(symbol);
   8.153          assert type != null;
   8.154          return type;
   8.155      }
   8.156  
   8.157 +    /**
   8.158 +     * Gets the type for a local variable if it is a bytecode local, otherwise null. Can be used in circumstances where
   8.159 +     * the type is irrelevant if the symbol is not a bytecode local. Note that for bytecode locals, it delegates to
   8.160 +     * {@link #getLocalVariableType(Symbol)}, so it will still assert that the type for such variable is already
   8.161 +     * defined (that is, not null).
   8.162 +     * @param symbol the symbol representing the variable.
   8.163 +     * @return the current variable type, if it is a bytecode local, otherwise null.
   8.164 +     */
   8.165 +    private LvarType getLocalVariableTypeIfBytecode(final Symbol symbol) {
   8.166 +        return symbol.isBytecodeLocal() ? getLocalVariableType(symbol) : null;
   8.167 +    }
   8.168 +
   8.169 +    /**
   8.170 +     * Gets the type for a variable represented by a symbol, or null if the type is not know. This is the least strict
   8.171 +     * of all local variable type getters, and as such its use is discouraged except in initialization scenarios (where
   8.172 +     * a just-defined symbol might still be null).
   8.173 +     * @param symbol the symbol
   8.174 +     * @return the current type for the symbol, or null if the type is not known either because the symbol has not been
   8.175 +     * initialized, or because the symbol does not represent a bytecode local variable.
   8.176 +     */
   8.177      private LvarType getLocalVariableTypeOrNull(final Symbol symbol) {
   8.178          return localVariableTypes.get(symbol);
   8.179      }
   8.180 @@ -1358,13 +1400,13 @@
   8.181          jumpToCatchBlock(identNode);
   8.182      }
   8.183  
   8.184 -    private void onSelfAssignment(final IdentNode identNode, final Expression assignment) {
   8.185 +    private void onSelfAssignment(final IdentNode identNode, final Expression assignment, final LvarType typeOnLoad) {
   8.186          final Symbol symbol = identNode.getSymbol();
   8.187          assert symbol != null : identNode.getName();
   8.188          if(!symbol.isBytecodeLocal()) {
   8.189              return;
   8.190          }
   8.191 -        final LvarType type = toLvarType(getType(assignment));
   8.192 +        final LvarType type = toLvarType(getType(assignment, symbol, typeOnLoad.type));
   8.193          // Self-assignment never produce either a boolean or undefined
   8.194          assert type != null && type != LvarType.UNDEFINED && type != LvarType.BOOLEAN;
   8.195          setType(symbol, type);
   8.196 @@ -1445,13 +1487,24 @@
   8.197          symbolIsUsed(symbol, getLocalVariableType(symbol));
   8.198      }
   8.199  
   8.200 +    /**
   8.201 +     * Gets the type of the expression, dependent on the current types of the local variables.
   8.202 +     *
   8.203 +     * @param expr the expression
   8.204 +     * @return the current type of the expression dependent on the current types of the local variables.
   8.205 +     */
   8.206      private Type getType(final Expression expr) {
   8.207          return expr.getType(getSymbolToType());
   8.208      }
   8.209  
   8.210 +    /**
   8.211 +     * Returns a function object from symbols to their types, used by the expressions to evaluate their type.
   8.212 +     * {@link BinaryNode} specifically uses identity of the function to cache type calculations. This method makes
   8.213 +     * sure to return the same function object while the local variable types don't change, and create a new function
   8.214 +     * object if the local variable types have been changed.
   8.215 +     * @return a function object representing a mapping from symbols to their types.
   8.216 +     */
   8.217      private Function<Symbol, Type> getSymbolToType() {
   8.218 -        // BinaryNode uses identity of the function to cache type calculations. Therefore, we must use different
   8.219 -        // function instances for different localVariableTypes instances.
   8.220          if(symbolToType.isStale()) {
   8.221              symbolToType = new SymbolToType();
   8.222          }
   8.223 @@ -1469,4 +1522,41 @@
   8.224              return boundTypes != localVariableTypes;
   8.225          }
   8.226      }
   8.227 +
   8.228 +    /**
   8.229 +     * Gets the type of the expression, dependent on the current types of the local variables and a single overridden
   8.230 +     * symbol type. Used by type calculation on compound operators to ensure the type of the LHS at the time it was
   8.231 +     * loaded (which can potentially be different after RHS evaluation, e.g. "var x; x += x = 0;") is preserved for
   8.232 +     * the calculation.
   8.233 +     *
   8.234 +     * @param expr the expression
   8.235 +     * @param overriddenSymbol the overridden symbol
   8.236 +     * @param overriddenType the overridden type
   8.237 +     * @return the current type of the expression dependent on the current types of the local variables and the single
   8.238 +     * potentially overridden type.
   8.239 +     */
   8.240 +    private Type getType(final Expression expr, final Symbol overriddenSymbol, final Type overriddenType) {
   8.241 +        return expr.getType(getSymbolToType(overriddenSymbol, overriddenType));
   8.242 +    }
   8.243 +
   8.244 +    private Function<Symbol, Type> getSymbolToType(final Symbol overriddenSymbol, final Type overriddenType) {
   8.245 +        return getLocalVariableType(overriddenSymbol).type == overriddenType ? getSymbolToType() :
   8.246 +            new SymbolToTypeOverride(overriddenSymbol, overriddenType);
   8.247 +    }
   8.248 +
   8.249 +    private class SymbolToTypeOverride implements Function<Symbol, Type> {
   8.250 +        private final Function<Symbol, Type> originalSymbolToType = getSymbolToType();
   8.251 +        private final Symbol overriddenSymbol;
   8.252 +        private final Type overriddenType;
   8.253 +
   8.254 +        SymbolToTypeOverride(final Symbol overriddenSymbol, final Type overriddenType) {
   8.255 +            this.overriddenSymbol = overriddenSymbol;
   8.256 +            this.overriddenType = overriddenType;
   8.257 +        }
   8.258 +
   8.259 +        @Override
   8.260 +        public Type apply(final Symbol symbol) {
   8.261 +            return symbol == overriddenSymbol ? overriddenType : originalSymbolToType.apply(symbol);
   8.262 +        }
   8.263 +    }
   8.264  }
     9.1 --- a/src/jdk/nashorn/internal/codegen/Lower.java	Tue Dec 16 14:46:13 2014 -0800
     9.2 +++ b/src/jdk/nashorn/internal/codegen/Lower.java	Wed Dec 17 12:51:46 2014 -0800
     9.3 @@ -34,6 +34,8 @@
     9.4  import java.util.Collections;
     9.5  import java.util.List;
     9.6  import java.util.ListIterator;
     9.7 +import java.util.regex.Pattern;
     9.8 +import jdk.nashorn.internal.ir.AccessNode;
     9.9  import jdk.nashorn.internal.ir.BaseNode;
    9.10  import jdk.nashorn.internal.ir.BinaryNode;
    9.11  import jdk.nashorn.internal.ir.Block;
    9.12 @@ -52,6 +54,7 @@
    9.13  import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
    9.14  import jdk.nashorn.internal.ir.IdentNode;
    9.15  import jdk.nashorn.internal.ir.IfNode;
    9.16 +import jdk.nashorn.internal.ir.IndexNode;
    9.17  import jdk.nashorn.internal.ir.JumpStatement;
    9.18  import jdk.nashorn.internal.ir.LabelNode;
    9.19  import jdk.nashorn.internal.ir.LexicalContext;
    9.20 @@ -93,6 +96,10 @@
    9.21  
    9.22      private final DebugLogger log;
    9.23  
    9.24 +    // Conservative pattern to test if element names consist of characters valid for identifiers.
    9.25 +    // This matches any non-zero length alphanumeric string including _ and $ and not starting with a digit.
    9.26 +    private static Pattern SAFE_PROPERTY_NAME = Pattern.compile("[a-zA-Z_$][\\w$]*");
    9.27 +
    9.28      /**
    9.29       * Constructor.
    9.30       */
    9.31 @@ -140,7 +147,7 @@
    9.32              }
    9.33          });
    9.34  
    9.35 -        this.log       = initLogger(compiler.getContext());
    9.36 +        this.log = initLogger(compiler.getContext());
    9.37      }
    9.38  
    9.39      @Override
    9.40 @@ -181,6 +188,28 @@
    9.41      }
    9.42  
    9.43      @Override
    9.44 +    public Node leaveIndexNode(final IndexNode indexNode) {
    9.45 +        final String name = getConstantPropertyName(indexNode.getIndex());
    9.46 +        if (name != null) {
    9.47 +            // If index node is a constant property name convert index node to access node.
    9.48 +            assert Token.descType(indexNode.getToken()) == TokenType.LBRACKET;
    9.49 +            return new AccessNode(indexNode.getToken(), indexNode.getFinish(), indexNode.getBase(), name);
    9.50 +        }
    9.51 +        return super.leaveIndexNode(indexNode);
    9.52 +    }
    9.53 +
    9.54 +    // If expression is a primitive literal that is not an array index and does return its string value. Else return null.
    9.55 +    private static String getConstantPropertyName(final Expression expression) {
    9.56 +        if (expression instanceof LiteralNode.PrimitiveLiteralNode) {
    9.57 +            final Object value = ((LiteralNode) expression).getValue();
    9.58 +            if (value instanceof String && SAFE_PROPERTY_NAME.matcher((String) value).matches()) {
    9.59 +                return (String) value;
    9.60 +            }
    9.61 +        }
    9.62 +        return null;
    9.63 +    }
    9.64 +
    9.65 +    @Override
    9.66      public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) {
    9.67          final Expression expr = expressionStatement.getExpression();
    9.68          ExpressionStatement node = expressionStatement;
    9.69 @@ -275,7 +304,7 @@
    9.70  
    9.71      @Override
    9.72      public Node leaveSwitchNode(final SwitchNode switchNode) {
    9.73 -        if(!switchNode.isInteger()) {
    9.74 +        if(!switchNode.isUniqueInteger()) {
    9.75              // Wrap it in a block so its internally created tag is restricted in scope
    9.76              addStatementEnclosedInBlock(switchNode);
    9.77          } else {
    10.1 --- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Tue Dec 16 14:46:13 2014 -0800
    10.2 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java	Wed Dec 17 12:51:46 2014 -0800
    10.3 @@ -2214,10 +2214,10 @@
    10.4       * @param name      name of property
    10.5       * @param flags     call site flags
    10.6       * @param isMethod  should it prefer retrieving methods
    10.7 -     *
    10.8 +     * @param isIndex   is this an index operation?
    10.9       * @return the method emitter
   10.10       */
   10.11 -    MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod) {
   10.12 +    MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod, final boolean isIndex) {
   10.13          debug("dynamic_get", name, valueType, getProgramPoint(flags));
   10.14  
   10.15          Type type = valueType;
   10.16 @@ -2226,8 +2226,8 @@
   10.17          }
   10.18  
   10.19          popType(Type.SCOPE);
   10.20 -        method.visitInvokeDynamicInsn((isMethod ? "dyn:getMethod|getProp|getElem:" : "dyn:getProp|getElem|getMethod:") +
   10.21 -                NameCodec.encode(name), Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags);
   10.22 +        method.visitInvokeDynamicInsn(dynGetOperation(isMethod, isIndex) + ':' + NameCodec.encode(name),
   10.23 +                Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags);
   10.24  
   10.25          pushType(type);
   10.26          convert(valueType); //most probably a nop
   10.27 @@ -2240,8 +2240,9 @@
   10.28       *
   10.29       * @param name  name of property
   10.30       * @param flags call site flags
   10.31 +     * @param isIndex is this an index operation?
   10.32       */
   10.33 -     void dynamicSet(final String name, final int flags) {
   10.34 +    void dynamicSet(final String name, final int flags, final boolean isIndex) {
   10.35           assert !isOptimistic(flags);
   10.36           debug("dynamic_set", name, peekType());
   10.37  
   10.38 @@ -2253,7 +2254,8 @@
   10.39          popType(type);
   10.40          popType(Type.SCOPE);
   10.41  
   10.42 -        method.visitInvokeDynamicInsn("dyn:setProp|setElem:" + NameCodec.encode(name), methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags);
   10.43 +        method.visitInvokeDynamicInsn(dynSetOperation(isIndex) + ':' + NameCodec.encode(name),
   10.44 +                methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags);
   10.45      }
   10.46  
   10.47       /**
   10.48 @@ -2286,7 +2288,7 @@
   10.49  
   10.50          final String signature = Type.getMethodDescriptor(resultType, Type.OBJECT /*e.g STRING->OBJECT*/, index);
   10.51  
   10.52 -        method.visitInvokeDynamicInsn(isMethod ? "dyn:getMethod|getElem|getProp" : "dyn:getElem|getProp|getMethod", signature, LINKERBOOTSTRAP, flags);
   10.53 +        method.visitInvokeDynamicInsn(dynGetOperation(isMethod, true), signature, LINKERBOOTSTRAP, flags);
   10.54          pushType(resultType);
   10.55  
   10.56          if (result.isBoolean()) {
   10.57 @@ -2500,6 +2502,18 @@
   10.58          }
   10.59      }
   10.60  
   10.61 +    private static String dynGetOperation(final boolean isMethod, final boolean isIndex) {
   10.62 +        if (isMethod) {
   10.63 +            return isIndex ? "dyn:getMethod|getElem|getProp" : "dyn:getMethod|getProp|getElem";
   10.64 +        } else {
   10.65 +            return isIndex ? "dyn:getElem|getProp|getMethod" : "dyn:getProp|getElem|getMethod";
   10.66 +        }
   10.67 +    }
   10.68 +
   10.69 +    private static String dynSetOperation(final boolean isIndex) {
   10.70 +        return isIndex ? "dyn:setElem|setProp" : "dyn:setProp|setElem";
   10.71 +    }
   10.72 +
   10.73      private Type emitLocalVariableConversion(final LocalVariableConversion conversion, final boolean onlySymbolLiveValue) {
   10.74          final Type from = conversion.getFrom();
   10.75          final Type to = conversion.getTo();
    11.1 --- a/src/jdk/nashorn/internal/codegen/SharedScopeCall.java	Tue Dec 16 14:46:13 2014 -0800
    11.2 +++ b/src/jdk/nashorn/internal/codegen/SharedScopeCall.java	Wed Dec 17 12:51:46 2014 -0800
    11.3 @@ -156,7 +156,7 @@
    11.4          assert !isCall || valueType.isObject(); // Callables are always objects
    11.5          // If flags are optimistic, but we're doing a call, remove optimistic flags from the getter, as they obviously
    11.6          // only apply to the call.
    11.7 -        method.dynamicGet(valueType, symbol.getName(), isCall ? CodeGenerator.nonOptimisticFlags(flags) : flags, isCall);
    11.8 +        method.dynamicGet(valueType, symbol.getName(), isCall ? CodeGenerator.nonOptimisticFlags(flags) : flags, isCall, false);
    11.9  
   11.10          // If this is a get we're done, otherwise call the value as function.
   11.11          if (isCall) {
    12.1 --- a/src/jdk/nashorn/internal/ir/AccessNode.java	Tue Dec 16 14:46:13 2014 -0800
    12.2 +++ b/src/jdk/nashorn/internal/ir/AccessNode.java	Wed Dec 17 12:51:46 2014 -0800
    12.3 @@ -28,6 +28,8 @@
    12.4  import jdk.nashorn.internal.codegen.types.Type;
    12.5  import jdk.nashorn.internal.ir.annotations.Immutable;
    12.6  import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    12.7 +import jdk.nashorn.internal.parser.Token;
    12.8 +import jdk.nashorn.internal.parser.TokenType;
    12.9  
   12.10  /**
   12.11   * IR representation of a property access (period operator.)
   12.12 @@ -101,6 +103,14 @@
   12.13          return property;
   12.14      }
   12.15  
   12.16 +    /**
   12.17 +     * Return true if this node represents an index operation normally represented as {@link IndexNode}.
   12.18 +     * @return true if an index access.
   12.19 +     */
   12.20 +    public boolean isIndex() {
   12.21 +        return Token.descType(getToken()) == TokenType.LBRACKET;
   12.22 +    }
   12.23 +
   12.24      private AccessNode setBase(final Expression base) {
   12.25          if (this.base == base) {
   12.26              return this;
    13.1 --- a/src/jdk/nashorn/internal/ir/BinaryNode.java	Tue Dec 16 14:46:13 2014 -0800
    13.2 +++ b/src/jdk/nashorn/internal/ir/BinaryNode.java	Wed Dec 17 12:51:46 2014 -0800
    13.3 @@ -341,10 +341,7 @@
    13.4      @Override
    13.5      public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
    13.6          if (visitor.enterBinaryNode(this)) {
    13.7 -            if(tokenType().isLeftAssociative()) {
    13.8 -                return visitor.leaveBinaryNode(setLHS((Expression)lhs.accept(visitor)).setRHS((Expression)rhs.accept(visitor)));
    13.9 -            }
   13.10 -            return visitor.leaveBinaryNode(setRHS((Expression)rhs.accept(visitor)).setLHS((Expression)lhs.accept(visitor)));
   13.11 +            return visitor.leaveBinaryNode(setLHS((Expression)lhs.accept(visitor)).setRHS((Expression)rhs.accept(visitor)));
   13.12          }
   13.13  
   13.14          return this;
    14.1 --- a/src/jdk/nashorn/internal/ir/RuntimeNode.java	Tue Dec 16 14:46:13 2014 -0800
    14.2 +++ b/src/jdk/nashorn/internal/ir/RuntimeNode.java	Wed Dec 17 12:51:46 2014 -0800
    14.3 @@ -27,7 +27,6 @@
    14.4  
    14.5  import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
    14.6  
    14.7 -import java.util.ArrayList;
    14.8  import java.util.Arrays;
    14.9  import java.util.Collections;
   14.10  import java.util.List;
   14.11 @@ -468,11 +467,7 @@
   14.12      @Override
   14.13      public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
   14.14          if (visitor.enterRuntimeNode(this)) {
   14.15 -            final List<Expression> newArgs = new ArrayList<>();
   14.16 -            for (final Node arg : args) {
   14.17 -                newArgs.add((Expression)arg.accept(visitor));
   14.18 -            }
   14.19 -            return visitor.leaveRuntimeNode(setArgs(newArgs));
   14.20 +            return visitor.leaveRuntimeNode(setArgs(Node.accept(visitor, args)));
   14.21          }
   14.22  
   14.23          return this;
    15.1 --- a/src/jdk/nashorn/internal/ir/SwitchNode.java	Tue Dec 16 14:46:13 2014 -0800
    15.2 +++ b/src/jdk/nashorn/internal/ir/SwitchNode.java	Wed Dec 17 12:51:46 2014 -0800
    15.3 @@ -48,6 +48,10 @@
    15.4      /** Switch default index. */
    15.5      private final int defaultCaseIndex;
    15.6  
    15.7 +    /** True if all cases are 32-bit signed integer constants, without repetitions. It's a prerequisite for
    15.8 +     * using a tableswitch/lookupswitch when generating code. */
    15.9 +    private final boolean uniqueInteger;
   15.10 +
   15.11      /** Tag symbol. */
   15.12      private Symbol tag;
   15.13  
   15.14 @@ -66,15 +70,17 @@
   15.15          this.expression       = expression;
   15.16          this.cases            = cases;
   15.17          this.defaultCaseIndex = defaultCase == null ? -1 : cases.indexOf(defaultCase);
   15.18 +        this.uniqueInteger    = false;
   15.19      }
   15.20  
   15.21      private SwitchNode(final SwitchNode switchNode, final Expression expression, final List<CaseNode> cases,
   15.22 -            final int defaultCaseIndex, final LocalVariableConversion conversion) {
   15.23 +            final int defaultCaseIndex, final LocalVariableConversion conversion, final boolean uniqueInteger) {
   15.24          super(switchNode, conversion);
   15.25          this.expression       = expression;
   15.26          this.cases            = cases;
   15.27          this.defaultCaseIndex = defaultCaseIndex;
   15.28 -        this.tag              = switchNode.getTag(); //TODO are symbols inhereted as references?
   15.29 +        this.tag              = switchNode.getTag(); //TODO are symbols inherited as references?
   15.30 +        this.uniqueInteger    = uniqueInteger;
   15.31      }
   15.32  
   15.33      @Override
   15.34 @@ -83,7 +89,7 @@
   15.35          for (final CaseNode caseNode : cases) {
   15.36              newCases.add(new CaseNode(caseNode, caseNode.getTest(), caseNode.getBody(), caseNode.getLocalVariableConversion()));
   15.37          }
   15.38 -        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex, conversion));
   15.39 +        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex, conversion, uniqueInteger));
   15.40      }
   15.41  
   15.42      @Override
   15.43 @@ -151,7 +157,7 @@
   15.44          if (this.cases == cases) {
   15.45              return this;
   15.46          }
   15.47 -        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion));
   15.48 +        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
   15.49      }
   15.50  
   15.51      /**
   15.52 @@ -183,7 +189,7 @@
   15.53          if (this.expression == expression) {
   15.54              return this;
   15.55          }
   15.56 -        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion));
   15.57 +        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
   15.58      }
   15.59  
   15.60      /**
   15.61 @@ -205,25 +211,30 @@
   15.62      }
   15.63  
   15.64      /**
   15.65 -     * Returns true if all cases of this switch statement are 32-bit signed integer constants.
   15.66 -     * @return true if all cases of this switch statement are 32-bit signed integer constants.
   15.67 +     * Returns true if all cases of this switch statement are 32-bit signed integer constants, without repetitions.
   15.68 +     * @return true if all cases of this switch statement are 32-bit signed integer constants, without repetitions.
   15.69       */
   15.70 -    public boolean isInteger() {
   15.71 -        for (final CaseNode caseNode : cases) {
   15.72 -            final Expression test = caseNode.getTest();
   15.73 -            if (test != null && !isIntegerLiteral(test)) {
   15.74 -                return false;
   15.75 -            }
   15.76 +    public boolean isUniqueInteger() {
   15.77 +        return uniqueInteger;
   15.78 +    }
   15.79 +
   15.80 +    /**
   15.81 +     * Sets whether all cases of this switch statement are 32-bit signed integer constants, without repetitions.
   15.82 +     * @param lc lexical context
   15.83 +     * @param uniqueInteger if true, all cases of this switch statement have been determined to be 32-bit signed
   15.84 +     * integer constants, without repetitions.
   15.85 +     * @return this switch node, if the value didn't change, or a new switch node with the changed value
   15.86 +     */
   15.87 +    public SwitchNode setUniqueInteger(final LexicalContext lc, final boolean uniqueInteger) {
   15.88 +        if(this.uniqueInteger == uniqueInteger) {
   15.89 +            return this;
   15.90          }
   15.91 -        return true;
   15.92 +        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
   15.93      }
   15.94  
   15.95      @Override
   15.96      JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
   15.97 -        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion));
   15.98 +        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
   15.99      }
  15.100  
  15.101 -    private static boolean isIntegerLiteral(final Expression expr) {
  15.102 -        return expr instanceof LiteralNode && ((LiteralNode<?>)expr).getValue() instanceof Integer;
  15.103 -    }
  15.104  }
    16.1 --- a/src/jdk/nashorn/internal/parser/Parser.java	Tue Dec 16 14:46:13 2014 -0800
    16.2 +++ b/src/jdk/nashorn/internal/parser/Parser.java	Wed Dec 17 12:51:46 2014 -0800
    16.3 @@ -2644,7 +2644,7 @@
    16.4          // name is null, generate anonymous name
    16.5          boolean isAnonymous = false;
    16.6          if (name == null) {
    16.7 -            final String tmpName = getDefaultValidFunctionName(functionLine);
    16.8 +            final String tmpName = getDefaultValidFunctionName(functionLine, isStatement);
    16.9              name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
   16.10              isAnonymous = true;
   16.11          }
   16.12 @@ -2653,7 +2653,15 @@
   16.13          final List<IdentNode> parameters = formalParameterList();
   16.14          expect(RPAREN);
   16.15  
   16.16 -        FunctionNode functionNode = functionBody(functionToken, name, parameters, FunctionNode.Kind.NORMAL, functionLine);
   16.17 +        FunctionNode functionNode;
   16.18 +        // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}"
   16.19 +        // If we didn't hide the current default name, then the innermost anonymous function would receive "x3".
   16.20 +        hideDefaultName();
   16.21 +        try {
   16.22 +            functionNode = functionBody(functionToken, name, parameters, FunctionNode.Kind.NORMAL, functionLine);
   16.23 +        } finally {
   16.24 +            defaultNames.pop();
   16.25 +        }
   16.26  
   16.27          if (isStatement) {
   16.28              if (topLevel || useBlockScope()) {
   16.29 @@ -2722,9 +2730,17 @@
   16.30          return functionNode;
   16.31      }
   16.32  
   16.33 -    private String getDefaultValidFunctionName(final int functionLine) {
   16.34 +    private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) {
   16.35          final String defaultFunctionName = getDefaultFunctionName();
   16.36 -        return isValidIdentifier(defaultFunctionName) ? defaultFunctionName : ANON_FUNCTION_PREFIX.symbolName() + functionLine;
   16.37 +        if (isValidIdentifier(defaultFunctionName)) {
   16.38 +            if (isStatement) {
   16.39 +                // The name will be used as the LHS of a symbol assignment. We add the anonymous function
   16.40 +                // prefix to ensure that it can't clash with another variable.
   16.41 +                return ANON_FUNCTION_PREFIX.symbolName() + defaultFunctionName;
   16.42 +            }
   16.43 +            return defaultFunctionName;
   16.44 +        }
   16.45 +        return ANON_FUNCTION_PREFIX.symbolName() + functionLine;
   16.46      }
   16.47  
   16.48      private static boolean isValidIdentifier(final String name) {
   16.49 @@ -2758,6 +2774,10 @@
   16.50  
   16.51      private void markDefaultNameUsed() {
   16.52          defaultNames.pop();
   16.53 +        hideDefaultName();
   16.54 +    }
   16.55 +
   16.56 +    private void hideDefaultName() {
   16.57          // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
   16.58          // from. Can't be null
   16.59          defaultNames.push("");
    17.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Tue Dec 16 14:46:13 2014 -0800
    17.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Wed Dec 17 12:51:46 2014 -0800
    17.3 @@ -2001,12 +2001,11 @@
    17.4  
    17.5          if (find == null) {
    17.6              switch (operator) {
    17.7 +            case "getElem": // getElem only gets here if element name is constant, so treat it like a property access
    17.8              case "getProp":
    17.9                  return noSuchProperty(desc, request);
   17.10              case "getMethod":
   17.11                  return noSuchMethod(desc, request);
   17.12 -            case "getElem":
   17.13 -                return createEmptyGetter(desc, explicitInstanceOfCheck, name);
   17.14              default:
   17.15                  throw new AssertionError(operator); // never invoked with any other operation
   17.16              }
   17.17 @@ -2333,8 +2332,9 @@
   17.18          }
   17.19  
   17.20          final ScriptFunction func = (ScriptFunction)value;
   17.21 -        final Object         thiz = scopeCall && func.isStrict() ? ScriptRuntime.UNDEFINED : this;
   17.22 +        final Object         thiz = scopeCall && func.isStrict() ? UNDEFINED : this;
   17.23          // TODO: It'd be awesome if we could bind "name" without binding "this".
   17.24 +        // Since we're binding this we must use an identity guard here.
   17.25          return new GuardedInvocation(
   17.26                  MH.dropArguments(
   17.27                          MH.constant(
   17.28 @@ -2342,9 +2342,9 @@
   17.29                                  func.makeBoundFunction(thiz, new Object[] { name })),
   17.30                          0,
   17.31                          Object.class),
   17.32 -                NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck),
   17.33 -                (SwitchPoint)null,
   17.34 -                explicitInstanceOfCheck ? null : ClassCastException.class);
   17.35 +                NashornGuards.combineGuards(
   17.36 +                        NashornGuards.getIdentityGuard(this),
   17.37 +                        NashornGuards.getMapGuard(getMap(), true)));
   17.38      }
   17.39  
   17.40      /**
   17.41 @@ -3710,7 +3710,9 @@
   17.42          final ScriptObject clone = (ScriptObject) super.clone();
   17.43          if (objectSpill != null) {
   17.44              clone.objectSpill = objectSpill.clone();
   17.45 -            clone.primitiveSpill = primitiveSpill.clone();
   17.46 +            if (primitiveSpill != null) {
   17.47 +                clone.primitiveSpill = primitiveSpill.clone();
   17.48 +            }
   17.49          }
   17.50          clone.arrayData = arrayData.copy();
   17.51          return clone;
    18.1 --- a/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java	Tue Dec 16 14:46:13 2014 -0800
    18.2 +++ b/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java	Wed Dec 17 12:51:46 2014 -0800
    18.3 @@ -29,6 +29,7 @@
    18.4  import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETSLOT;
    18.5  import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETMEMBER;
    18.6  import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETSLOT;
    18.7 +import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_CALL;
    18.8  import java.lang.invoke.MethodHandle;
    18.9  import java.lang.invoke.MethodHandles;
   18.10  import jdk.internal.dynalink.CallSiteDescriptor;
   18.11 @@ -123,6 +124,8 @@
   18.12              case "setProp":
   18.13              case "setElem":
   18.14                  return c > 2 ? findSetMethod(desc) : findSetIndexMethod();
   18.15 +            case "call":
   18.16 +                return findCallMethod(desc);
   18.17              default:
   18.18                  return null;
   18.19          }
   18.20 @@ -148,6 +151,11 @@
   18.21          return new GuardedInvocation(JSOBJECTLINKER_PUT, IS_JSOBJECT_GUARD);
   18.22      }
   18.23  
   18.24 +    private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc) {
   18.25 +        final MethodHandle call = MH.insertArguments(JSOBJECT_CALL, 1, "call");
   18.26 +        return new GuardedInvocation(MH.asCollector(call, Object[].class, desc.getMethodType().parameterCount() - 1), IS_JSOBJECT_GUARD);
   18.27 +    }
   18.28 +
   18.29      @SuppressWarnings("unused")
   18.30      private static boolean isJSObject(final Object self) {
   18.31          return jsObjectClass.isInstance(self);
   18.32 @@ -207,6 +215,7 @@
   18.33          static final MethodHandle JSOBJECT_GETSLOT       = findJSObjectMH_V("getSlot", Object.class, int.class).asType(MH.type(Object.class, Object.class, int.class));
   18.34          static final MethodHandle JSOBJECT_SETMEMBER     = findJSObjectMH_V("setMember", Void.TYPE, String.class, Object.class).asType(MH.type(Void.TYPE, Object.class, String.class, Object.class));
   18.35          static final MethodHandle JSOBJECT_SETSLOT       = findJSObjectMH_V("setSlot", Void.TYPE, int.class, Object.class).asType(MH.type(Void.TYPE, Object.class, int.class, Object.class));
   18.36 +        static final MethodHandle JSOBJECT_CALL          = findJSObjectMH_V("call", Object.class, String.class, Object[].class).asType(MH.type(Object.class, Object.class, String.class, Object[].class));
   18.37  
   18.38          private static MethodHandle findJSObjectMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
   18.39              checkJSObjectClass();
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/test/script/basic/JDK-8066221.js	Wed Dec 17 12:51:46 2014 -0800
    19.3 @@ -0,0 +1,31 @@
    19.4 +/*
    19.5 + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
    19.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    19.7 + * 
    19.8 + * This code is free software; you can redistribute it and/or modify it
    19.9 + * under the terms of the GNU General Public License version 2 only, as
   19.10 + * published by the Free Software Foundation.
   19.11 + * 
   19.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   19.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   19.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   19.15 + * version 2 for more details (a copy is included in the LICENSE file that
   19.16 + * accompanied this code).
   19.17 + * 
   19.18 + * You should have received a copy of the GNU General Public License version
   19.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   19.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   19.21 + * 
   19.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   19.23 + * or visit www.oracle.com if you need additional information or have any
   19.24 + * questions.
   19.25 + */
   19.26 +
   19.27 +/**
   19.28 + * JDK-8066221: anonymous function statement name clashes with another symbol
   19.29 + * (compile-only test)
   19.30 + *
   19.31 + * @test
   19.32 + */
   19.33 +
   19.34 +x3 = function x1(x3) { function (){} };
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/test/script/basic/JDK-8066224.js	Wed Dec 17 12:51:46 2014 -0800
    20.3 @@ -0,0 +1,38 @@
    20.4 +/*
    20.5 + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
    20.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    20.7 + * 
    20.8 + * This code is free software; you can redistribute it and/or modify it
    20.9 + * under the terms of the GNU General Public License version 2 only, as
   20.10 + * published by the Free Software Foundation.
   20.11 + * 
   20.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   20.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   20.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   20.15 + * version 2 for more details (a copy is included in the LICENSE file that
   20.16 + * accompanied this code).
   20.17 + * 
   20.18 + * You should have received a copy of the GNU General Public License version
   20.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   20.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20.21 + * 
   20.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   20.23 + * or visit www.oracle.com if you need additional information or have any
   20.24 + * questions.
   20.25 + */
   20.26 +
   20.27 +/**
   20.28 + * JDK-8066224: fixes for folding a constant-test ternary operator
   20.29 + *
   20.30 + * @test
   20.31 + * @run
   20.32 + */
   20.33 +
   20.34 +print((function(){ 
   20.35 +    if(false ? 0 : '') {
   20.36 +        throw false;
   20.37 +    } else if (x = this) {
   20.38 +        var x = x; 
   20.39 +    }
   20.40 +    return x === this;
   20.41 +})())
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/test/script/basic/JDK-8066224.js.EXPECTED	Wed Dec 17 12:51:46 2014 -0800
    21.3 @@ -0,0 +1,1 @@
    21.4 +true
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/test/script/basic/JDK-8066225.js	Wed Dec 17 12:51:46 2014 -0800
    22.3 @@ -0,0 +1,36 @@
    22.4 +/*
    22.5 + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
    22.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    22.7 + * 
    22.8 + * This code is free software; you can redistribute it and/or modify it
    22.9 + * under the terms of the GNU General Public License version 2 only, as
   22.10 + * published by the Free Software Foundation.
   22.11 + * 
   22.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   22.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   22.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   22.15 + * version 2 for more details (a copy is included in the LICENSE file that
   22.16 + * accompanied this code).
   22.17 + * 
   22.18 + * You should have received a copy of the GNU General Public License version
   22.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   22.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   22.21 + * 
   22.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22.23 + * or visit www.oracle.com if you need additional information or have any
   22.24 + * questions.
   22.25 + */
   22.26 +
   22.27 +/**
   22.28 + * JDK-8066225: NPE in MethodEmitter with duplicate integer switch cases
   22.29 + *
   22.30 + * @test
   22.31 + * @run
   22.32 + */
   22.33 +
   22.34 +(function (x){
   22.35 +    switch(x) { 
   22.36 +       case 44: for (var x in {}) {x}; print("1"); 
   22.37 +       case 44: print("2");
   22.38 +    }
   22.39 +})(44);
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/test/script/basic/JDK-8066225.js.EXPECTED	Wed Dec 17 12:51:46 2014 -0800
    23.3 @@ -0,0 +1,2 @@
    23.4 +1
    23.5 +2
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/test/script/basic/JDK-8066227.js	Wed Dec 17 12:51:46 2014 -0800
    24.3 @@ -0,0 +1,40 @@
    24.4 +/*
    24.5 + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
    24.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    24.7 + * 
    24.8 + * This code is free software; you can redistribute it and/or modify it
    24.9 + * under the terms of the GNU General Public License version 2 only, as
   24.10 + * published by the Free Software Foundation.
   24.11 + * 
   24.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   24.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   24.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   24.15 + * version 2 for more details (a copy is included in the LICENSE file that
   24.16 + * accompanied this code).
   24.17 + * 
   24.18 + * You should have received a copy of the GNU General Public License version
   24.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   24.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   24.21 + * 
   24.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   24.23 + * or visit www.oracle.com if you need additional information or have any
   24.24 + * questions.
   24.25 + */
   24.26 +
   24.27 +/**
   24.28 + * JDK-8066227: CodeGenerator load unitialized slot
   24.29 + *
   24.30 + * @test
   24.31 + * @run
   24.32 + */
   24.33 +
   24.34 +print((function () { var x; (x += x = 0); return x; })());
   24.35 +print((function () { var x; (x -= x = 0); return x; })());
   24.36 +print((function () { var x; (x *= x = 0); return x; })());
   24.37 +print((function () { var x; (x /= x = 0); return x; })());
   24.38 +print((function () { var x; (x %= x = 0); return x; })());
   24.39 +print((function () { var x; (x <<= x = 0); return x; })());
   24.40 +print((function () { var x; (x >>= x = 0); return x; })());
   24.41 +print((function () { var x; (x >>>= x = 0); return x; })());
   24.42 +print((function () { var x; (x |= x = 0); return x; })());
   24.43 +print((function () { var x; (x &= x = 0); return x; })());
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/test/script/basic/JDK-8066227.js.EXPECTED	Wed Dec 17 12:51:46 2014 -0800
    25.3 @@ -0,0 +1,10 @@
    25.4 +NaN
    25.5 +NaN
    25.6 +NaN
    25.7 +NaN
    25.8 +NaN
    25.9 +0
   25.10 +0
   25.11 +0
   25.12 +0
   25.13 +0
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/test/script/basic/JDK-8066230.js	Wed Dec 17 12:51:46 2014 -0800
    26.3 @@ -0,0 +1,34 @@
    26.4 +/*
    26.5 + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
    26.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    26.7 + * 
    26.8 + * This code is free software; you can redistribute it and/or modify it
    26.9 + * under the terms of the GNU General Public License version 2 only, as
   26.10 + * published by the Free Software Foundation.
   26.11 + * 
   26.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   26.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   26.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   26.15 + * version 2 for more details (a copy is included in the LICENSE file that
   26.16 + * accompanied this code).
   26.17 + * 
   26.18 + * You should have received a copy of the GNU General Public License version
   26.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   26.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   26.21 + * 
   26.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   26.23 + * or visit www.oracle.com if you need additional information or have any
   26.24 + * questions.
   26.25 + */
   26.26 +
   26.27 +/**
   26.28 + * JDK-8066230: Undefined object type assertion when computing TypeBounds
   26.29 + *
   26.30 + * @test
   26.31 + * @run
   26.32 + */
   26.33 +
   26.34 +(function() { void null + 0; })();
   26.35 +(function() { var x; x += void x; })();
   26.36 +(function() { var a = true + x, x; })();
   26.37 +print("SUCCESS");
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/test/script/basic/JDK-8066230.js.EXPECTED	Wed Dec 17 12:51:46 2014 -0800
    27.3 @@ -0,0 +1,1 @@
    27.4 +SUCCESS
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/test/script/basic/JDK-8066236.js	Wed Dec 17 12:51:46 2014 -0800
    28.3 @@ -0,0 +1,46 @@
    28.4 +/*
    28.5 + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
    28.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    28.7 + * 
    28.8 + * This code is free software; you can redistribute it and/or modify it
    28.9 + * under the terms of the GNU General Public License version 2 only, as
   28.10 + * published by the Free Software Foundation.
   28.11 + * 
   28.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   28.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   28.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   28.15 + * version 2 for more details (a copy is included in the LICENSE file that
   28.16 + * accompanied this code).
   28.17 + * 
   28.18 + * You should have received a copy of the GNU General Public License version
   28.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   28.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   28.21 + * 
   28.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   28.23 + * or visit www.oracle.com if you need additional information or have any
   28.24 + * questions.
   28.25 + */
   28.26 +
   28.27 +/**
   28.28 + * JDK-8066236: RuntimeNode forces copy creation on visitation
   28.29 + *
   28.30 + * @test
   28.31 + * @run
   28.32 + */
   28.33 +
   28.34 +// Note: we're using Function("code") instead of (function(){ code }) so that
   28.35 +// we don't trigger parser API validation in JDK-8008448 tests. The test code
   28.36 +// encapsulated in functions below can't be correctly handled by the parser API
   28.37 +// currently, as it contains parser-generated REFERENCE_ERROR runtime nodes.
   28.38 +try {
   28.39 +    Function("L: {this = x;break L}")();
   28.40 +} catch (e) {
   28.41 +   print("threw ReferenceError: " + (e instanceof ReferenceError));
   28.42 +}
   28.43 +try {
   28.44 +    Function("L:with(this--)break L;")();
   28.45 +} catch (e) {
   28.46 +   print("threw ReferenceError: " + (e instanceof ReferenceError));
   28.47 +}
   28.48 +Function("L:with(Object in Object)break L;")();
   28.49 +print("SUCCESS");
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/test/script/basic/JDK-8066236.js.EXPECTED	Wed Dec 17 12:51:46 2014 -0800
    29.3 @@ -0,0 +1,3 @@
    29.4 +threw ReferenceError: true
    29.5 +threw ReferenceError: true
    29.6 +SUCCESS
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/test/script/basic/JDK-8066669.js	Wed Dec 17 12:51:46 2014 -0800
    30.3 @@ -0,0 +1,58 @@
    30.4 +/*
    30.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
    30.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    30.7 + * 
    30.8 + * This code is free software; you can redistribute it and/or modify it
    30.9 + * under the terms of the GNU General Public License version 2 only, as
   30.10 + * published by the Free Software Foundation.
   30.11 + * 
   30.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   30.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   30.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   30.15 + * version 2 for more details (a copy is included in the LICENSE file that
   30.16 + * accompanied this code).
   30.17 + * 
   30.18 + * You should have received a copy of the GNU General Public License version
   30.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   30.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   30.21 + * 
   30.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   30.23 + * or visit www.oracle.com if you need additional information or have any
   30.24 + * questions.
   30.25 + */
   30.26 +
   30.27 +/**
   30.28 + * JDK-8066669: dust.js performance regression caused by primitive field conversion
   30.29 + *
   30.30 + * @test
   30.31 + * @run
   30.32 + */
   30.33 +
   30.34 +// Make sure index access on Java objects is working as expected.
   30.35 +var map = new java.util.HashMap();
   30.36 +
   30.37 +map["foo"] = "bar";
   30.38 +map[1] = 2;
   30.39 +map[false] = true;
   30.40 +map[null] = 0;
   30.41 +
   30.42 +print(map);
   30.43 +
   30.44 +var keys =  map.keySet().iterator();
   30.45 +
   30.46 +while(keys.hasNext()) {
   30.47 +    var key = keys.next();
   30.48 +    print(typeof key, key);
   30.49 +}
   30.50 +
   30.51 +print(typeof map["foo"], map["foo"]);
   30.52 +print(typeof map[1], map[1]);
   30.53 +print(typeof map[false], map[false]);
   30.54 +print(typeof map[null], map[null]);
   30.55 +
   30.56 +print(map.foo);
   30.57 +print(map.false);
   30.58 +print(map.null);
   30.59 +
   30.60 +map.foo = "baz";
   30.61 +print(map);
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/test/script/basic/JDK-8066669.js.EXPECTED	Wed Dec 17 12:51:46 2014 -0800
    31.3 @@ -0,0 +1,13 @@
    31.4 +{null=0, 1=2, false=true, foo=bar}
    31.5 +object null
    31.6 +number 1
    31.7 +boolean false
    31.8 +string foo
    31.9 +string bar
   31.10 +number 2
   31.11 +boolean true
   31.12 +number 0
   31.13 +bar
   31.14 +null
   31.15 +null
   31.16 +{null=0, 1=2, false=true, foo=baz}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/test/script/basic/JDK-8066932.js	Wed Dec 17 12:51:46 2014 -0800
    32.3 @@ -0,0 +1,48 @@
    32.4 +/*
    32.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
    32.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    32.7 + * 
    32.8 + * This code is free software; you can redistribute it and/or modify it
    32.9 + * under the terms of the GNU General Public License version 2 only, as
   32.10 + * published by the Free Software Foundation.
   32.11 + * 
   32.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   32.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   32.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   32.15 + * version 2 for more details (a copy is included in the LICENSE file that
   32.16 + * accompanied this code).
   32.17 + * 
   32.18 + * You should have received a copy of the GNU General Public License version
   32.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   32.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   32.21 + * 
   32.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   32.23 + * or visit www.oracle.com if you need additional information or have any
   32.24 + * questions.
   32.25 + */
   32.26 +
   32.27 +/**
   32.28 + * JDK-8066932: __noSuchMethod__ binds to this-object without proper guard
   32.29 + *
   32.30 + * @test
   32.31 + * @run
   32.32 + */
   32.33 +
   32.34 +function C(id) {
   32.35 +    this.id = id;
   32.36 +}
   32.37 +
   32.38 +C.prototype.__noSuchMethod__ = function(name, args) {
   32.39 +    return this.id;
   32.40 +};
   32.41 +
   32.42 +function test(id) {
   32.43 +    var c = new C(id);
   32.44 +    return c.nonExistingMethod();
   32.45 +}
   32.46 +
   32.47 +for (var i = 0; i < 30; i++) {
   32.48 +    if (test(i) !== i) {
   32.49 +        throw new Error("Wrong result from noSuchMethod in iteration " + i);
   32.50 +    }
   32.51 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/test/script/basic/JDK-8067136.js	Wed Dec 17 12:51:46 2014 -0800
    33.3 @@ -0,0 +1,69 @@
    33.4 +/*
    33.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    33.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    33.7 + *
    33.8 + * This code is free software; you can redistribute it and/or modify it
    33.9 + * under the terms of the GNU General Public License version 2 only, as
   33.10 + * published by the Free Software Foundation.
   33.11 + *
   33.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   33.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   33.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   33.15 + * version 2 for more details (a copy is included in the LICENSE file that
   33.16 + * accompanied this code).
   33.17 + *
   33.18 + * You should have received a copy of the GNU General Public License version
   33.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   33.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   33.21 + *
   33.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   33.23 + * or visit www.oracle.com if you need additional information or have any
   33.24 + * questions.
   33.25 + */
   33.26 +
   33.27 +/**
   33.28 + * JDK-8067136: BrowserJSObjectLinker does not handle call on JSObjects
   33.29 + *
   33.30 + * @test
   33.31 + * @option -scripting
   33.32 + * @run
   33.33 + */
   33.34 +
   33.35 +// call on netscape.javascript.JSObject
   33.36 +
   33.37 +function main() {
   33.38 +    var JSObject;
   33.39 +    try {
   33.40 +        JSObject = Java.type("netscape.javascript.JSObject");
   33.41 +    } catch (e) {
   33.42 +        if (e instanceof java.lang.ClassNotFoundException) {
   33.43 +            // pass vacuously by emitting the .EXPECTED file content
   33.44 +            var str = readFully(__DIR__ + "JDK-8067136.js.EXPECTED");
   33.45 +            print(str.substring(0, str.length - 1));
   33.46 +            return;
   33.47 +        } else{
   33.48 +            fail("unexpected exception for JSObject", e);
   33.49 +        }
   33.50 +    }
   33.51 +    test(JSObject);
   33.52 +}
   33.53 +
   33.54 +function test(JSObject) {
   33.55 +    var obj = new (Java.extend(JSObject))() {
   33.56 +        getMember: function(name) {
   33.57 +            if (name == "func") {
   33.58 +                return new (Java.extend(JSObject)) {
   33.59 +                    call: function(n) {
   33.60 +                        print("func called");
   33.61 +                    }
   33.62 +                }
   33.63 +            }
   33.64 +            return name.toUpperCase();
   33.65 +        },
   33.66 +
   33.67 +    };
   33.68 +
   33.69 +    obj.func();
   33.70 +}
   33.71 +
   33.72 +main();
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/test/script/basic/JDK-8067136.js.EXPECTED	Wed Dec 17 12:51:46 2014 -0800
    34.3 @@ -0,0 +1,1 @@
    34.4 +func called
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/test/script/basic/es6/for-let-object-fields.js	Wed Dec 17 12:51:46 2014 -0800
    35.3 @@ -0,0 +1,81 @@
    35.4 +/*
    35.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
    35.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    35.7 + * 
    35.8 + * This code is free software; you can redistribute it and/or modify it
    35.9 + * under the terms of the GNU General Public License version 2 only, as
   35.10 + * published by the Free Software Foundation.
   35.11 + * 
   35.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   35.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   35.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   35.15 + * version 2 for more details (a copy is included in the LICENSE file that
   35.16 + * accompanied this code).
   35.17 + * 
   35.18 + * You should have received a copy of the GNU General Public License version
   35.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   35.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   35.21 + * 
   35.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   35.23 + * or visit www.oracle.com if you need additional information or have any
   35.24 + * questions.
   35.25 + */
   35.26 +
   35.27 +/**
   35.28 + * JDK-8067219: NPE in ScriptObject.clone() when running with object fields
   35.29 + *
   35.30 + * @test
   35.31 + * @run
   35.32 + * @fork
   35.33 + * @option -Dnashorn.fields.objects=true
   35.34 + * @option --language=es6
   35.35 + */
   35.36 +
   35.37 +"use strict";
   35.38 +
   35.39 +for (let i = 0; i < 10; i++) {
   35.40 +    print(i);
   35.41 +}
   35.42 +
   35.43 +try {
   35.44 +    print(i);
   35.45 +} catch (e) {
   35.46 +    print(e);
   35.47 +}
   35.48 +
   35.49 +let a = [];
   35.50 +
   35.51 +for (let i = 0; i < 10; i++) {
   35.52 +    a.push(function() { print(i); });
   35.53 +}
   35.54 +
   35.55 +a.forEach(function(f) { f(); });
   35.56 +
   35.57 +a = [];
   35.58 +
   35.59 +for (let i = 0; i < 10; i++) {
   35.60 +    if (i == 5) {
   35.61 +        i = "foo";
   35.62 +    }
   35.63 +    a.push(function() { print(i); });
   35.64 +}
   35.65 +
   35.66 +a.forEach(function(f) { f(); });
   35.67 +
   35.68 +try {
   35.69 +    print(i);
   35.70 +} catch (e) {
   35.71 +    print(e);
   35.72 +}
   35.73 +
   35.74 +a = [];
   35.75 +
   35.76 +for (let i = 0; i < 20; i++) {
   35.77 +    if (i % 2 == 1) {
   35.78 +        i += 2;
   35.79 +        continue;
   35.80 +    }
   35.81 +    a.push(function() { print(i); });
   35.82 +}
   35.83 +
   35.84 +a.forEach(function(f) { f(); });
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/test/script/basic/es6/for-let-object-fields.js.EXPECTED	Wed Dec 17 12:51:46 2014 -0800
    36.3 @@ -0,0 +1,33 @@
    36.4 +0
    36.5 +1
    36.6 +2
    36.7 +3
    36.8 +4
    36.9 +5
   36.10 +6
   36.11 +7
   36.12 +8
   36.13 +9
   36.14 +ReferenceError: "i" is not defined
   36.15 +0
   36.16 +1
   36.17 +2
   36.18 +3
   36.19 +4
   36.20 +5
   36.21 +6
   36.22 +7
   36.23 +8
   36.24 +9
   36.25 +0
   36.26 +1
   36.27 +2
   36.28 +3
   36.29 +4
   36.30 +foo
   36.31 +ReferenceError: "i" is not defined
   36.32 +0
   36.33 +4
   36.34 +8
   36.35 +12
   36.36 +16
    37.1 --- a/test/script/basic/es6/for-let.js	Tue Dec 16 14:46:13 2014 -0800
    37.2 +++ b/test/script/basic/es6/for-let.js	Wed Dec 17 12:51:46 2014 -0800
    37.3 @@ -26,7 +26,8 @@
    37.4   *
    37.5   * @test
    37.6   * @run
    37.7 - * @option --language=es6 */
    37.8 + * @option --language=es6
    37.9 + */
   37.10  
   37.11  "use strict";
   37.12  
    38.1 --- a/test/script/basic/list.js.EXPECTED	Tue Dec 16 14:46:13 2014 -0800
    38.2 +++ b/test/script/basic/list.js.EXPECTED	Wed Dec 17 12:51:46 2014 -0800
    38.3 @@ -10,7 +10,7 @@
    38.4  l[0]=foo
    38.5  l[1]=a
    38.6  l[0.9]=null
    38.7 -l['blah']=null
    38.8 +l['blah']=undefined
    38.9  l[size_name]()=2
   38.10  java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
   38.11  java.lang.IndexOutOfBoundsException: Index: Infinity, Size: 2

mercurial