8057825: Bug in apply specialization - if an apply specialization that is available doesn't fit, a new one wouldn't be installed, if the new code generated as a specialization didn't manage to do the apply specialization. Basically changing a conditional to an unconditional.

Wed, 05 Nov 2014 12:34:06 +0100

author
lagergren
date
Wed, 05 Nov 2014 12:34:06 +0100
changeset 1086
d0b26e6f602c
parent 1085
b00442519275
child 1087
a119a11d49d8

8057825: Bug in apply specialization - if an apply specialization that is available doesn't fit, a new one wouldn't be installed, if the new code generated as a specialization didn't manage to do the apply specialization. Basically changing a conditional to an unconditional.
Reviewed-by: attila, hannesw

src/jdk/nashorn/internal/codegen/ApplySpecialization.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/CodeGenerator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/types/Type.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeString.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java file | annotate | diff | comparison | revisions
test/script/basic/JDK-8057825.js file | annotate | diff | comparison | revisions
test/script/basic/JDK-8057825.js.EXPECTED file | annotate | diff | comparison | revisions
test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/test/models/ClassLoaderAware.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/internal/codegen/ApplySpecialization.java	Mon Nov 03 14:59:34 2014 +0100
     1.2 +++ b/src/jdk/nashorn/internal/codegen/ApplySpecialization.java	Wed Nov 05 12:34:06 2014 +0100
     1.3 @@ -29,6 +29,7 @@
     1.4  import static jdk.nashorn.internal.codegen.CompilerConstants.EXPLODED_ARGUMENT_PREFIX;
     1.5  
     1.6  import java.lang.invoke.MethodType;
     1.7 +import java.net.URL;
     1.8  import java.util.ArrayDeque;
     1.9  import java.util.ArrayList;
    1.10  import java.util.Deque;
    1.11 @@ -93,6 +94,8 @@
    1.12  
    1.13      private final Deque<List<IdentNode>> explodedArguments = new ArrayDeque<>();
    1.14  
    1.15 +    private final Deque<MethodType> callSiteTypes = new ArrayDeque<>();
    1.16 +
    1.17      private static final String ARGUMENTS = ARGUMENTS_VAR.symbolName();
    1.18  
    1.19      /**
    1.20 @@ -118,86 +121,108 @@
    1.21          return context.getLogger(this.getClass());
    1.22      }
    1.23  
    1.24 +    @SuppressWarnings("serial")
    1.25 +    private static class TransformFailedException extends RuntimeException {
    1.26 +        TransformFailedException(final FunctionNode fn, final String message) {
    1.27 +            super(massageURL(fn.getSource().getURL()) + '.' + fn.getName() + " => " + message, null, false, false);
    1.28 +        }
    1.29 +    }
    1.30 +
    1.31 +    @SuppressWarnings("serial")
    1.32 +    private static class AppliesFoundException extends RuntimeException {
    1.33 +        AppliesFoundException() {
    1.34 +            super("applies_found", null, false, false);
    1.35 +        }
    1.36 +    }
    1.37 +
    1.38 +    private static final AppliesFoundException HAS_APPLIES = new AppliesFoundException();
    1.39 +
    1.40 +    private boolean hasApplies(final FunctionNode functionNode) {
    1.41 +        try {
    1.42 +            functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
    1.43 +                @Override
    1.44 +                public boolean enterCallNode(final CallNode callNode) {
    1.45 +                    if (isApply(callNode)) {
    1.46 +                        throw HAS_APPLIES;
    1.47 +                    }
    1.48 +                    return true;
    1.49 +                }
    1.50 +            });
    1.51 +        } catch (final AppliesFoundException e) {
    1.52 +            return true;
    1.53 +        }
    1.54 +
    1.55 +        log.fine("There are no applies in ", DebugLogger.quote(functionNode.getName()), " - nothing to do.");
    1.56 +        return false; // no applies
    1.57 +    }
    1.58 +
    1.59      /**
    1.60       * Arguments may only be used as args to the apply. Everything else is disqualified
    1.61       * We cannot control arguments if they escape from the method and go into an unknown
    1.62       * scope, thus we are conservative and treat any access to arguments outside the
    1.63       * apply call as a case of "we cannot apply the optimization".
    1.64 -     *
    1.65 -     * @return true if arguments escape
    1.66       */
    1.67 -    private boolean argumentsEscape(final FunctionNode functionNode) {
    1.68 -
    1.69 -        @SuppressWarnings("serial")
    1.70 -        final UnsupportedOperationException uoe = new UnsupportedOperationException() {
    1.71 -            @Override
    1.72 -            public synchronized Throwable fillInStackTrace() {
    1.73 -                return null;
    1.74 -            }
    1.75 -        };
    1.76 +    private void checkValidTransform(final FunctionNode functionNode) {
    1.77  
    1.78          final Set<Expression> argumentsFound = new HashSet<>();
    1.79          final Deque<Set<Expression>> stack = new ArrayDeque<>();
    1.80 +
    1.81          //ensure that arguments is only passed as arg to apply
    1.82 -        try {
    1.83 -            functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
    1.84 -                private boolean isCurrentArg(final Expression expr) {
    1.85 -                    return !stack.isEmpty() && stack.peek().contains(expr); //args to current apply call
    1.86 -                }
    1.87 +        functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
    1.88  
    1.89 -                private boolean isArguments(final Expression expr) {
    1.90 -                    if (expr instanceof IdentNode && ARGUMENTS.equals(((IdentNode)expr).getName())) {
    1.91 -                        argumentsFound.add(expr);
    1.92 +            private boolean isCurrentArg(final Expression expr) {
    1.93 +                return !stack.isEmpty() && stack.peek().contains(expr); //args to current apply call
    1.94 +            }
    1.95 +
    1.96 +            private boolean isArguments(final Expression expr) {
    1.97 +                if (expr instanceof IdentNode && ARGUMENTS.equals(((IdentNode)expr).getName())) {
    1.98 +                    argumentsFound.add(expr);
    1.99 +                    return true;
   1.100 +               }
   1.101 +                return false;
   1.102 +            }
   1.103 +
   1.104 +            private boolean isParam(final String name) {
   1.105 +                for (final IdentNode param : functionNode.getParameters()) {
   1.106 +                    if (param.getName().equals(name)) {
   1.107                          return true;
   1.108                      }
   1.109 -                    return false;
   1.110                  }
   1.111 +                return false;
   1.112 +            }
   1.113  
   1.114 -                private boolean isParam(final String name) {
   1.115 -                    for (final IdentNode param : functionNode.getParameters()) {
   1.116 -                        if (param.getName().equals(name)) {
   1.117 -                            return true;
   1.118 -                        }
   1.119 +            @Override
   1.120 +            public Node leaveIdentNode(final IdentNode identNode) {
   1.121 +                if (isParam(identNode.getName())) {
   1.122 +                    throw new TransformFailedException(lc.getCurrentFunction(), "parameter: " + identNode.getName());
   1.123 +                }
   1.124 +                // it's OK if 'argument' occurs as the current argument of an apply
   1.125 +                if (isArguments(identNode) && !isCurrentArg(identNode)) {
   1.126 +                    throw new TransformFailedException(lc.getCurrentFunction(), "is 'arguments': " + identNode.getName());
   1.127 +                }
   1.128 +                return identNode;
   1.129 +            }
   1.130 +
   1.131 +            @Override
   1.132 +            public boolean enterCallNode(final CallNode callNode) {
   1.133 +                final Set<Expression> callArgs = new HashSet<>();
   1.134 +                if (isApply(callNode)) {
   1.135 +                    final List<Expression> argList = callNode.getArgs();
   1.136 +                    if (argList.size() != 2 || !isArguments(argList.get(argList.size() - 1))) {
   1.137 +                        throw new TransformFailedException(lc.getCurrentFunction(), "argument pattern not matched: " + argList);
   1.138                      }
   1.139 -                    return false;
   1.140 +                    callArgs.addAll(callNode.getArgs());
   1.141                  }
   1.142 +                stack.push(callArgs);
   1.143 +                return true;
   1.144 +            }
   1.145  
   1.146 -                @Override
   1.147 -                public Node leaveIdentNode(final IdentNode identNode) {
   1.148 -                    if (isParam(identNode.getName()) || isArguments(identNode) && !isCurrentArg(identNode)) {
   1.149 -                        throw uoe; //avoid filling in stack trace
   1.150 -                    }
   1.151 -                    return identNode;
   1.152 -                }
   1.153 -
   1.154 -                @Override
   1.155 -                public boolean enterCallNode(final CallNode callNode) {
   1.156 -                    final Set<Expression> callArgs = new HashSet<>();
   1.157 -                    if (isApply(callNode)) {
   1.158 -                        final List<Expression> argList = callNode.getArgs();
   1.159 -                        if (argList.size() != 2 || !isArguments(argList.get(argList.size() - 1))) {
   1.160 -                            throw new UnsupportedOperationException();
   1.161 -                        }
   1.162 -                        callArgs.addAll(callNode.getArgs());
   1.163 -                    }
   1.164 -                    stack.push(callArgs);
   1.165 -                    return true;
   1.166 -                }
   1.167 -
   1.168 -                @Override
   1.169 -                public Node leaveCallNode(final CallNode callNode) {
   1.170 -                    stack.pop();
   1.171 -                    return callNode;
   1.172 -                }
   1.173 -            });
   1.174 -        } catch (final UnsupportedOperationException e) {
   1.175 -            if (!argumentsFound.isEmpty()) {
   1.176 -                log.fine("'arguments' is used but escapes, or is reassigned in '" + functionNode.getName() + "'. Aborting");
   1.177 +            @Override
   1.178 +            public Node leaveCallNode(final CallNode callNode) {
   1.179 +                stack.pop();
   1.180 +                return callNode;
   1.181              }
   1.182 -            return true; //bad
   1.183 -        }
   1.184 -
   1.185 -        return false;
   1.186 +       });
   1.187      }
   1.188  
   1.189      @Override
   1.190 @@ -224,12 +249,14 @@
   1.191  
   1.192              final CallNode newCallNode = callNode.setArgs(newArgs).setIsApplyToCall();
   1.193  
   1.194 -            log.fine("Transformed ",
   1.195 -                    callNode,
   1.196 -                    " from apply to call => ",
   1.197 -                    newCallNode,
   1.198 -                    " in ",
   1.199 -                    DebugLogger.quote(lc.getCurrentFunction().getName()));
   1.200 +            if (log.isEnabled()) {
   1.201 +                log.fine("Transformed ",
   1.202 +                        callNode,
   1.203 +                        " from apply to call => ",
   1.204 +                        newCallNode,
   1.205 +                        " in ",
   1.206 +                        DebugLogger.quote(lc.getCurrentFunction().getName()));
   1.207 +            }
   1.208  
   1.209              return newCallNode;
   1.210          }
   1.211 @@ -237,12 +264,12 @@
   1.212          return callNode;
   1.213      }
   1.214  
   1.215 -    private boolean pushExplodedArgs(final FunctionNode functionNode) {
   1.216 +    private void pushExplodedArgs(final FunctionNode functionNode) {
   1.217          int start = 0;
   1.218  
   1.219          final MethodType actualCallSiteType = compiler.getCallSiteType(functionNode);
   1.220          if (actualCallSiteType == null) {
   1.221 -            return false;
   1.222 +            throw new TransformFailedException(lc.getCurrentFunction(), "No callsite type");
   1.223          }
   1.224          assert actualCallSiteType.parameterType(actualCallSiteType.parameterCount() - 1) != Object[].class : "error vararg callsite passed to apply2call " + functionNode.getName() + " " + actualCallSiteType;
   1.225  
   1.226 @@ -264,8 +291,8 @@
   1.227              }
   1.228          }
   1.229  
   1.230 +        callSiteTypes.push(actualCallSiteType);
   1.231          explodedArguments.push(newParams);
   1.232 -        return true;
   1.233      }
   1.234  
   1.235      @Override
   1.236 @@ -288,11 +315,30 @@
   1.237              return false;
   1.238          }
   1.239  
   1.240 -        if (argumentsEscape(functionNode)) {
   1.241 +        if (!hasApplies(functionNode)) {
   1.242              return false;
   1.243          }
   1.244  
   1.245 -        return pushExplodedArgs(functionNode);
   1.246 +        if (log.isEnabled()) {
   1.247 +            log.info("Trying to specialize apply to call in '",
   1.248 +                    functionNode.getName(),
   1.249 +                    "' params=",
   1.250 +                    functionNode.getParameters(),
   1.251 +                    " id=",
   1.252 +                    functionNode.getId(),
   1.253 +                    " source=",
   1.254 +                    massageURL(functionNode.getSource().getURL()));
   1.255 +        }
   1.256 +
   1.257 +        try {
   1.258 +            checkValidTransform(functionNode);
   1.259 +            pushExplodedArgs(functionNode);
   1.260 +        } catch (final TransformFailedException e) {
   1.261 +            log.info("Failure: ", e.getMessage());
   1.262 +            return false;
   1.263 +        }
   1.264 +
   1.265 +        return true;
   1.266      }
   1.267  
   1.268      /**
   1.269 @@ -300,8 +346,8 @@
   1.270       * @return true if successful, false otherwise
   1.271       */
   1.272      @Override
   1.273 -    public Node leaveFunctionNode(final FunctionNode functionNode0) {
   1.274 -        FunctionNode newFunctionNode = functionNode0;
   1.275 +    public Node leaveFunctionNode(final FunctionNode functionNode) {
   1.276 +        FunctionNode newFunctionNode = functionNode;
   1.277          final String functionName = newFunctionNode.getName();
   1.278  
   1.279          if (changed.contains(newFunctionNode.getId())) {
   1.280 @@ -310,17 +356,18 @@
   1.281                      setParameters(lc, explodedArguments.peek());
   1.282  
   1.283              if (log.isEnabled()) {
   1.284 -                log.info("Successfully specialized apply to call in '",
   1.285 +                log.info("Success: ",
   1.286 +                        massageURL(newFunctionNode.getSource().getURL()),
   1.287 +                        '.',
   1.288                          functionName,
   1.289 -                        " params=",
   1.290 -                        explodedArguments.peek(),
   1.291                          "' id=",
   1.292                          newFunctionNode.getId(),
   1.293 -                        " source=",
   1.294 -                        newFunctionNode.getSource().getURL());
   1.295 +                        " params=",
   1.296 +                        callSiteTypes.peek());
   1.297              }
   1.298          }
   1.299  
   1.300 +        callSiteTypes.pop();
   1.301          explodedArguments.pop();
   1.302  
   1.303          return newFunctionNode.setState(lc, CompilationState.BUILTINS_TRANSFORMED);
   1.304 @@ -331,4 +378,15 @@
   1.305          return f instanceof AccessNode && "apply".equals(((AccessNode)f).getProperty());
   1.306      }
   1.307  
   1.308 +    private static String massageURL(final URL url) {
   1.309 +        if (url == null) {
   1.310 +            return "<null>";
   1.311 +        }
   1.312 +        final String str = url.toString();
   1.313 +        final int slash = str.lastIndexOf('/');
   1.314 +        if (slash == -1) {
   1.315 +            return str;
   1.316 +        }
   1.317 +        return str.substring(slash + 1);
   1.318 +    }
   1.319  }
     2.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Mon Nov 03 14:59:34 2014 +0100
     2.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Nov 05 12:34:06 2014 +0100
     2.3 @@ -615,7 +615,6 @@
     2.4  
     2.5          static final TypeBounds UNBOUNDED = new TypeBounds(Type.UNKNOWN, Type.OBJECT);
     2.6          static final TypeBounds INT = exact(Type.INT);
     2.7 -        static final TypeBounds NUMBER = exact(Type.NUMBER);
     2.8          static final TypeBounds OBJECT = exact(Type.OBJECT);
     2.9          static final TypeBounds BOOLEAN = exact(Type.BOOLEAN);
    2.10  
    2.11 @@ -3894,7 +3893,7 @@
    2.12  
    2.13      private static boolean isRhsZero(final BinaryNode binaryNode) {
    2.14          final Expression rhs = binaryNode.rhs();
    2.15 -        return rhs instanceof LiteralNode && INT_ZERO.equals(((LiteralNode)rhs).getValue());
    2.16 +        return rhs instanceof LiteralNode && INT_ZERO.equals(((LiteralNode<?>)rhs).getValue());
    2.17      }
    2.18  
    2.19      private void loadBIT_XOR(final BinaryNode binaryNode) {
     3.1 --- a/src/jdk/nashorn/internal/codegen/types/Type.java	Mon Nov 03 14:59:34 2014 +0100
     3.2 +++ b/src/jdk/nashorn/internal/codegen/types/Type.java	Wed Nov 05 12:34:06 2014 +0100
     3.3 @@ -1155,6 +1155,10 @@
     3.4          return type;
     3.5      }
     3.6  
     3.7 +    /**
     3.8 +     * Read resolve
     3.9 +     * @return resolved type
    3.10 +     */
    3.11      protected final Object readResolve() {
    3.12          return Type.typeFor(clazz);
    3.13      }
     4.1 --- a/src/jdk/nashorn/internal/objects/NativeString.java	Mon Nov 03 14:59:34 2014 +0100
     4.2 +++ b/src/jdk/nashorn/internal/objects/NativeString.java	Wed Nov 05 12:34:06 2014 +0100
     4.3 @@ -29,6 +29,7 @@
     4.4  import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
     4.5  import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt;
     4.6  import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
     4.7 +
     4.8  import java.lang.invoke.MethodHandle;
     4.9  import java.lang.invoke.MethodHandles;
    4.10  import java.lang.invoke.MethodType;
    4.11 @@ -1380,7 +1381,6 @@
    4.12       * sequence and that we are in range
    4.13       */
    4.14      private static final class CharCodeAtLinkLogic extends SpecializedFunction.LinkLogic {
    4.15 -
    4.16          private static final CharCodeAtLinkLogic INSTANCE = new CharCodeAtLinkLogic();
    4.17  
    4.18          @Override
     5.1 --- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Mon Nov 03 14:59:34 2014 +0100
     5.2 +++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java	Wed Nov 05 12:34:06 2014 +0100
     5.3 @@ -26,6 +26,7 @@
     5.4  package jdk.nashorn.internal.runtime;
     5.5  
     5.6  import static jdk.nashorn.internal.lookup.Lookup.MH;
     5.7 +
     5.8  import java.io.IOException;
     5.9  import java.lang.invoke.MethodHandle;
    5.10  import java.lang.invoke.MethodHandles;
    5.11 @@ -727,7 +728,7 @@
    5.12  
    5.13          assert existingBest != null;
    5.14          //we are calling a vararg method with real args
    5.15 -        boolean applyToCall = existingBest.isVarArg() && !CompiledFunction.isVarArgsType(callSiteType);
    5.16 +        boolean varArgWithRealArgs = existingBest.isVarArg() && !CompiledFunction.isVarArgsType(callSiteType);
    5.17  
    5.18          //if the best one is an apply to call, it has to match the callsite exactly
    5.19          //or we need to regenerate
    5.20 @@ -736,14 +737,16 @@
    5.21              if (best != null) {
    5.22                  return best;
    5.23              }
    5.24 -            applyToCall = true;
    5.25 +            varArgWithRealArgs = true;
    5.26          }
    5.27  
    5.28 -        if (applyToCall) {
    5.29 +        if (varArgWithRealArgs) {
    5.30 +            // special case: we had an apply to call, but we failed to make it fit.
    5.31 +            // Try to generate a specialized one for this callsite. It may
    5.32 +            // be another apply to call specialization, or it may not, but whatever
    5.33 +            // it is, it is a specialization that is guaranteed to fit
    5.34              final FunctionInitializer fnInit = compileTypeSpecialization(callSiteType, runtimeScope, false);
    5.35 -            if ((fnInit.getFlags() & FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION) != 0) { //did the specialization work
    5.36 -                existingBest = addCode(fnInit, callSiteType);
    5.37 -            }
    5.38 +            existingBest = addCode(fnInit, callSiteType);
    5.39          }
    5.40  
    5.41          return existingBest;
     6.1 --- a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java	Mon Nov 03 14:59:34 2014 +0100
     6.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java	Wed Nov 05 12:34:06 2014 +0100
     6.3 @@ -36,12 +36,7 @@
     6.4   * Handle arrays where the index is very large.
     6.5   */
     6.6  class SparseArrayData extends ArrayData {
     6.7 -    static final long MAX_DENSE_LENGTH = 16 * 512 * 1024;
     6.8 -
     6.9 -    static {
    6.10 -        // we must break into sparse arrays before we require long indexes
    6.11 -        assert MAX_DENSE_LENGTH <= Integer.MAX_VALUE;
    6.12 -    }
    6.13 +    static final int MAX_DENSE_LENGTH = 8 * 1024 * 1024;
    6.14  
    6.15      /** Underlying array. */
    6.16      private ArrayData underlying;
     7.1 --- a/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java	Mon Nov 03 14:59:34 2014 +0100
     7.2 +++ b/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java	Wed Nov 05 12:34:06 2014 +0100
     7.3 @@ -47,7 +47,7 @@
     7.4       * @param level            logging level
     7.5       * @param rewriteException rewriteException wrapped by this RuntimEvent
     7.6       * @param returnValue      rewriteException return value - as we don't want to make
     7.7 -     *     {@link RewriteException#getReturnValueNonDestructive()} public, we pass it as
     7.8 +     *     {@code RewriteException.getReturnValueNonDestructive()} public, we pass it as
     7.9       *     an extra parameter, rather than querying the getter from another package.
    7.10       */
    7.11      public RecompilationEvent(final Level level, final RewriteException rewriteException, final Object returnValue) {
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/test/script/basic/JDK-8057825.js	Wed Nov 05 12:34:06 2014 +0100
     8.3 @@ -0,0 +1,45 @@
     8.4 +/*
     8.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
     8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.7 + *
     8.8 + * This code is free software; you can redistribute it and/or modify it
     8.9 + * under the terms of the GNU General Public License version 2 only, as
    8.10 + * published by the Free Software Foundation.
    8.11 + *
    8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    8.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    8.15 + * version 2 for more details (a copy is included in the LICENSE file that
    8.16 + * accompanied this code).
    8.17 + *
    8.18 + * You should have received a copy of the GNU General Public License version
    8.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    8.21 + *
    8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    8.23 + * or visit www.oracle.com if you need additional information or have any
    8.24 + * questions.
    8.25 + */
    8.26 +
    8.27 +/**
    8.28 + * JDK-8057825 : A failed apply to call generation should NOT reuse the 
    8.29 + * best apply to call generation so far - because it may not fit!!!
    8.30 + *
    8.31 + * @test
    8.32 + * @run
    8.33 + */
    8.34 +
    8.35 +function createApplier(f) { 
    8.36 +    function applier() { 
    8.37 +        f.apply(this, arguments); // no transform applied here 
    8.38 +    } 
    8.39 +    return applier; 
    8.40 +} 
    8.41 +
    8.42 +function printer(x,y) { 
    8.43 +    print(x + " and " + y);
    8.44 +} 
    8.45 +
    8.46 +var printerApplier = createApplier(printer); 
    8.47 +printerApplier();
    8.48 +printerApplier.apply(this, ["foo", "bar"]); 
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/test/script/basic/JDK-8057825.js.EXPECTED	Wed Nov 05 12:34:06 2014 +0100
     9.3 @@ -0,0 +1,2 @@
     9.4 +undefined and undefined
     9.5 +foo and bar
    10.1 --- a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java	Mon Nov 03 14:59:34 2014 +0100
    10.2 +++ b/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java	Wed Nov 05 12:34:06 2014 +0100
    10.3 @@ -28,6 +28,7 @@
    10.4  import jdk.nashorn.test.models.ClassLoaderAware;
    10.5  import org.testng.annotations.Test;
    10.6  
    10.7 +@SuppressWarnings("javadoc")
    10.8  public class CallerSensitiveTest {
    10.9      @Test
   10.10      public void testCallerSensitive() {
    11.1 --- a/test/src/jdk/nashorn/test/models/ClassLoaderAware.java	Mon Nov 03 14:59:34 2014 +0100
    11.2 +++ b/test/src/jdk/nashorn/test/models/ClassLoaderAware.java	Wed Nov 05 12:34:06 2014 +0100
    11.3 @@ -25,6 +25,7 @@
    11.4  
    11.5  package jdk.nashorn.test.models;
    11.6  
    11.7 +@SuppressWarnings("javadoc")
    11.8  public interface ClassLoaderAware {
    11.9      public ClassLoader getContextClassLoader();
   11.10      public void checkMemberAccess(Class<?> clazz, int which);

mercurial