8032681: Issues with Nashorn

Thu, 30 Jan 2014 20:14:29 +0100

author
attila
date
Thu, 30 Jan 2014 20:14:29 +0100
changeset 719
11b83c913cca
parent 718
c59fb10cb0b5
child 720
e77bf2c56784
child 729
73cbad0c5d28

8032681: Issues with Nashorn
Reviewed-by: ahgross, jlaskey, sundar

src/jdk/internal/dynalink/linker/GuardedTypeConversion.java file | annotate | diff | comparison | revisions
src/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java file | annotate | diff | comparison | revisions
src/jdk/internal/dynalink/support/LinkerServicesImpl.java file | annotate | diff | comparison | revisions
src/jdk/internal/dynalink/support/TypeConverterFactory.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/api/scripting/NashornScriptEngine.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeJava.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeJavaImporter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/Context.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/NativeJavaPackage.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptFunction.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/AdaptationResult.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/NashornLinker.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/resources/Messages.properties file | annotate | diff | comparison | revisions
test/script/basic/JDK-8014647.js file | annotate | diff | comparison | revisions
test/script/basic/JDK-8014647.js.EXPECTED file | annotate | diff | comparison | revisions
test/script/basic/javaclassoverrides.js file | annotate | diff | comparison | revisions
test/script/basic/javaclassoverrides.js.EXPECTED file | annotate | diff | comparison | revisions
test/script/sandbox/javaextend.js file | annotate | diff | comparison | revisions
test/script/sandbox/javaextend.js.EXPECTED file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/test/models/ClassWithFinalFinalizer.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/test/models/ClassWithInheritedFinalFinalizer.java file | annotate | diff | comparison | revisions
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java	Thu Jan 30 20:14:29 2014 +0100
     1.3 @@ -0,0 +1,102 @@
     1.4 +/*
     1.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +/*
    1.30 + * This file is available under and governed by the GNU General Public
    1.31 + * License version 2 only, as published by the Free Software Foundation.
    1.32 + * However, the following notice accompanied the original version of this
    1.33 + * file, and Oracle licenses the original version of this file under the BSD
    1.34 + * license:
    1.35 + */
    1.36 +/*
    1.37 +   Copyright 2009-2013 Attila Szegedi
    1.38 +
    1.39 +   Licensed under both the Apache License, Version 2.0 (the "Apache License")
    1.40 +   and the BSD License (the "BSD License"), with licensee being free to
    1.41 +   choose either of the two at their discretion.
    1.42 +
    1.43 +   You may not use this file except in compliance with either the Apache
    1.44 +   License or the BSD License.
    1.45 +
    1.46 +   If you choose to use this file in compliance with the Apache License, the
    1.47 +   following notice applies to you:
    1.48 +
    1.49 +       You may obtain a copy of the Apache License at
    1.50 +
    1.51 +           http://www.apache.org/licenses/LICENSE-2.0
    1.52 +
    1.53 +       Unless required by applicable law or agreed to in writing, software
    1.54 +       distributed under the License is distributed on an "AS IS" BASIS,
    1.55 +       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    1.56 +       implied. See the License for the specific language governing
    1.57 +       permissions and limitations under the License.
    1.58 +
    1.59 +   If you choose to use this file in compliance with the BSD License, the
    1.60 +   following notice applies to you:
    1.61 +
    1.62 +       Redistribution and use in source and binary forms, with or without
    1.63 +       modification, are permitted provided that the following conditions are
    1.64 +       met:
    1.65 +       * Redistributions of source code must retain the above copyright
    1.66 +         notice, this list of conditions and the following disclaimer.
    1.67 +       * Redistributions in binary form must reproduce the above copyright
    1.68 +         notice, this list of conditions and the following disclaimer in the
    1.69 +         documentation and/or other materials provided with the distribution.
    1.70 +       * Neither the name of the copyright holder nor the names of
    1.71 +         contributors may be used to endorse or promote products derived from
    1.72 +         this software without specific prior written permission.
    1.73 +
    1.74 +       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
    1.75 +       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
    1.76 +       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
    1.77 +       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
    1.78 +       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    1.79 +       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    1.80 +       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
    1.81 +       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    1.82 +       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    1.83 +       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
    1.84 +       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.85 +*/
    1.86 +
    1.87 +package jdk.internal.dynalink.linker;
    1.88 +
    1.89 +public class GuardedTypeConversion {
    1.90 +    private final GuardedInvocation conversionInvocation;
    1.91 +    private final boolean cacheable;
    1.92 +
    1.93 +    public GuardedTypeConversion(final GuardedInvocation conversionInvocation, final boolean cacheable) {
    1.94 +        this.conversionInvocation = conversionInvocation;
    1.95 +        this.cacheable = cacheable;
    1.96 +    }
    1.97 +
    1.98 +    public GuardedInvocation getConversionInvocation() {
    1.99 +        return conversionInvocation;
   1.100 +    }
   1.101 +
   1.102 +    public boolean isCacheable() {
   1.103 +        return cacheable;
   1.104 +    }
   1.105 +}
     2.1 --- a/src/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java	Thu Jan 30 19:45:20 2014 +0530
     2.2 +++ b/src/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java	Thu Jan 30 20:14:29 2014 +0100
     2.3 @@ -96,19 +96,19 @@
     2.4   */
     2.5  public interface GuardingTypeConverterFactory {
     2.6      /**
     2.7 -     * Returns a guarded invocation that receives an Object of the specified source type and returns an Object converted
     2.8 -     * to the specified target type. The type of the invocation is targetType(sourceType), while the type of the guard
     2.9 -     * is boolean(sourceType). Note that this will never be invoked for type conversions allowed by the JLS 5.3 "Method
    2.10 -     * Invocation Conversion", see {@link TypeUtilities#isMethodInvocationConvertible(Class, Class)} for details. An
    2.11 -     * implementation can assume it is never requested to produce a converter for these conversions.
    2.12 +     * Returns a guarded type conversion that receives an Object of the specified source type and returns an Object
    2.13 +     * converted to the specified target type. The type of the invocation is targetType(sourceType), while the type of
    2.14 +     * the guard is boolean(sourceType). Note that this will never be invoked for type conversions allowed by the JLS
    2.15 +     * 5.3 "Method Invocation Conversion", see {@link TypeUtilities#isMethodInvocationConvertible(Class, Class)} for
    2.16 +     * details. An implementation can assume it is never requested to produce a converter for these conversions.
    2.17       *
    2.18       * @param sourceType source type
    2.19       * @param targetType the target type.
    2.20 -     * @return a guarded invocation that can take an object (if it passes guard) and returns another object that is its
    2.21 -     * representation coerced into the target type. In case the factory is certain it is unable to handle a conversion,
    2.22 -     * it can return null. In case the factory is certain that it can always handle the conversion, it can return an
    2.23 -     * unconditional invocation (one whose guard is null).
    2.24 +     * @return a guarded type conversion that contains a guarded invocation that can take an object (if it passes guard)
    2.25 +     * and return another object that is its representation coerced into the target type. In case the factory is certain
    2.26 +     * it is unable to handle a conversion, it can return null. In case the factory is certain that it can always handle
    2.27 +     * the conversion, it can return an unconditional invocation (one whose guard is null).
    2.28       * @throws Exception if there was an error during creation of the converter
    2.29       */
    2.30 -    public GuardedInvocation convertToType(Class<?> sourceType, Class<?> targetType) throws Exception;
    2.31 +    public GuardedTypeConversion convertToType(Class<?> sourceType, Class<?> targetType) throws Exception;
    2.32  }
     3.1 --- a/src/jdk/internal/dynalink/support/LinkerServicesImpl.java	Thu Jan 30 19:45:20 2014 +0530
     3.2 +++ b/src/jdk/internal/dynalink/support/LinkerServicesImpl.java	Thu Jan 30 20:14:29 2014 +0100
     3.3 @@ -98,6 +98,9 @@
     3.4   */
     3.5  public class LinkerServicesImpl implements LinkerServices {
     3.6  
     3.7 +    private static final RuntimePermission GET_CURRENT_LINK_REQUEST = new RuntimePermission("dynalink.getCurrentLinkRequest");
     3.8 +    private static final ThreadLocal<LinkRequest> threadLinkRequest = new ThreadLocal<>();
     3.9 +
    3.10      private final TypeConverterFactory typeConverterFactory;
    3.11      private final GuardingDynamicLinker topLevelLinker;
    3.12  
    3.13 @@ -135,6 +138,26 @@
    3.14  
    3.15      @Override
    3.16      public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest) throws Exception {
    3.17 -        return topLevelLinker.getGuardedInvocation(linkRequest, this);
    3.18 +        final LinkRequest prevLinkRequest = threadLinkRequest.get();
    3.19 +        threadLinkRequest.set(linkRequest);
    3.20 +        try {
    3.21 +            return topLevelLinker.getGuardedInvocation(linkRequest, this);
    3.22 +        } finally {
    3.23 +            threadLinkRequest.set(prevLinkRequest);
    3.24 +        }
    3.25 +    }
    3.26 +
    3.27 +    /**
    3.28 +     * Returns the currently processed link request, or null if the method is invoked outside of the linking process.
    3.29 +     * @return the currently processed link request, or null.
    3.30 +     * @throws SecurityException if the calling code doesn't have the {@code "dynalink.getCurrentLinkRequest"} runtime
    3.31 +     * permission.
    3.32 +     */
    3.33 +    public static LinkRequest getCurrentLinkRequest() {
    3.34 +        SecurityManager sm = System.getSecurityManager();
    3.35 +        if(sm != null) {
    3.36 +            sm.checkPermission(GET_CURRENT_LINK_REQUEST);
    3.37 +        }
    3.38 +        return threadLinkRequest.get();
    3.39      }
    3.40  }
     4.1 --- a/src/jdk/internal/dynalink/support/TypeConverterFactory.java	Thu Jan 30 19:45:20 2014 +0530
     4.2 +++ b/src/jdk/internal/dynalink/support/TypeConverterFactory.java	Thu Jan 30 20:14:29 2014 +0100
     4.3 @@ -94,6 +94,7 @@
     4.4  import jdk.internal.dynalink.linker.ConversionComparator;
     4.5  import jdk.internal.dynalink.linker.ConversionComparator.Comparison;
     4.6  import jdk.internal.dynalink.linker.GuardedInvocation;
     4.7 +import jdk.internal.dynalink.linker.GuardedTypeConversion;
     4.8  import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
     4.9  import jdk.internal.dynalink.linker.LinkerServices;
    4.10  
    4.11 @@ -134,8 +135,8 @@
    4.12                  @Override
    4.13                  protected MethodHandle computeValue(Class<?> targetType) {
    4.14                      if(!canAutoConvert(sourceType, targetType)) {
    4.15 -                        final MethodHandle converter = getTypeConverterNull(sourceType, targetType);
    4.16 -                        if(converter != null) {
    4.17 +                        final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType);
    4.18 +                        if(converter != IDENTITY_CONVERSION) {
    4.19                              return converter;
    4.20                          }
    4.21                      }
    4.22 @@ -145,6 +146,24 @@
    4.23          }
    4.24      };
    4.25  
    4.26 +    private final ClassValue<ClassMap<Boolean>> canConvert = new ClassValue<ClassMap<Boolean>>() {
    4.27 +        @Override
    4.28 +        protected ClassMap<Boolean> computeValue(final Class<?> sourceType) {
    4.29 +            return new ClassMap<Boolean>(getClassLoader(sourceType)) {
    4.30 +                @Override
    4.31 +                protected Boolean computeValue(Class<?> targetType) {
    4.32 +                    try {
    4.33 +                        return getTypeConverterNull(sourceType, targetType) != null;
    4.34 +                    } catch (RuntimeException e) {
    4.35 +                        throw e;
    4.36 +                    } catch (Exception e) {
    4.37 +                        throw new RuntimeException(e);
    4.38 +                    }
    4.39 +                }
    4.40 +            };
    4.41 +        }
    4.42 +    };
    4.43 +
    4.44      private static final ClassLoader getClassLoader(final Class<?> clazz) {
    4.45          return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
    4.46              @Override
    4.47 @@ -253,7 +272,7 @@
    4.48       * @return true if there can be a conversion, false if there can not.
    4.49       */
    4.50      public boolean canConvert(final Class<?> from, final Class<?> to) {
    4.51 -        return canAutoConvert(from, to) || getTypeConverterNull(from, to) != null;
    4.52 +        return canAutoConvert(from, to) || canConvert.get(from).get(to).booleanValue();
    4.53      }
    4.54  
    4.55      /**
    4.56 @@ -294,9 +313,21 @@
    4.57          return TypeUtilities.isMethodInvocationConvertible(fromType, toType);
    4.58      }
    4.59  
    4.60 +    /*private*/ MethodHandle getCacheableTypeConverterNull(Class<?> sourceType, Class<?> targetType) {
    4.61 +        final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType);
    4.62 +        return converter == IDENTITY_CONVERSION ? null : converter;
    4.63 +    }
    4.64 +
    4.65      /*private*/ MethodHandle getTypeConverterNull(Class<?> sourceType, Class<?> targetType) {
    4.66 -        final MethodHandle converter = converterMap.get(sourceType).get(targetType);
    4.67 -        return converter == IDENTITY_CONVERSION ? null : converter;
    4.68 +        try {
    4.69 +            return getCacheableTypeConverterNull(sourceType, targetType);
    4.70 +        } catch(NotCacheableConverter e) {
    4.71 +            return e.converter;
    4.72 +        }
    4.73 +    }
    4.74 +
    4.75 +    /*private*/ MethodHandle getCacheableTypeConverter(Class<?> sourceType, Class<?> targetType) {
    4.76 +        return converterMap.get(sourceType).get(targetType);
    4.77      }
    4.78  
    4.79      /**
    4.80 @@ -309,22 +340,44 @@
    4.81       * @return a method handle performing the conversion.
    4.82       */
    4.83      public MethodHandle getTypeConverter(Class<?> sourceType, Class<?> targetType) {
    4.84 -        return converterIdentityMap.get(sourceType).get(targetType);
    4.85 +        try {
    4.86 +            return converterIdentityMap.get(sourceType).get(targetType);
    4.87 +        } catch(NotCacheableConverter e) {
    4.88 +            return e.converter;
    4.89 +        }
    4.90      }
    4.91  
    4.92      /*private*/ MethodHandle createConverter(Class<?> sourceType, Class<?> targetType) throws Exception {
    4.93          final MethodType type = MethodType.methodType(targetType, sourceType);
    4.94          final MethodHandle identity = IDENTITY_CONVERSION.asType(type);
    4.95          MethodHandle last = identity;
    4.96 +        boolean cacheable = true;
    4.97          for(int i = factories.length; i-- > 0;) {
    4.98 -            final GuardedInvocation next = factories[i].convertToType(sourceType, targetType);
    4.99 +            final GuardedTypeConversion next = factories[i].convertToType(sourceType, targetType);
   4.100              if(next != null) {
   4.101 -                next.assertType(type);
   4.102 -                last = next.compose(last);
   4.103 +                cacheable = cacheable && next.isCacheable();
   4.104 +                final GuardedInvocation conversionInvocation = next.getConversionInvocation();
   4.105 +                conversionInvocation.assertType(type);
   4.106 +                last = conversionInvocation.compose(last);
   4.107              }
   4.108          }
   4.109 -        return last == identity ? IDENTITY_CONVERSION : last;
   4.110 +        if(last == identity) {
   4.111 +            return IDENTITY_CONVERSION;
   4.112 +        }
   4.113 +        if(cacheable) {
   4.114 +            return last;
   4.115 +        }
   4.116 +        throw new NotCacheableConverter(last);
   4.117      }
   4.118  
   4.119      /*private*/ static final MethodHandle IDENTITY_CONVERSION = MethodHandles.identity(Object.class);
   4.120 +
   4.121 +    private static class NotCacheableConverter extends RuntimeException {
   4.122 +        final MethodHandle converter;
   4.123 +
   4.124 +        NotCacheableConverter(final MethodHandle converter) {
   4.125 +            super("", null, false, false);
   4.126 +            this.converter = converter;
   4.127 +        }
   4.128 +    }
   4.129  }
     5.1 --- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Thu Jan 30 19:45:20 2014 +0530
     5.2 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java	Thu Jan 30 20:14:29 2014 +0100
     5.3 @@ -32,6 +32,7 @@
     5.4  import java.io.InputStream;
     5.5  import java.io.InputStreamReader;
     5.6  import java.io.Reader;
     5.7 +import java.lang.invoke.MethodHandles;
     5.8  import java.lang.reflect.Method;
     5.9  import java.lang.reflect.Modifier;
    5.10  import java.net.URL;
    5.11 @@ -104,7 +105,7 @@
    5.12      private volatile Property         contextProperty;
    5.13  
    5.14      // default options passed to Nashorn Options object
    5.15 -    private static final String[] DEFAULT_OPTIONS = new String[] { "-scripting", "-doe" };
    5.16 +    private static final String[] DEFAULT_OPTIONS = new String[] { "-doe" };
    5.17  
    5.18      // Nashorn script engine error message management
    5.19      private static final String MESSAGES_RESOURCE = "jdk.nashorn.api.scripting.resources.Messages";
    5.20 @@ -355,7 +356,8 @@
    5.21                  if (! isInterfaceImplemented(clazz, realSelf)) {
    5.22                      return null;
    5.23                  }
    5.24 -                return clazz.cast(JavaAdapterFactory.getConstructor(realSelf.getClass(), clazz).invoke(realSelf));
    5.25 +                return clazz.cast(JavaAdapterFactory.getConstructor(realSelf.getClass(), clazz,
    5.26 +                        MethodHandles.publicLookup()).invoke(realSelf));
    5.27              } finally {
    5.28                  if (globalChanged) {
    5.29                      Context.setGlobal(oldGlobal);
     6.1 --- a/src/jdk/nashorn/internal/objects/NativeJava.java	Thu Jan 30 19:45:20 2014 +0530
     6.2 +++ b/src/jdk/nashorn/internal/objects/NativeJava.java	Thu Jan 30 20:14:29 2014 +0100
     6.3 @@ -28,6 +28,7 @@
     6.4  import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
     6.5  import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
     6.6  
     6.7 +import java.lang.invoke.MethodHandles;
     6.8  import java.lang.reflect.Array;
     6.9  import java.util.Collection;
    6.10  import java.util.Deque;
    6.11 @@ -463,12 +464,14 @@
    6.12       * </pre>
    6.13       * We can see several important concepts in the above example:
    6.14       * <ul>
    6.15 -     * <li>Every specified list of Java types will have exactly one extender subclass in Nashorn - repeated invocations
    6.16 -     * of {@code extend} for the same list of types will yield the same extender type. It's a generic adapter that
    6.17 -     * delegates to whatever JavaScript functions its implementation object has on a per-instance basis.</li>
    6.18 +     * <li>Every specified list of Java types will have one extender subclass in Nashorn per caller protection domain -
    6.19 +     * repeated invocations of {@code extend} for the same list of types for scripts same protection domain will yield
    6.20 +     * the same extender type. It's a generic adapter that delegates to whatever JavaScript functions its implementation
    6.21 +     * object has on a per-instance basis.</li>
    6.22       * <li>If the Java method is overloaded (as in the above example {@code List.add()}), then your JavaScript adapter
    6.23       * must be prepared to deal with all overloads.</li>
    6.24 -     * <li>You can't invoke {@code super.*()} from adapters for now.</li>
    6.25 +     * <li>To invoke super methods from adapters, call them on the adapter instance prefixing them with {@code super$},
    6.26 +     * or use the special {@link #_super(Object, Object) super-adapter}.</li>
    6.27       * <li>It is also possible to specify an ordinary JavaScript object as the last argument to {@code extend}. In that
    6.28       * case, it is treated as a class-level override. {@code extend} will return an extender class where all instances
    6.29       * will have the methods implemented by functions on that object, just as if that object were passed as the last
    6.30 @@ -486,15 +489,18 @@
    6.31       * t.join()
    6.32       * </pre>
    6.33       * As you can see, you don't have to pass any object when you create a new instance of {@code R1} as its
    6.34 -     * {@code run()} function was defined already when extending the class. Of course, you can still provide
    6.35 -     * instance-level overrides on these objects. The order of precedence is instance-level method, class-level method,
    6.36 -     * superclass method, or {@code UnsupportedOperationException} if the superclass method is abstract. If we continue
    6.37 -     * our previous example:
    6.38 +     * {@code run()} function was defined already when extending the class. If you also want to add instance-level
    6.39 +     * overrides on these objects, you will have to repeatedly use {@code extend()} to subclass the class-level adapter.
    6.40 +     * For such adapters, the order of precedence is instance-level method, class-level method, superclass method, or
    6.41 +     * {@code UnsupportedOperationException} if the superclass method is abstract. If we continue our previous example:
    6.42       * <pre>
    6.43 -     * var r2 = new R1(function() { print("r2.run() invoked!") })
    6.44 +     * var R2 = Java.extend(R1);
    6.45 +     * var r2 = new R2(function() { print("r2.run() invoked!") })
    6.46       * r2.run()
    6.47       * </pre>
    6.48       * We'll see it'll print {@code "r2.run() invoked!"}, thus overriding on instance-level the class-level behavior.
    6.49 +     * Note that you must use {@code Java.extend} to explicitly create an instance-override adapter class from a
    6.50 +     * class-override adapter class, as the class-override adapter class is no longer abstract.
    6.51       * </li>
    6.52       * </ul>
    6.53       * @param self not used
    6.54 @@ -541,7 +547,18 @@
    6.55          } catch(final ClassCastException e) {
    6.56              throw typeError("extend.expects.java.types");
    6.57          }
    6.58 -        return JavaAdapterFactory.getAdapterClassFor(stypes, classOverrides);
    6.59 +        // Note that while the public API documentation claims self is not used, we actually use it.
    6.60 +        // ScriptFunction.findCallMethod will bind the lookup object into it, and we can then use that lookup when
    6.61 +        // requesting the adapter class. Note that if Java.extend is invoked with no lookup object, it'll pass the
    6.62 +        // public lookup which'll result in generation of a no-permissions adapter. A typical situation this can happen
    6.63 +        // is when the extend function is bound.
    6.64 +        final MethodHandles.Lookup lookup;
    6.65 +        if(self instanceof MethodHandles.Lookup) {
    6.66 +            lookup = (MethodHandles.Lookup)self;
    6.67 +        } else {
    6.68 +            lookup = MethodHandles.publicLookup();
    6.69 +        }
    6.70 +        return JavaAdapterFactory.getAdapterClassFor(stypes, classOverrides, lookup);
    6.71      }
    6.72  
    6.73      /**
     7.1 --- a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java	Thu Jan 30 19:45:20 2014 +0530
     7.2 +++ b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java	Thu Jan 30 20:14:29 2014 +0100
     7.3 @@ -33,6 +33,7 @@
     7.4  import jdk.nashorn.internal.objects.annotations.Constructor;
     7.5  import jdk.nashorn.internal.objects.annotations.Function;
     7.6  import jdk.nashorn.internal.objects.annotations.ScriptClass;
     7.7 +import jdk.nashorn.internal.runtime.Context;
     7.8  import jdk.nashorn.internal.runtime.NativeJavaPackage;
     7.9  import jdk.nashorn.internal.runtime.PropertyMap;
    7.10  import jdk.nashorn.internal.runtime.ScriptObject;
    7.11 @@ -156,8 +157,9 @@
    7.12              } else if (obj instanceof NativeJavaPackage) {
    7.13                  final String pkgName  = ((NativeJavaPackage)obj).getName();
    7.14                  final String fullName = pkgName.isEmpty() ? name : (pkgName + "." + name);
    7.15 +                final Context context = Global.instance().getContext();
    7.16                  try {
    7.17 -                    return StaticClass.forClass(Class.forName(fullName));
    7.18 +                    return StaticClass.forClass(context.findClass(fullName));
    7.19                  } catch (final ClassNotFoundException e) {
    7.20                      // IGNORE
    7.21                  }
     8.1 --- a/src/jdk/nashorn/internal/runtime/Context.java	Thu Jan 30 19:45:20 2014 +0530
     8.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java	Thu Jan 30 20:14:29 2014 +0100
     8.3 @@ -647,6 +647,19 @@
     8.4      }
     8.5  
     8.6      /**
     8.7 +     * Checks that the given package name can be accessed from no permissions context.
     8.8 +     *
     8.9 +     * @param pkgName package name
    8.10 +     * @throw SecurityException if not accessible
    8.11 +     */
    8.12 +    public static void checkPackageAccess(final String pkgName) {
    8.13 +        final SecurityManager sm = System.getSecurityManager();
    8.14 +        if (sm != null) {
    8.15 +            checkPackageAccess(sm, pkgName.endsWith(".")? pkgName : pkgName + ".");
    8.16 +        }
    8.17 +    }
    8.18 +
    8.19 +    /**
    8.20       * Checks that the given package can be accessed from no permissions context.
    8.21       *
    8.22       * @param sm current security manager instance
     9.1 --- a/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java	Thu Jan 30 19:45:20 2014 +0530
     9.2 +++ b/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java	Thu Jan 30 20:14:29 2014 +0100
     9.3 @@ -85,6 +85,8 @@
     9.4       */
     9.5      public NativeJavaPackage(final String name, final ScriptObject proto) {
     9.6          super(proto, null);
     9.7 +        // defense-in-path, check here for sensitive packages
     9.8 +        Context.checkPackageAccess(name);
     9.9          this.name = name;
    9.10      }
    9.11  
    10.1 --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Thu Jan 30 19:45:20 2014 +0530
    10.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java	Thu Jan 30 20:14:29 2014 +0100
    10.3 @@ -26,14 +26,13 @@
    10.4  package jdk.nashorn.internal.runtime;
    10.5  
    10.6  import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
    10.7 +import static jdk.nashorn.internal.lookup.Lookup.MH;
    10.8  import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
    10.9  import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
   10.10 -import static jdk.nashorn.internal.lookup.Lookup.MH;
   10.11  
   10.12  import java.lang.invoke.MethodHandle;
   10.13  import java.lang.invoke.MethodHandles;
   10.14  import java.lang.invoke.MethodType;
   10.15 -
   10.16  import jdk.internal.dynalink.CallSiteDescriptor;
   10.17  import jdk.internal.dynalink.linker.GuardedInvocation;
   10.18  import jdk.internal.dynalink.linker.LinkRequest;
   10.19 @@ -524,7 +523,11 @@
   10.20              }
   10.21          } else {
   10.22              final MethodHandle callHandle = getBestInvoker(type.dropParameterTypes(0, 1), request.getArguments());
   10.23 -            if (scopeCall) {
   10.24 +            if (data.isBuiltin() && "extend".equals(data.getName())) {
   10.25 +                // NOTE: the only built-in named "extend" is NativeJava.extend. As a special-case we're binding the
   10.26 +                // current lookup as its "this" so it can do security-sensitive creation of adapter classes.
   10.27 +                boundHandle = MH.dropArguments(MH.bindTo(callHandle, desc.getLookup()), 0, Object.class, Object.class);
   10.28 +            } else if (scopeCall) {
   10.29                  // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
   10.30                  // (this, args...) => (args...)
   10.31                  boundHandle = MH.bindTo(callHandle, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED);
    11.1 --- a/src/jdk/nashorn/internal/runtime/linker/AdaptationResult.java	Thu Jan 30 19:45:20 2014 +0530
    11.2 +++ b/src/jdk/nashorn/internal/runtime/linker/AdaptationResult.java	Thu Jan 30 20:14:29 2014 +0100
    11.3 @@ -47,7 +47,8 @@
    11.4          ERROR_NON_PUBLIC_CLASS,
    11.5          ERROR_NO_ACCESSIBLE_CONSTRUCTOR,
    11.6          ERROR_MULTIPLE_SUPERCLASSES,
    11.7 -        ERROR_NO_COMMON_LOADER
    11.8 +        ERROR_NO_COMMON_LOADER,
    11.9 +        ERROR_FINAL_FINALIZER
   11.10      }
   11.11  
   11.12      static final AdaptationResult SUCCESSFUL_RESULT = new AdaptationResult(Outcome.SUCCESS, "");
    12.1 --- a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java	Thu Jan 30 19:45:20 2014 +0530
    12.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java	Thu Jan 30 20:14:29 2014 +0100
    12.3 @@ -32,6 +32,7 @@
    12.4  import java.util.Map;
    12.5  import jdk.internal.dynalink.CallSiteDescriptor;
    12.6  import jdk.internal.dynalink.linker.GuardedInvocation;
    12.7 +import jdk.internal.dynalink.linker.GuardedTypeConversion;
    12.8  import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
    12.9  import jdk.internal.dynalink.linker.LinkRequest;
   12.10  import jdk.internal.dynalink.linker.LinkerServices;
   12.11 @@ -79,7 +80,7 @@
   12.12      }
   12.13  
   12.14      @Override
   12.15 -    public GuardedInvocation convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception {
   12.16 +    public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception {
   12.17          final boolean sourceIsAlwaysJSObject = JSObject.class.isAssignableFrom(sourceType);
   12.18          if(!sourceIsAlwaysJSObject && !sourceType.isAssignableFrom(JSObject.class)) {
   12.19              return null;
   12.20 @@ -90,7 +91,7 @@
   12.21              return null;
   12.22          }
   12.23  
   12.24 -        return new GuardedInvocation(converter, sourceIsAlwaysJSObject ? null : IS_JSOBJECT_GUARD).asType(MethodType.methodType(targetType, sourceType));
   12.25 +        return new GuardedTypeConversion(new GuardedInvocation(converter, sourceIsAlwaysJSObject ? null : IS_JSOBJECT_GUARD).asType(MethodType.methodType(targetType, sourceType)), true);
   12.26      }
   12.27  
   12.28  
    13.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Thu Jan 30 19:45:20 2014 +0530
    13.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Thu Jan 30 20:14:29 2014 +0100
    13.3 @@ -59,6 +59,7 @@
    13.4  import java.util.List;
    13.5  import java.util.Set;
    13.6  import jdk.internal.org.objectweb.asm.ClassWriter;
    13.7 +import jdk.internal.org.objectweb.asm.Handle;
    13.8  import jdk.internal.org.objectweb.asm.Label;
    13.9  import jdk.internal.org.objectweb.asm.Opcodes;
   13.10  import jdk.internal.org.objectweb.asm.Type;
   13.11 @@ -66,21 +67,23 @@
   13.12  import jdk.nashorn.internal.runtime.Context;
   13.13  import jdk.nashorn.internal.runtime.ScriptFunction;
   13.14  import jdk.nashorn.internal.runtime.ScriptObject;
   13.15 +import jdk.nashorn.internal.runtime.linker.AdaptationResult.Outcome;
   13.16  import sun.reflect.CallerSensitive;
   13.17  
   13.18  /**
   13.19   * Generates bytecode for a Java adapter class. Used by the {@link JavaAdapterFactory}.
   13.20   * </p><p>
   13.21 - * For every protected or public constructor in the extended class, the adapter class will have between one to three
   13.22 + * For every protected or public constructor in the extended class, the adapter class will have either one or two
   13.23   * public constructors (visibility of protected constructors in the extended class is promoted to public).
   13.24 - * <ul>
   13.25 - * <li>In every case, a constructor taking a trailing ScriptObject argument preceded by original constructor arguments
   13.26 - * is always created on the adapter class. When such a constructor is invoked, the passed ScriptObject's member
   13.27 - * functions are used to implement and/or override methods on the original class, dispatched by name. A single
   13.28 - * JavaScript function will act as the implementation for all overloaded methods of the same name. When methods on an
   13.29 - * adapter instance are invoked, the functions are invoked having the ScriptObject passed in the instance constructor as
   13.30 - * their "this". Subsequent changes to the ScriptObject (reassignment or removal of its functions) are not reflected in
   13.31 - * the adapter instance; the method implementations are bound to functions at constructor invocation time.
   13.32 + * <li>
   13.33 + * <li>For adapter classes with instance-level overrides, a constructor taking a trailing ScriptObject argument preceded
   13.34 + * by original constructor arguments is always created on the adapter class. When such a constructor is invoked, the
   13.35 + * passed ScriptObject's member functions are used to implement and/or override methods on the original class,
   13.36 + * dispatched by name. A single JavaScript function will act as the implementation for all overloaded methods of the
   13.37 + * same name. When methods on an adapter instance are invoked, the functions are invoked having the ScriptObject passed
   13.38 + * in the instance constructor as their "this". Subsequent changes to the ScriptObject (reassignment or removal of its
   13.39 + * functions) are not reflected in the adapter instance; the method implementations are bound to functions at
   13.40 + * constructor invocation time.
   13.41   * {@code java.lang.Object} methods {@code equals}, {@code hashCode}, and {@code toString} can also be overridden. The
   13.42   * only restriction is that since every JavaScript object already has a {@code toString} function through the
   13.43   * {@code Object.prototype}, the {@code toString} in the adapter is only overridden if the passed ScriptObject has a
   13.44 @@ -89,16 +92,17 @@
   13.45   * </li>
   13.46   * <li>
   13.47   * If the original types collectively have only one abstract method, or have several of them, but all share the
   13.48 - * same name, an additional constructor is provided for every original constructor; this one takes a ScriptFunction as
   13.49 - * its last argument preceded by original constructor arguments. This constructor will use the passed function as the
   13.50 - * implementation for all abstract methods. For consistency, any concrete methods sharing the single abstract method
   13.51 - * name will also be overridden by the function. When methods on the adapter instance are invoked, the ScriptFunction is
   13.52 - * invoked with global or UNDEFINED as its "this" depending whether the function is non-strict or not.
   13.53 + * same name, an additional constructor for instance-level override adapter is provided for every original constructor;
   13.54 + * this one takes a ScriptFunction as its last argument preceded by original constructor arguments. This constructor
   13.55 + * will use the passed function as the implementation for all abstract methods. For consistency, any concrete methods
   13.56 + * sharing the single abstract method name will also be overridden by the function. When methods on the adapter instance
   13.57 + * are invoked, the ScriptFunction is invoked with UNDEFINED or Global as its "this" depending whether the function is
   13.58 + * strict or not.
   13.59   * </li>
   13.60   * <li>
   13.61   * If the adapter being generated can have class-level overrides, constructors taking same arguments as the superclass
   13.62 - * constructors are also created. These constructors simply delegate to the superclass constructor. They are used to
   13.63 - * create instances of the adapter class with no instance-level overrides.
   13.64 + * constructors are created. These constructors simply delegate to the superclass constructor. They are simply used to
   13.65 + * create instances of the adapter class, with no instance-level overrides, as they don't have them.
   13.66   * </li>
   13.67   * </ul>
   13.68   * </p><p>
   13.69 @@ -111,16 +115,20 @@
   13.70   * source-level script expression <code>new X(a, b) { ... }</code> (which is a proprietary syntax extension Nashorn uses
   13.71   * to resemble Java anonymous classes) is actually equivalent to <code>new X(a, b, { ... })</code>.
   13.72   * </p><p>
   13.73 - * It is possible to create two different classes: those that can have both class-level and instance-level overrides,
   13.74 - * and those that can only have instance-level overrides. When
   13.75 - * {@link JavaAdapterFactory#getAdapterClassFor(Class[], ScriptObject)} is invoked with non-null {@code classOverrides}
   13.76 - * parameter, an adapter class is created that can have class-level overrides, and the passed script object will be used
   13.77 - * as the implementations for its methods, just as in the above case of the constructor taking a script object. Note
   13.78 - * that in the case of class-level overrides, a new adapter class is created on every invocation, and the implementation
   13.79 - * object is bound to the class, not to any instance. All created instances will share these functions. Of course, when
   13.80 - * instances of such a class are being created, they can still take another object (or possibly a function) in their
   13.81 - * constructor's trailing position and thus provide further instance-specific overrides. The order of invocation is
   13.82 - * always instance-specified method, then a class-specified method, and finally the superclass method.
   13.83 + * It is possible to create two different adapter classes: those that can have class-level overrides, and those that can
   13.84 + * have instance-level overrides. When {@link JavaAdapterFactory#getAdapterClassFor(Class[], ScriptObject)} is invoked
   13.85 + * with non-null {@code classOverrides} parameter, an adapter class is created that can have class-level overrides, and
   13.86 + * the passed script object will be used as the implementations for its methods, just as in the above case of the
   13.87 + * constructor taking a script object. Note that in the case of class-level overrides, a new adapter class is created on
   13.88 + * every invocation, and the implementation object is bound to the class, not to any instance. All created instances
   13.89 + * will share these functions. If it is required to have both class-level overrides and instance-level overrides, the
   13.90 + * class-level override adapter class should be subclassed with an instance-override adapter. Since adapters delegate to
   13.91 + * super class when an overriding method handle is not specified, this will behave as expected. It is not possible to
   13.92 + * have both class-level and instance-level overrides in the same class for security reasons: adapter classes are
   13.93 + * defined with a protection domain of their creator code, and an adapter class that has both class and instance level
   13.94 + * overrides would need to have two potentially different protection domains: one for class-based behavior and one for
   13.95 + * instance-based behavior; since Java classes can only belong to a single protection domain, this could not be
   13.96 + * implemented securely.
   13.97   */
   13.98  final class JavaAdapterBytecodeGenerator {
   13.99      static final Type CONTEXT_TYPE       = Type.getType(Context.class);
  13.100 @@ -171,7 +179,6 @@
  13.101      private static final int MAX_GENERATED_TYPE_NAME_LENGTH = 255;
  13.102  
  13.103      private static final String CLASS_INIT = "<clinit>";
  13.104 -    private static final String STATIC_GLOBAL_FIELD_NAME = "staticGlobal";
  13.105  
  13.106      // Method name prefix for invoking super-methods
  13.107      static final String SUPER_PREFIX = "super$";
  13.108 @@ -199,6 +206,7 @@
  13.109      private final Set<MethodInfo> finalMethods = new HashSet<>(EXCLUDED);
  13.110      private final Set<MethodInfo> methodInfos = new HashSet<>();
  13.111      private boolean autoConvertibleFromFunction = false;
  13.112 +    private boolean hasExplicitFinalizer = false;
  13.113  
  13.114      private final ClassWriter cw;
  13.115  
  13.116 @@ -207,8 +215,8 @@
  13.117       * @param superClass the superclass the adapter will extend.
  13.118       * @param interfaces the interfaces the adapter will implement.
  13.119       * @param commonLoader the class loader that can see all of superClass, interfaces, and Nashorn classes.
  13.120 -     * @param classOverride true to generate the bytecode for the adapter that has both class-level and instance-level
  13.121 -     * overrides, false to generate the bytecode for the adapter that only has instance-level overrides.
  13.122 +     * @param classOverride true to generate the bytecode for the adapter that has class-level overrides, false to
  13.123 +     * generate the bytecode for the adapter that has instance-level overrides.
  13.124       * @throws AdaptationException if the adapter can not be generated for some reason.
  13.125       */
  13.126      JavaAdapterBytecodeGenerator(final Class<?> superClass, final List<Class<?>> interfaces,
  13.127 @@ -230,8 +238,7 @@
  13.128          superClassName = Type.getInternalName(superClass);
  13.129          generatedClassName = getGeneratedClassName(superClass, interfaces);
  13.130  
  13.131 -        cw.visit(Opcodes.V1_7, ACC_PUBLIC | ACC_SUPER | ACC_FINAL, generatedClassName, null, superClassName, getInternalTypeNames(interfaces));
  13.132 -
  13.133 +        cw.visit(Opcodes.V1_7, ACC_PUBLIC | ACC_SUPER, generatedClassName, null, superClassName, getInternalTypeNames(interfaces));
  13.134          generateGlobalFields();
  13.135  
  13.136          gatherMethods(superClass);
  13.137 @@ -244,17 +251,16 @@
  13.138          generateConstructors();
  13.139          generateMethods();
  13.140          generateSuperMethods();
  13.141 +        if (hasExplicitFinalizer) {
  13.142 +            generateFinalizerMethods();
  13.143 +        }
  13.144          // }
  13.145          cw.visitEnd();
  13.146      }
  13.147  
  13.148      private void generateGlobalFields() {
  13.149 -        cw.visitField(ACC_PRIVATE | ACC_FINAL, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR, null, null).visitEnd();
  13.150 +        cw.visitField(ACC_PRIVATE | ACC_FINAL | (classOverride ? ACC_STATIC : 0), GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR, null, null).visitEnd();
  13.151          usedFieldNames.add(GLOBAL_FIELD_NAME);
  13.152 -        if(classOverride) {
  13.153 -            cw.visitField(ACC_PRIVATE | ACC_FINAL | ACC_STATIC, STATIC_GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR, null, null).visitEnd();
  13.154 -            usedFieldNames.add(STATIC_GLOBAL_FIELD_NAME);
  13.155 -        }
  13.156      }
  13.157  
  13.158      JavaAdapterClassLoader createAdapterClassLoader() {
  13.159 @@ -305,11 +311,9 @@
  13.160      }
  13.161  
  13.162      private void generateHandleFields() {
  13.163 +        final int flags = ACC_PRIVATE | ACC_FINAL | (classOverride ? ACC_STATIC : 0);
  13.164          for (final MethodInfo mi: methodInfos) {
  13.165 -            cw.visitField(ACC_PRIVATE | ACC_FINAL, mi.methodHandleInstanceFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR, null, null).visitEnd();
  13.166 -            if(classOverride) {
  13.167 -                cw.visitField(ACC_PRIVATE | ACC_FINAL | ACC_STATIC, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR, null, null).visitEnd();
  13.168 -            }
  13.169 +            cw.visitField(flags, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR, null, null).visitEnd();
  13.170          }
  13.171      }
  13.172  
  13.173 @@ -337,7 +341,7 @@
  13.174                  } else {
  13.175                      mv.visitInsn(ACONST_NULL);
  13.176                  }
  13.177 -                mv.putstatic(generatedClassName, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
  13.178 +                mv.putstatic(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
  13.179              }
  13.180              initGlobal = new Label();
  13.181              mv.goTo(initGlobal);
  13.182 @@ -351,15 +355,15 @@
  13.183              mv.aconst(mi.getName());
  13.184              mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
  13.185              mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_OBJECT_DESCRIPTOR);
  13.186 -            mv.putstatic(generatedClassName, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
  13.187 +            mv.putstatic(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
  13.188          }
  13.189  
  13.190          if(initGlobal != null) {
  13.191              mv.visitLabel(initGlobal);
  13.192          }
  13.193 -        // Assign "staticGlobal = Context.getGlobal()"
  13.194 +        // Assign "global = Context.getGlobal()"
  13.195          invokeGetGlobalWithNullCheck(mv);
  13.196 -        mv.putstatic(generatedClassName, STATIC_GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
  13.197 +        mv.putstatic(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
  13.198  
  13.199          endInitMethod(mv);
  13.200      }
  13.201 @@ -390,21 +394,21 @@
  13.202              // Generate a constructor that just delegates to ctor. This is used with class-level overrides, when we want
  13.203              // to create instances without further per-instance overrides.
  13.204              generateDelegatingConstructor(ctor);
  13.205 -        }
  13.206 +        } else {
  13.207 +            // Generate a constructor that delegates to ctor, but takes an additional ScriptObject parameter at the
  13.208 +            // beginning of its parameter list.
  13.209 +            generateOverridingConstructor(ctor, false);
  13.210  
  13.211 -        // Generate a constructor that delegates to ctor, but takes an additional ScriptObject parameter at the
  13.212 -        // beginning of its parameter list.
  13.213 -        generateOverridingConstructor(ctor, false);
  13.214 -
  13.215 -        if (samName != null) {
  13.216 -            if (!autoConvertibleFromFunction && ctor.getParameterTypes().length == 0) {
  13.217 -                // If the original type only has a single abstract method name, as well as a default ctor, then it can
  13.218 -                // be automatically converted from JS function.
  13.219 -                autoConvertibleFromFunction = true;
  13.220 +            if (samName != null) {
  13.221 +                if (!autoConvertibleFromFunction && ctor.getParameterTypes().length == 0) {
  13.222 +                    // If the original type only has a single abstract method name, as well as a default ctor, then it can
  13.223 +                    // be automatically converted from JS function.
  13.224 +                    autoConvertibleFromFunction = true;
  13.225 +                }
  13.226 +                // If all our abstract methods have a single name, generate an additional constructor, one that takes a
  13.227 +                // ScriptFunction as its first parameter and assigns it as the implementation for all abstract methods.
  13.228 +                generateOverridingConstructor(ctor, true);
  13.229              }
  13.230 -            // If all our abstract methods have a single name, generate an additional constructor, one that takes a
  13.231 -            // ScriptFunction as its first parameter and assigns it as the implementation for all abstract methods.
  13.232 -            generateOverridingConstructor(ctor, true);
  13.233          }
  13.234      }
  13.235  
  13.236 @@ -430,7 +434,7 @@
  13.237      }
  13.238  
  13.239      /**
  13.240 -     * Generates a constructor for the adapter class. This constructor will take the same arguments as the supertype
  13.241 +     * Generates a constructor for the instance adapter class. This constructor will take the same arguments as the supertype
  13.242       * constructor passed as the argument here, and delegate to it. However, it will take an additional argument of
  13.243       * either ScriptObject or ScriptFunction type (based on the value of the "fromFunction" parameter), and initialize
  13.244       * all the method handle fields of the adapter instance with functions from the script object (or the script
  13.245 @@ -498,7 +502,7 @@
  13.246                  mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
  13.247                  mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", getHandleDescriptor);
  13.248              }
  13.249 -            mv.putfield(generatedClassName, mi.methodHandleInstanceFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
  13.250 +            mv.putfield(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
  13.251          }
  13.252  
  13.253          // Assign "this.global = Context.getGlobal()"
  13.254 @@ -536,8 +540,7 @@
  13.255      private static class MethodInfo {
  13.256          private final Method method;
  13.257          private final MethodType type;
  13.258 -        private String methodHandleInstanceFieldName;
  13.259 -        private String methodHandleClassFieldName;
  13.260 +        private String methodHandleFieldName;
  13.261  
  13.262          private MethodInfo(final Class<?> clazz, final String name, final Class<?>... argTypes) throws NoSuchMethodException {
  13.263              this(clazz.getDeclaredMethod(name, argTypes));
  13.264 @@ -567,25 +570,20 @@
  13.265              return getName().hashCode() ^ type.hashCode();
  13.266          }
  13.267  
  13.268 -        void setIsCanonical(final Set<String> usedFieldNames, boolean classOverride) {
  13.269 -            methodHandleInstanceFieldName = nextName(usedFieldNames);
  13.270 -            if(classOverride) {
  13.271 -                methodHandleClassFieldName = nextName(usedFieldNames);
  13.272 -            }
  13.273 +        void setIsCanonical(final JavaAdapterBytecodeGenerator self) {
  13.274 +            methodHandleFieldName = self.nextName(getName());
  13.275          }
  13.276 +    }
  13.277  
  13.278 -        String nextName(final Set<String> usedFieldNames) {
  13.279 -            int i = 0;
  13.280 -            final String name = getName();
  13.281 -            String nextName = name;
  13.282 -            while (!usedFieldNames.add(nextName)) {
  13.283 -                final String ordinal = String.valueOf(i++);
  13.284 -                final int maxNameLen = 255 - ordinal.length();
  13.285 -                nextName = (name.length() <= maxNameLen ? name : name.substring(0, maxNameLen)).concat(ordinal);
  13.286 -            }
  13.287 -            return nextName;
  13.288 +    private String nextName(final String name) {
  13.289 +        int i = 0;
  13.290 +        String nextName = name;
  13.291 +        while (!usedFieldNames.add(nextName)) {
  13.292 +            final String ordinal = String.valueOf(i++);
  13.293 +            final int maxNameLen = 255 - ordinal.length();
  13.294 +            nextName = (name.length() <= maxNameLen ? name : name.substring(0, maxNameLen)).concat(ordinal);
  13.295          }
  13.296 -
  13.297 +        return nextName;
  13.298      }
  13.299  
  13.300      private void generateMethods() {
  13.301 @@ -624,23 +622,19 @@
  13.302                  methodDesc, null, exceptionNames));
  13.303          mv.visitCode();
  13.304  
  13.305 -        final Label instanceHandleDefined = new Label();
  13.306 -        final Label classHandleDefined = new Label();
  13.307 +        final Label handleDefined = new Label();
  13.308  
  13.309          final Type asmReturnType = Type.getType(type.returnType());
  13.310  
  13.311 -        // See if we have instance handle defined
  13.312 -        mv.visitVarInsn(ALOAD, 0);
  13.313 -        mv.getfield(generatedClassName, mi.methodHandleInstanceFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
  13.314 -        // stack: [instanceHandle]
  13.315 -        jumpIfNonNullKeepOperand(mv, instanceHandleDefined);
  13.316 -
  13.317 +        // See if we have overriding method handle defined
  13.318          if(classOverride) {
  13.319 -            // See if we have the static handle
  13.320 -            mv.getstatic(generatedClassName, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
  13.321 -            // stack: [classHandle]
  13.322 -            jumpIfNonNullKeepOperand(mv, classHandleDefined);
  13.323 +            mv.getstatic(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
  13.324 +        } else {
  13.325 +            mv.visitVarInsn(ALOAD, 0);
  13.326 +            mv.getfield(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
  13.327          }
  13.328 +        // stack: [handle]
  13.329 +        jumpIfNonNullKeepOperand(mv, handleDefined);
  13.330  
  13.331          // No handle is available, fall back to default behavior
  13.332          if(Modifier.isAbstract(method.getModifiers())) {
  13.333 @@ -654,25 +648,17 @@
  13.334              emitSuperCall(mv, name, methodDesc);
  13.335          }
  13.336  
  13.337 +        mv.visitLabel(handleDefined);
  13.338 +        // Load the creatingGlobal object
  13.339 +        if(classOverride) {
  13.340 +            // If class handle is defined, load the static defining global
  13.341 +            mv.getstatic(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
  13.342 +        } else {
  13.343 +            mv.visitVarInsn(ALOAD, 0);
  13.344 +            mv.getfield(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
  13.345 +        }
  13.346 +        // stack: [creatingGlobal, handle]
  13.347          final Label setupGlobal = new Label();
  13.348 -
  13.349 -        if(classOverride) {
  13.350 -            mv.visitLabel(classHandleDefined);
  13.351 -            // If class handle is defined, load the static defining global
  13.352 -            mv.getstatic(generatedClassName, STATIC_GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
  13.353 -            // stack: [creatingGlobal := classGlobal, classHandle]
  13.354 -            mv.goTo(setupGlobal);
  13.355 -        }
  13.356 -
  13.357 -        mv.visitLabel(instanceHandleDefined);
  13.358 -        // If instance handle is defined, load the instance defining global
  13.359 -        mv.visitVarInsn(ALOAD, 0);
  13.360 -        mv.getfield(generatedClassName, GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
  13.361 -        // stack: [creatingGlobal := instanceGlobal, instanceHandle]
  13.362 -
  13.363 -        // fallthrough to setupGlobal
  13.364 -
  13.365 -        // stack: [creatingGlobal, someHandle]
  13.366          mv.visitLabel(setupGlobal);
  13.367  
  13.368          // Determine the first index for a local variable
  13.369 @@ -685,38 +671,39 @@
  13.370          final int globalsDifferVar  = nextLocalVar++;
  13.371  
  13.372          mv.dup();
  13.373 -        // stack: [creatingGlobal, creatingGlobal, someHandle]
  13.374 +        // stack: [creatingGlobal, creatingGlobal, handle]
  13.375  
  13.376          // Emit code for switching to the creating global
  13.377          // ScriptObject currentGlobal = Context.getGlobal();
  13.378          invokeGetGlobal(mv);
  13.379          mv.dup();
  13.380 +
  13.381          mv.visitVarInsn(ASTORE, currentGlobalVar);
  13.382 -        // stack: [currentGlobal, creatingGlobal, creatingGlobal, someHandle]
  13.383 +        // stack: [currentGlobal, creatingGlobal, creatingGlobal, handle]
  13.384          // if(definingGlobal == currentGlobal) {
  13.385          final Label globalsDiffer = new Label();
  13.386          mv.ifacmpne(globalsDiffer);
  13.387 -        // stack: [someGlobal, someHandle]
  13.388 +        // stack: [creatingGlobal, handle]
  13.389          //     globalsDiffer = false
  13.390          mv.pop();
  13.391 -        // stack: [someHandle]
  13.392 +        // stack: [handle]
  13.393          mv.iconst(0); // false
  13.394 -        // stack: [false, someHandle]
  13.395 +        // stack: [false, handle]
  13.396          final Label invokeHandle = new Label();
  13.397          mv.goTo(invokeHandle);
  13.398          mv.visitLabel(globalsDiffer);
  13.399          // } else {
  13.400          //     Context.setGlobal(definingGlobal);
  13.401 -        // stack: [someGlobal, someHandle]
  13.402 +        // stack: [creatingGlobal, handle]
  13.403          invokeSetGlobal(mv);
  13.404 -        // stack: [someHandle]
  13.405 +        // stack: [handle]
  13.406          //     globalsDiffer = true
  13.407          mv.iconst(1);
  13.408 -        // stack: [true, someHandle]
  13.409 +        // stack: [true, handle]
  13.410  
  13.411          mv.visitLabel(invokeHandle);
  13.412          mv.visitVarInsn(ISTORE, globalsDifferVar);
  13.413 -        // stack: [someHandle]
  13.414 +        // stack: [handle]
  13.415  
  13.416          // Load all parameters back on stack for dynamic invocation.
  13.417          int varOffset = 1;
  13.418 @@ -847,6 +834,42 @@
  13.419          mv.areturn(methodType.getReturnType());
  13.420      }
  13.421  
  13.422 +    private void generateFinalizerMethods() {
  13.423 +        final String finalizerDelegateName = nextName("access$");
  13.424 +        generateFinalizerDelegate(finalizerDelegateName);
  13.425 +        generateFinalizerOverride(finalizerDelegateName);
  13.426 +    }
  13.427 +
  13.428 +    private void generateFinalizerDelegate(final String finalizerDelegateName) {
  13.429 +        // Generate a delegate that will be invoked from the no-permission trampoline. Note it can be private, as we'll
  13.430 +        // refer to it with a MethodHandle constant pool entry in the overridden finalize() method (see
  13.431 +        // generateFinalizerOverride()).
  13.432 +        final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PRIVATE | ACC_STATIC,
  13.433 +                finalizerDelegateName, Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE), null, null));
  13.434 +
  13.435 +        // Simply invoke super.finalize()
  13.436 +        mv.visitVarInsn(ALOAD, 0);
  13.437 +        mv.checkcast(Type.getType(generatedClassName));
  13.438 +        mv.invokespecial(superClassName, "finalize", Type.getMethodDescriptor(Type.VOID_TYPE), false);
  13.439 +
  13.440 +        mv.visitInsn(RETURN);
  13.441 +        endMethod(mv);
  13.442 +    }
  13.443 +
  13.444 +    private void generateFinalizerOverride(final String finalizerDelegateName) {
  13.445 +        final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, "finalize",
  13.446 +                VOID_NOARG_METHOD_DESCRIPTOR, null, null));
  13.447 +        // Overridden finalizer will take a MethodHandle to the finalizer delegating method, ...
  13.448 +        mv.aconst(new Handle(Opcodes.H_INVOKESTATIC, generatedClassName, finalizerDelegateName,
  13.449 +                Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE)));
  13.450 +        mv.visitVarInsn(ALOAD, 0);
  13.451 +        // ...and invoke it through JavaAdapterServices.invokeNoPermissions
  13.452 +        mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "invokeNoPermissions",
  13.453 +                Type.getMethodDescriptor(METHOD_HANDLE_TYPE, OBJECT_TYPE), false);
  13.454 +        mv.visitInsn(RETURN);
  13.455 +        endMethod(mv);
  13.456 +    }
  13.457 +
  13.458      private static String[] getExceptionNames(final Class<?>[] exceptions) {
  13.459          final String[] exceptionNames = new String[exceptions.length];
  13.460          for (int i = 0; i < exceptions.length; ++i) {
  13.461 @@ -867,16 +890,32 @@
  13.462       * class.
  13.463       * @param type the type defining the methods.
  13.464       */
  13.465 -    private void gatherMethods(final Class<?> type) {
  13.466 +    private void gatherMethods(final Class<?> type) throws AdaptationException {
  13.467          if (Modifier.isPublic(type.getModifiers())) {
  13.468              final Method[] typeMethods = type.isInterface() ? type.getMethods() : type.getDeclaredMethods();
  13.469  
  13.470              for (final Method typeMethod: typeMethods) {
  13.471 +                final String name = typeMethod.getName();
  13.472 +                if(name.startsWith(SUPER_PREFIX)) {
  13.473 +                    continue;
  13.474 +                }
  13.475                  final int m = typeMethod.getModifiers();
  13.476                  if (Modifier.isStatic(m)) {
  13.477                      continue;
  13.478                  }
  13.479                  if (Modifier.isPublic(m) || Modifier.isProtected(m)) {
  13.480 +                    // Is it a "finalize()"?
  13.481 +                    if(name.equals("finalize") && typeMethod.getParameterCount() == 0) {
  13.482 +                        if(type != Object.class) {
  13.483 +                            hasExplicitFinalizer = true;
  13.484 +                            if(Modifier.isFinal(m)) {
  13.485 +                                // Must be able to override an explicit finalizer
  13.486 +                                throw new AdaptationException(Outcome.ERROR_FINAL_FINALIZER, type.getCanonicalName());
  13.487 +                            }
  13.488 +                        }
  13.489 +                        continue;
  13.490 +                    }
  13.491 +
  13.492                      final MethodInfo mi = new MethodInfo(typeMethod);
  13.493                      if (Modifier.isFinal(m) || isCallerSensitive(typeMethod)) {
  13.494                          finalMethods.add(mi);
  13.495 @@ -884,7 +923,7 @@
  13.496                          if (Modifier.isAbstract(m)) {
  13.497                              abstractMethodNames.add(mi.getName());
  13.498                          }
  13.499 -                        mi.setIsCanonical(usedFieldNames, classOverride);
  13.500 +                        mi.setIsCanonical(this);
  13.501                      }
  13.502                  }
  13.503              }
  13.504 @@ -905,7 +944,7 @@
  13.505          }
  13.506      }
  13.507  
  13.508 -    private void gatherMethods(final List<Class<?>> classes) {
  13.509 +    private void gatherMethods(final List<Class<?>> classes) throws AdaptationException {
  13.510          for(final Class<?> c: classes) {
  13.511              gatherMethods(c);
  13.512          }
    14.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java	Thu Jan 30 19:45:20 2014 +0530
    14.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java	Thu Jan 30 20:14:29 2014 +0100
    14.3 @@ -27,10 +27,6 @@
    14.4  
    14.5  import java.security.AccessControlContext;
    14.6  import java.security.AccessController;
    14.7 -import java.security.AllPermission;
    14.8 -import java.security.CodeSigner;
    14.9 -import java.security.CodeSource;
   14.10 -import java.security.Permissions;
   14.11  import java.security.PrivilegedAction;
   14.12  import java.security.ProtectionDomain;
   14.13  import java.security.SecureClassLoader;
   14.14 @@ -45,11 +41,10 @@
   14.15   */
   14.16  @SuppressWarnings("javadoc")
   14.17  final class JavaAdapterClassLoader {
   14.18 -    private static final ProtectionDomain GENERATED_PROTECTION_DOMAIN = createGeneratedProtectionDomain();
   14.19      private static final AccessControlContext CREATE_LOADER_ACC_CTXT = ClassAndLoader.createPermAccCtxt("createClassLoader");
   14.20  
   14.21      private final String className;
   14.22 -    private volatile byte[] classBytes;
   14.23 +    private final byte[] classBytes;
   14.24  
   14.25      JavaAdapterClassLoader(String className, byte[] classBytes) {
   14.26          this.className = className.replace('/', '.');
   14.27 @@ -57,23 +52,18 @@
   14.28      }
   14.29  
   14.30      /**
   14.31 -     * clear classBytes after loading class.
   14.32 -     */
   14.33 -    void clearClassBytes() {
   14.34 -       this.classBytes = null;
   14.35 -    }
   14.36 -
   14.37 -    /**
   14.38       * Loads the generated adapter class into the JVM.
   14.39       * @param parentLoader the parent class loader for the generated class loader
   14.40 +     * @param protectionDomain the protection domain for the generated class
   14.41       * @return the generated adapter class
   14.42       */
   14.43 -    StaticClass generateClass(final ClassLoader parentLoader) {
   14.44 +    StaticClass generateClass(final ClassLoader parentLoader, final ProtectionDomain protectionDomain) {
   14.45 +        assert protectionDomain != null;
   14.46          return AccessController.doPrivileged(new PrivilegedAction<StaticClass>() {
   14.47              @Override
   14.48              public StaticClass run() {
   14.49                  try {
   14.50 -                    return StaticClass.forClass(Class.forName(className, true, createClassLoader(parentLoader)));
   14.51 +                    return StaticClass.forClass(Class.forName(className, true, createClassLoader(parentLoader, protectionDomain)));
   14.52                  } catch (final ClassNotFoundException e) {
   14.53                      throw new AssertionError(e); // cannot happen
   14.54                  }
   14.55 @@ -88,7 +78,7 @@
   14.56      // it even more by separating its invocation into a separate static method on the adapter class, but then someone
   14.57      // with ability to introspect on the class and use setAccessible(true) on it could invoke the method. It's a
   14.58      // security tradeoff...
   14.59 -    private ClassLoader createClassLoader(final ClassLoader parentLoader) {
   14.60 +    private ClassLoader createClassLoader(final ClassLoader parentLoader, final ProtectionDomain protectionDomain) {
   14.61          return new SecureClassLoader(parentLoader) {
   14.62              private final ClassLoader myLoader = getClass().getClassLoader();
   14.63  
   14.64 @@ -112,21 +102,10 @@
   14.65              protected Class<?> findClass(final String name) throws ClassNotFoundException {
   14.66                  if(name.equals(className)) {
   14.67                      assert classBytes != null : "what? already cleared .class bytes!!";
   14.68 -                    return defineClass(name, classBytes, 0, classBytes.length, GENERATED_PROTECTION_DOMAIN);
   14.69 +                    return defineClass(name, classBytes, 0, classBytes.length, protectionDomain);
   14.70                  }
   14.71                  throw new ClassNotFoundException(name);
   14.72              }
   14.73          };
   14.74      }
   14.75 -
   14.76 -    private static ProtectionDomain createGeneratedProtectionDomain() {
   14.77 -        // Generated classes need to have AllPermission. Since we require the "createClassLoader" RuntimePermission, we
   14.78 -        // can create a class loader that'll load new classes with any permissions. Our generated classes are just
   14.79 -        // delegating adapters, so having AllPermission can't cause anything wrong; the effective set of permissions for
   14.80 -        // the executing script functions will still be limited by the permissions of the caller and the permissions of
   14.81 -        // the script.
   14.82 -        final Permissions permissions = new Permissions();
   14.83 -        permissions.add(new AllPermission());
   14.84 -        return new ProtectionDomain(new CodeSource(null, (CodeSigner[])null), permissions);
   14.85 -    }
   14.86  }
    15.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java	Thu Jan 30 19:45:20 2014 +0530
    15.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java	Thu Jan 30 20:14:29 2014 +0100
    15.3 @@ -29,17 +29,23 @@
    15.4  
    15.5  import java.lang.invoke.MethodHandle;
    15.6  import java.lang.invoke.MethodHandles;
    15.7 +import java.lang.invoke.MethodHandles.Lookup;
    15.8  import java.lang.invoke.MethodType;
    15.9  import java.lang.reflect.Modifier;
   15.10  import java.security.AccessControlContext;
   15.11  import java.security.AccessController;
   15.12 +import java.security.CodeSigner;
   15.13 +import java.security.CodeSource;
   15.14 +import java.security.Permissions;
   15.15  import java.security.PrivilegedAction;
   15.16 +import java.security.ProtectionDomain;
   15.17  import java.util.ArrayList;
   15.18  import java.util.Arrays;
   15.19  import java.util.Collections;
   15.20  import java.util.HashMap;
   15.21  import java.util.List;
   15.22  import java.util.Map;
   15.23 +import java.util.concurrent.ConcurrentHashMap;
   15.24  import jdk.internal.dynalink.beans.StaticClass;
   15.25  import jdk.internal.dynalink.support.LinkRequestImpl;
   15.26  import jdk.nashorn.internal.objects.NativeJava;
   15.27 @@ -70,6 +76,8 @@
   15.28  
   15.29  @SuppressWarnings("javadoc")
   15.30  public final class JavaAdapterFactory {
   15.31 +    private static final ProtectionDomain MINIMAL_PERMISSION_DOMAIN = createMinimalPermissionDomain();
   15.32 +
   15.33      // context with permissions needs for AdapterInfo creation
   15.34      private static final AccessControlContext CREATE_ADAPTER_INFO_ACC_CTXT =
   15.35          ClassAndLoader.createPermAccCtxt("createClassLoader", "getClassLoader",
   15.36 @@ -99,11 +107,18 @@
   15.37       * @param classOverrides a JavaScript object with functions serving as the class-level overrides and
   15.38       * implementations. These overrides are defined for all instances of the class, and can be further overridden on a
   15.39       * per-instance basis by passing additional objects in the constructor.
   15.40 +     * @param lookup the lookup object identifying the caller class. The generated adapter class will have the
   15.41 +     * protection domain of the caller class iff the lookup object is full-strength, otherwise it will be completely
   15.42 +     * unprivileged.
   15.43       * @return an adapter class. See this class' documentation for details on the generated adapter class.
   15.44       * @throws ECMAException with a TypeError if the adapter class can not be generated because the original class is
   15.45       * final, non-public, or has no public or protected constructors.
   15.46       */
   15.47 -    public static StaticClass getAdapterClassFor(final Class<?>[] types, ScriptObject classOverrides) {
   15.48 +    public static StaticClass getAdapterClassFor(final Class<?>[] types, ScriptObject classOverrides, final MethodHandles.Lookup lookup) {
   15.49 +        return getAdapterClassFor(types, classOverrides, getProtectionDomain(lookup));
   15.50 +    }
   15.51 +
   15.52 +    private static StaticClass getAdapterClassFor(final Class<?>[] types, ScriptObject classOverrides, final ProtectionDomain protectionDomain) {
   15.53          assert types != null && types.length > 0;
   15.54          final SecurityManager sm = System.getSecurityManager();
   15.55          if (sm != null) {
   15.56 @@ -114,7 +129,23 @@
   15.57                  ReflectionCheckLinker.checkReflectionAccess(type, true);
   15.58              }
   15.59          }
   15.60 -        return getAdapterInfo(types).getAdapterClassFor(classOverrides);
   15.61 +        return getAdapterInfo(types).getAdapterClass(classOverrides, protectionDomain);
   15.62 +    }
   15.63 +
   15.64 +    private static ProtectionDomain getProtectionDomain(final MethodHandles.Lookup lookup) {
   15.65 +        if((lookup.lookupModes() & Lookup.PRIVATE) == 0) {
   15.66 +            return MINIMAL_PERMISSION_DOMAIN;
   15.67 +        }
   15.68 +        return getProtectionDomain(lookup.lookupClass());
   15.69 +    }
   15.70 +
   15.71 +    private static ProtectionDomain getProtectionDomain(final Class<?> clazz) {
   15.72 +        return AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() {
   15.73 +            @Override
   15.74 +            public ProtectionDomain run() {
   15.75 +                return clazz.getProtectionDomain();
   15.76 +            }
   15.77 +        });
   15.78      }
   15.79  
   15.80      /**
   15.81 @@ -129,10 +160,10 @@
   15.82       * @return the constructor method handle.
   15.83       * @throws Exception if anything goes wrong
   15.84       */
   15.85 -    public static MethodHandle getConstructor(final Class<?> sourceType, final Class<?> targetType) throws Exception {
   15.86 -        final StaticClass adapterClass = getAdapterClassFor(new Class<?>[] { targetType }, null);
   15.87 +    public static MethodHandle getConstructor(final Class<?> sourceType, final Class<?> targetType, final MethodHandles.Lookup lookup) throws Exception {
   15.88 +        final StaticClass adapterClass = getAdapterClassFor(new Class<?>[] { targetType }, null, lookup);
   15.89          return MH.bindTo(Bootstrap.getLinkerServices().getGuardedInvocation(new LinkRequestImpl(
   15.90 -                NashornCallSiteDescriptor.get(MethodHandles.publicLookup(),  "dyn:new",
   15.91 +                NashornCallSiteDescriptor.get(lookup, "dyn:new",
   15.92                          MethodType.methodType(targetType, StaticClass.class, sourceType), 0), false,
   15.93                          adapterClass, null)).getInvocation(), adapterClass);
   15.94      }
   15.95 @@ -220,10 +251,10 @@
   15.96          private static final ClassAndLoader SCRIPT_OBJECT_LOADER = new ClassAndLoader(ScriptObject.class, true);
   15.97  
   15.98          private final ClassLoader commonLoader;
   15.99 -        private final JavaAdapterClassLoader adapterGenerator;
  15.100 -        // Cacheable adapter class that is shared by all adapter instances that don't have class overrides, only
  15.101 -        // instance overrides.
  15.102 -        final StaticClass instanceAdapterClass;
  15.103 +        // TODO: soft reference the JavaAdapterClassLoader objects. They can be recreated when needed.
  15.104 +        private final JavaAdapterClassLoader classAdapterGenerator;
  15.105 +        private final JavaAdapterClassLoader instanceAdapterGenerator;
  15.106 +        private final Map<CodeSource, StaticClass> instanceAdapters = new ConcurrentHashMap<>();
  15.107          final boolean autoConvertibleFromFunction;
  15.108          final AdaptationResult adaptationResult;
  15.109  
  15.110 @@ -231,11 +262,8 @@
  15.111              this.commonLoader = findCommonLoader(definingLoader);
  15.112              final JavaAdapterBytecodeGenerator gen = new JavaAdapterBytecodeGenerator(superClass, interfaces, commonLoader, false);
  15.113              this.autoConvertibleFromFunction = gen.isAutoConvertibleFromFunction();
  15.114 -            final JavaAdapterClassLoader jacl = gen.createAdapterClassLoader();
  15.115 -            this.instanceAdapterClass = jacl.generateClass(commonLoader);
  15.116 -            // loaded Class - no need to keep class bytes around
  15.117 -            jacl.clearClassBytes();
  15.118 -            this.adapterGenerator = new JavaAdapterBytecodeGenerator(superClass, interfaces, commonLoader, true).createAdapterClassLoader();
  15.119 +            instanceAdapterGenerator = gen.createAdapterClassLoader();
  15.120 +            this.classAdapterGenerator = new JavaAdapterBytecodeGenerator(superClass, interfaces, commonLoader, true).createAdapterClassLoader();
  15.121              this.adaptationResult = AdaptationResult.SUCCESSFUL_RESULT;
  15.122          }
  15.123  
  15.124 @@ -245,22 +273,42 @@
  15.125  
  15.126          AdapterInfo(final AdaptationResult adaptationResult) {
  15.127              this.commonLoader = null;
  15.128 -            this.adapterGenerator = null;
  15.129 -            this.instanceAdapterClass = null;
  15.130 +            this.classAdapterGenerator = null;
  15.131 +            this.instanceAdapterGenerator = null;
  15.132              this.autoConvertibleFromFunction = false;
  15.133              this.adaptationResult = adaptationResult;
  15.134          }
  15.135  
  15.136 -        StaticClass getAdapterClassFor(ScriptObject classOverrides) {
  15.137 +        StaticClass getAdapterClass(final ScriptObject classOverrides, final ProtectionDomain protectionDomain) {
  15.138              if(adaptationResult.getOutcome() != AdaptationResult.Outcome.SUCCESS) {
  15.139                  throw adaptationResult.typeError();
  15.140              }
  15.141 -            if(classOverrides == null) {
  15.142 +            return classOverrides == null ? getInstanceAdapterClass(protectionDomain) :
  15.143 +                getClassAdapterClass(classOverrides, protectionDomain);
  15.144 +        }
  15.145 +
  15.146 +        private StaticClass getInstanceAdapterClass(final ProtectionDomain protectionDomain) {
  15.147 +            CodeSource codeSource = protectionDomain.getCodeSource();
  15.148 +            if(codeSource == null) {
  15.149 +                codeSource = MINIMAL_PERMISSION_DOMAIN.getCodeSource();
  15.150 +            }
  15.151 +            StaticClass instanceAdapterClass = instanceAdapters.get(codeSource);
  15.152 +            if(instanceAdapterClass != null) {
  15.153                  return instanceAdapterClass;
  15.154              }
  15.155 +            // Any "unknown source" code source will default to no permission domain.
  15.156 +            final ProtectionDomain effectiveDomain = codeSource.equals(MINIMAL_PERMISSION_DOMAIN.getCodeSource()) ?
  15.157 +                    MINIMAL_PERMISSION_DOMAIN : protectionDomain;
  15.158 +
  15.159 +            instanceAdapterClass = instanceAdapterGenerator.generateClass(commonLoader, effectiveDomain);
  15.160 +            final StaticClass existing = instanceAdapters.putIfAbsent(codeSource, instanceAdapterClass);
  15.161 +            return existing == null ? instanceAdapterClass : existing;
  15.162 +        }
  15.163 +
  15.164 +        private StaticClass getClassAdapterClass(final ScriptObject classOverrides, final ProtectionDomain protectionDomain) {
  15.165              JavaAdapterServices.setClassOverrides(classOverrides);
  15.166              try {
  15.167 -                return adapterGenerator.generateClass(commonLoader);
  15.168 +                return classAdapterGenerator.generateClass(commonLoader, protectionDomain);
  15.169              } finally {
  15.170                  JavaAdapterServices.setClassOverrides(null);
  15.171              }
  15.172 @@ -285,4 +333,12 @@
  15.173              throw new AdaptationException(AdaptationResult.Outcome.ERROR_NO_COMMON_LOADER, classAndLoader.getRepresentativeClass().getCanonicalName());
  15.174          }
  15.175      }
  15.176 +
  15.177 +    private static ProtectionDomain createMinimalPermissionDomain() {
  15.178 +        // Generated classes need to have at least the permission to access Nashorn runtime and runtime.linker packages.
  15.179 +        final Permissions permissions = new Permissions();
  15.180 +        permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.runtime"));
  15.181 +        permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.runtime.linker"));
  15.182 +        return new ProtectionDomain(new CodeSource(null, (CodeSigner[])null), permissions);
  15.183 +    }
  15.184  }
    16.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java	Thu Jan 30 19:45:20 2014 +0530
    16.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java	Thu Jan 30 20:14:29 2014 +0100
    16.3 @@ -25,10 +25,28 @@
    16.4  
    16.5  package jdk.nashorn.internal.runtime.linker;
    16.6  
    16.7 +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_FINAL;
    16.8 +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
    16.9 +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
   16.10 +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
   16.11 +import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD;
   16.12 +import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
   16.13  import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
   16.14  
   16.15  import java.lang.invoke.MethodHandle;
   16.16 +import java.lang.invoke.MethodHandles;
   16.17  import java.lang.invoke.MethodType;
   16.18 +import java.security.AccessController;
   16.19 +import java.security.CodeSigner;
   16.20 +import java.security.CodeSource;
   16.21 +import java.security.Permissions;
   16.22 +import java.security.PrivilegedAction;
   16.23 +import java.security.ProtectionDomain;
   16.24 +import java.security.SecureClassLoader;
   16.25 +import jdk.internal.org.objectweb.asm.ClassWriter;
   16.26 +import jdk.internal.org.objectweb.asm.Opcodes;
   16.27 +import jdk.internal.org.objectweb.asm.Type;
   16.28 +import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
   16.29  import jdk.nashorn.internal.runtime.Context;
   16.30  import jdk.nashorn.internal.runtime.ScriptFunction;
   16.31  import jdk.nashorn.internal.runtime.ScriptObject;
   16.32 @@ -40,6 +58,7 @@
   16.33   */
   16.34  public final class JavaAdapterServices {
   16.35      private static final ThreadLocal<ScriptObject> classOverrides = new ThreadLocal<>();
   16.36 +    private static final MethodHandle NO_PERMISSIONS_INVOKER = createNoPermissionsInvoker();
   16.37  
   16.38      private JavaAdapterServices() {
   16.39      }
   16.40 @@ -55,7 +74,7 @@
   16.41       */
   16.42      public static MethodHandle getHandle(final ScriptFunction fn, final MethodType type) {
   16.43          // JS "this" will be global object or undefined depending on if 'fn' is strict or not
   16.44 -        return adaptHandle(fn.getBoundInvokeHandle(fn.isStrict()? ScriptRuntime.UNDEFINED : Context.getGlobal()), type);
   16.45 +        return bindAndAdaptHandle(fn, fn.isStrict()? ScriptRuntime.UNDEFINED : Context.getGlobal(), type);
   16.46      }
   16.47  
   16.48      /**
   16.49 @@ -83,7 +102,7 @@
   16.50  
   16.51          final Object fnObj = sobj.get(name);
   16.52          if (fnObj instanceof ScriptFunction) {
   16.53 -            return adaptHandle(((ScriptFunction)fnObj).getBoundInvokeHandle(sobj), type);
   16.54 +            return bindAndAdaptHandle((ScriptFunction)fnObj, sobj, type);
   16.55          } else if(fnObj == null || fnObj instanceof Undefined) {
   16.56              return null;
   16.57          } else {
   16.58 @@ -103,11 +122,67 @@
   16.59          return overrides;
   16.60      }
   16.61  
   16.62 +    /**
   16.63 +     * Takes a method handle and an argument to it, and invokes the method handle passing it the argument. Basically
   16.64 +     * equivalent to {@code method.invokeExact(arg)}, except that the method handle will be invoked in a protection
   16.65 +     * domain with absolutely no permissions.
   16.66 +     * @param method the method handle to invoke. The handle must have the exact type of {@code void(Object)}.
   16.67 +     * @param arg the argument to pass to the handle.
   16.68 +     * @throws Throwable if anything goes wrong.
   16.69 +     */
   16.70 +    public static void invokeNoPermissions(final MethodHandle method, final Object arg) throws Throwable {
   16.71 +        NO_PERMISSIONS_INVOKER.invokeExact(method, arg);
   16.72 +    }
   16.73 +
   16.74      static void setClassOverrides(ScriptObject overrides) {
   16.75          classOverrides.set(overrides);
   16.76      }
   16.77  
   16.78 -    private static MethodHandle adaptHandle(final MethodHandle handle, final MethodType type) {
   16.79 -        return Bootstrap.getLinkerServices().asType(ScriptObject.pairArguments(handle, type, false), type);
   16.80 +    private static MethodHandle bindAndAdaptHandle(final ScriptFunction fn, final Object self, final MethodType type) {
   16.81 +        return Bootstrap.getLinkerServices().asType(ScriptObject.pairArguments(fn.getBoundInvokeHandle(self), type, false), type);
   16.82 +    }
   16.83 +
   16.84 +    private static MethodHandle createNoPermissionsInvoker() {
   16.85 +        final String className = "NoPermissionsInvoker";
   16.86 +
   16.87 +        final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
   16.88 +        cw.visit(Opcodes.V1_7, ACC_PUBLIC | ACC_SUPER | ACC_FINAL, className, null, "java/lang/Object", null);
   16.89 +        final Type objectType = Type.getType(Object.class);
   16.90 +        final Type methodHandleType = Type.getType(MethodHandle.class);
   16.91 +        final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "invoke",
   16.92 +                Type.getMethodDescriptor(Type.VOID_TYPE, methodHandleType, objectType), null, null));
   16.93 +        mv.visitCode();
   16.94 +        mv.visitVarInsn(ALOAD, 0);
   16.95 +        mv.visitVarInsn(ALOAD, 1);
   16.96 +        mv.invokevirtual(methodHandleType.getInternalName(), "invokeExact", Type.getMethodDescriptor(
   16.97 +                Type.VOID_TYPE, objectType), false);
   16.98 +        mv.visitInsn(RETURN);
   16.99 +        mv.visitMaxs(0, 0);
  16.100 +        mv.visitEnd();
  16.101 +        cw.visitEnd();
  16.102 +        final byte[] bytes = cw.toByteArray();
  16.103 +
  16.104 +        final ClassLoader loader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
  16.105 +            @Override
  16.106 +            public ClassLoader run() {
  16.107 +                return new SecureClassLoader(null) {
  16.108 +                    @Override
  16.109 +                    protected Class<?> findClass(String name) throws ClassNotFoundException {
  16.110 +                        if(name.equals(className)) {
  16.111 +                            return defineClass(name, bytes, 0, bytes.length, new ProtectionDomain(
  16.112 +                                    new CodeSource(null, (CodeSigner[])null), new Permissions()));
  16.113 +                        }
  16.114 +                        throw new ClassNotFoundException(name);
  16.115 +                    }
  16.116 +                };
  16.117 +            }
  16.118 +        });
  16.119 +
  16.120 +        try {
  16.121 +            return MethodHandles.lookup().findStatic(Class.forName(className, true, loader), "invoke",
  16.122 +                    MethodType.methodType(void.class, MethodHandle.class, Object.class));
  16.123 +        } catch(ReflectiveOperationException e) {
  16.124 +            throw new AssertionError(e.getMessage(), e);
  16.125 +        }
  16.126      }
  16.127  }
    17.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java	Thu Jan 30 19:45:20 2014 +0530
    17.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java	Thu Jan 30 20:14:29 2014 +0100
    17.3 @@ -25,19 +25,20 @@
    17.4  
    17.5  package jdk.nashorn.internal.runtime.linker;
    17.6  
    17.7 +import static jdk.nashorn.internal.lookup.Lookup.MH;
    17.8  import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
    17.9  import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
   17.10 -import static jdk.nashorn.internal.lookup.Lookup.MH;
   17.11  
   17.12  import java.lang.invoke.MethodHandle;
   17.13  import java.lang.invoke.MethodType;
   17.14  import java.lang.reflect.Method;
   17.15  import java.lang.reflect.Modifier;
   17.16 +import java.util.HashMap;
   17.17  import java.util.Map;
   17.18 -import java.util.HashMap;
   17.19  import jdk.internal.dynalink.CallSiteDescriptor;
   17.20  import jdk.internal.dynalink.beans.BeansLinker;
   17.21  import jdk.internal.dynalink.linker.GuardedInvocation;
   17.22 +import jdk.internal.dynalink.linker.GuardedTypeConversion;
   17.23  import jdk.internal.dynalink.linker.GuardingDynamicLinker;
   17.24  import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
   17.25  import jdk.internal.dynalink.linker.LinkRequest;
   17.26 @@ -134,9 +135,9 @@
   17.27      }
   17.28  
   17.29      @Override
   17.30 -    public GuardedInvocation convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception {
   17.31 +    public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception {
   17.32          final GuardedInvocation gi = convertToTypeNoCast(sourceType, targetType);
   17.33 -        return gi == null ? null : gi.asType(MH.type(targetType, sourceType));
   17.34 +        return gi == null ? null : new GuardedTypeConversion(gi.asType(MH.type(targetType, sourceType)), true);
   17.35      }
   17.36  
   17.37      /**
    18.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java	Thu Jan 30 19:45:20 2014 +0530
    18.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java	Thu Jan 30 20:14:29 2014 +0100
    18.3 @@ -29,7 +29,10 @@
    18.4  
    18.5  import java.lang.invoke.MethodHandle;
    18.6  import java.lang.invoke.MethodHandles;
    18.7 +import java.lang.invoke.MethodHandles.Lookup;
    18.8  import java.lang.reflect.Modifier;
    18.9 +import java.security.AccessController;
   18.10 +import java.security.PrivilegedAction;
   18.11  import java.util.Deque;
   18.12  import java.util.List;
   18.13  import java.util.Map;
   18.14 @@ -37,16 +40,17 @@
   18.15  import jdk.internal.dynalink.CallSiteDescriptor;
   18.16  import jdk.internal.dynalink.linker.ConversionComparator;
   18.17  import jdk.internal.dynalink.linker.GuardedInvocation;
   18.18 +import jdk.internal.dynalink.linker.GuardedTypeConversion;
   18.19  import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
   18.20  import jdk.internal.dynalink.linker.LinkRequest;
   18.21  import jdk.internal.dynalink.linker.LinkerServices;
   18.22  import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
   18.23  import jdk.internal.dynalink.support.Guards;
   18.24 +import jdk.internal.dynalink.support.LinkerServicesImpl;
   18.25  import jdk.nashorn.api.scripting.JSObject;
   18.26  import jdk.nashorn.api.scripting.ScriptObjectMirror;
   18.27  import jdk.nashorn.api.scripting.ScriptUtils;
   18.28  import jdk.nashorn.internal.objects.NativeArray;
   18.29 -import jdk.nashorn.internal.runtime.Context;
   18.30  import jdk.nashorn.internal.runtime.JSType;
   18.31  import jdk.nashorn.internal.runtime.ScriptFunction;
   18.32  import jdk.nashorn.internal.runtime.ScriptObject;
   18.33 @@ -100,9 +104,16 @@
   18.34      }
   18.35  
   18.36      @Override
   18.37 -    public GuardedInvocation convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception {
   18.38 -        final GuardedInvocation gi = convertToTypeNoCast(sourceType, targetType);
   18.39 -        return gi == null ? null : gi.asType(MH.type(targetType, sourceType));
   18.40 +    public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception {
   18.41 +        GuardedInvocation gi = convertToTypeNoCast(sourceType, targetType);
   18.42 +        if(gi != null) {
   18.43 +            return new GuardedTypeConversion(gi.asType(MH.type(targetType, sourceType)), true);
   18.44 +        }
   18.45 +        gi = getSamTypeConverter(sourceType, targetType);
   18.46 +        if(gi != null) {
   18.47 +            return new GuardedTypeConversion(gi.asType(MH.type(targetType, sourceType)), false);
   18.48 +        }
   18.49 +        return null;
   18.50      }
   18.51  
   18.52      /**
   18.53 @@ -126,12 +137,7 @@
   18.54              return arrayConverter;
   18.55          }
   18.56  
   18.57 -        final GuardedInvocation mirrorConverter = getMirrorConverter(sourceType, targetType);
   18.58 -        if(mirrorConverter != null) {
   18.59 -            return mirrorConverter;
   18.60 -        }
   18.61 -
   18.62 -        return getSamTypeConverter(sourceType, targetType);
   18.63 +        return getMirrorConverter(sourceType, targetType);
   18.64      }
   18.65  
   18.66      /**
   18.67 @@ -150,13 +156,23 @@
   18.68          final boolean isSourceTypeGeneric = sourceType.isAssignableFrom(ScriptFunction.class);
   18.69  
   18.70          if ((isSourceTypeGeneric || ScriptFunction.class.isAssignableFrom(sourceType)) && isAutoConvertibleFromFunction(targetType)) {
   18.71 -            final MethodHandle ctor = JavaAdapterFactory.getConstructor(ScriptFunction.class, targetType);
   18.72 +            final MethodHandle ctor = JavaAdapterFactory.getConstructor(ScriptFunction.class, targetType, getCurrentLookup());
   18.73              assert ctor != null; // if isAutoConvertibleFromFunction() returned true, then ctor must exist.
   18.74              return new GuardedInvocation(ctor, isSourceTypeGeneric ? IS_SCRIPT_FUNCTION : null);
   18.75          }
   18.76          return null;
   18.77      }
   18.78  
   18.79 +    private static Lookup getCurrentLookup() {
   18.80 +        final LinkRequest currentRequest = AccessController.doPrivileged(new PrivilegedAction<LinkRequest>() {
   18.81 +            @Override
   18.82 +            public LinkRequest run() {
   18.83 +                return LinkerServicesImpl.getCurrentLinkRequest();
   18.84 +            }
   18.85 +        });
   18.86 +        return currentRequest == null ? MethodHandles.publicLookup() : currentRequest.getCallSiteDescriptor().getLookup();
   18.87 +    }
   18.88 +
   18.89      /**
   18.90       * Returns a guarded invocation that converts from a source type that is NativeArray to a Java array or List or
   18.91       * Deque type.
    19.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java	Thu Jan 30 19:45:20 2014 +0530
    19.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java	Thu Jan 30 20:14:29 2014 +0100
    19.3 @@ -31,6 +31,7 @@
    19.4  import java.lang.invoke.MethodHandles;
    19.5  import jdk.internal.dynalink.linker.ConversionComparator;
    19.6  import jdk.internal.dynalink.linker.GuardedInvocation;
    19.7 +import jdk.internal.dynalink.linker.GuardedTypeConversion;
    19.8  import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
    19.9  import jdk.internal.dynalink.linker.LinkRequest;
   19.10  import jdk.internal.dynalink.linker.LinkerServices;
   19.11 @@ -75,13 +76,13 @@
   19.12       * @return a conditional converter from source to target type
   19.13       */
   19.14      @Override
   19.15 -    public GuardedInvocation convertToType(final Class<?> sourceType, final Class<?> targetType) {
   19.16 +    public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) {
   19.17          final MethodHandle mh = JavaArgumentConverters.getConverter(targetType);
   19.18          if (mh == null) {
   19.19              return null;
   19.20          }
   19.21  
   19.22 -        return new GuardedInvocation(mh, canLinkTypeStatic(sourceType) ? null : GUARD_PRIMITIVE).asType(mh.type().changeParameterType(0, sourceType));
   19.23 +        return new GuardedTypeConversion(new GuardedInvocation(mh, canLinkTypeStatic(sourceType) ? null : GUARD_PRIMITIVE).asType(mh.type().changeParameterType(0, sourceType)), true);
   19.24      }
   19.25  
   19.26      /**
    20.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java	Thu Jan 30 19:45:20 2014 +0530
    20.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java	Thu Jan 30 20:14:29 2014 +0100
    20.3 @@ -76,7 +76,8 @@
    20.4              if (NashornLinker.isAbstractClass(receiverClass)) {
    20.5                  // Change this link request into a link request on the adapter class.
    20.6                  final Object[] args = request.getArguments();
    20.7 -                args[0] = JavaAdapterFactory.getAdapterClassFor(new Class<?>[] { receiverClass }, null);
    20.8 +                args[0] = JavaAdapterFactory.getAdapterClassFor(new Class<?>[] { receiverClass }, null,
    20.9 +                        linkRequest.getCallSiteDescriptor().getLookup());
   20.10                  final LinkRequest adapterRequest = request.replaceArguments(request.getCallSiteDescriptor(), args);
   20.11                  final GuardedInvocation gi = checkNullConstructor(delegate(linkerServices, adapterRequest), receiverClass);
   20.12                  // Finally, modify the guard to test for the original abstract class.
    21.1 --- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties	Thu Jan 30 19:45:20 2014 +0530
    21.2 +++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties	Thu Jan 30 20:14:29 2014 +0100
    21.3 @@ -130,6 +130,7 @@
    21.4  type.error.extend.ERROR_NO_ACCESSIBLE_CONSTRUCTOR=Can not extend class {0} as it has no public or protected constructors.
    21.5  type.error.extend.ERROR_MULTIPLE_SUPERCLASSES=Can not extend multiple classes {0}. At most one of the specified types can be a class, the rest must all be interfaces.
    21.6  type.error.extend.ERROR_NO_COMMON_LOADER=Can not find a common class loader for ScriptObject and {0}.
    21.7 +type.error.extend.ERROR_FINAL_FINALIZER=Can not extend class because {0} has a final finalize method.
    21.8  type.error.no.constructor.matches.args=Can not construct {0} with the passed arguments; they do not match any of its constructor signatures.
    21.9  type.error.no.method.matches.args=Can not invoke method {0} with the passed arguments; they do not match any of its method signatures.
   21.10  type.error.method.not.constructor=Java method {0} can't be used as a constructor.
    22.1 --- a/test/script/basic/JDK-8014647.js	Thu Jan 30 19:45:20 2014 +0530
    22.2 +++ b/test/script/basic/JDK-8014647.js	Thu Jan 30 20:14:29 2014 +0100
    22.3 @@ -32,9 +32,10 @@
    22.4  var RunnableImpl2 = Java.extend(java.lang.Runnable, function() { print("I'm runnable 2!") })
    22.5  var r1 = new RunnableImpl1()
    22.6  var r2 = new RunnableImpl2()
    22.7 -var r3 = new RunnableImpl2(function() { print("I'm runnable 3!") })
    22.8 +var RunnableImpl3 = Java.extend(RunnableImpl2);
    22.9 +var r3 = new RunnableImpl3({ run: function() { print("I'm runnable 3!") }})
   22.10  r1.run()
   22.11  r2.run()
   22.12  r3.run()
   22.13 -print("r1.class === r2.class: " + (r1.class === r2.class))
   22.14 -print("r2.class === r3.class: " + (r2.class === r3.class))
   22.15 +print("r1.class !== r2.class: " + (r1.class !== r2.class))
   22.16 +print("r2.class !== r3.class: " + (r2.class !== r3.class))
    23.1 --- a/test/script/basic/JDK-8014647.js.EXPECTED	Thu Jan 30 19:45:20 2014 +0530
    23.2 +++ b/test/script/basic/JDK-8014647.js.EXPECTED	Thu Jan 30 20:14:29 2014 +0100
    23.3 @@ -1,5 +1,5 @@
    23.4  I'm runnable 1!
    23.5  I'm runnable 2!
    23.6  I'm runnable 3!
    23.7 -r1.class === r2.class: false
    23.8 -r2.class === r3.class: true
    23.9 +r1.class !== r2.class: true
   23.10 +r2.class !== r3.class: true
    24.1 --- a/test/script/basic/javaclassoverrides.js	Thu Jan 30 19:45:20 2014 +0530
    24.2 +++ b/test/script/basic/javaclassoverrides.js	Thu Jan 30 20:14:29 2014 +0100
    24.3 @@ -46,7 +46,8 @@
    24.4  var r1 = new R1
    24.5  var r2 = new R2
    24.6  // Create one with an instance-override too
    24.7 -var r3 = new R2(function() { print("r3.run() invoked") })
    24.8 +var R3 = Java.extend(R2)
    24.9 +var r3 = new R3({ run: function() { print("r3.run() invoked") }})
   24.10  
   24.11  // Run 'em - we're passing them through a Thread to make sure they indeed
   24.12  // are full-blown Runnables
   24.13 @@ -60,9 +61,9 @@
   24.14  runInThread(r3)
   24.15  
   24.16  // Two class-override classes differ
   24.17 -print("r1.class != r2.class: " + (r1.class != r2.class))
   24.18 -// However, adding instance-overrides doesn't change the class
   24.19 -print("r2.class == r3.class: " + (r2.class == r3.class))
   24.20 +print("r1.class !== r2.class: " + (r1.class !== r2.class))
   24.21 +// instance-override class also differs
   24.22 +print("r2.class !== r3.class: " + (r2.class !== r3.class))
   24.23  
   24.24  function checkAbstract(r) {
   24.25      try {
   24.26 @@ -77,10 +78,10 @@
   24.27  // overrides nor instance overrides are present
   24.28  var RAbstract = Java.extend(java.lang.Runnable, {})
   24.29  checkAbstract(new RAbstract()) // class override (empty)
   24.30 -checkAbstract(new RAbstract() {}) // class+instance override (empty)
   24.31 +checkAbstract(new (Java.extend(RAbstract))() {}) // class+instance override (empty)
   24.32  
   24.33  // Check we delegate to superclass if neither class
   24.34  // overrides nor instance overrides are present
   24.35  var ExtendsList = Java.extend(java.util.ArrayList, {})
   24.36  print("(new ExtendsList).size() = " + (new ExtendsList).size())
   24.37 -print("(new ExtendsList(){}).size() = " + (new ExtendsList(){}).size())
   24.38 \ No newline at end of file
   24.39 +print("(new (Java.extend(ExtendsList)){}).size() = " + (new (Java.extend(ExtendsList)){}).size())
    25.1 --- a/test/script/basic/javaclassoverrides.js.EXPECTED	Thu Jan 30 19:45:20 2014 +0530
    25.2 +++ b/test/script/basic/javaclassoverrides.js.EXPECTED	Thu Jan 30 20:14:29 2014 +0100
    25.3 @@ -1,9 +1,9 @@
    25.4  R1.run() invoked
    25.5  R2.run() invoked
    25.6  r3.run() invoked
    25.7 -r1.class != r2.class: true
    25.8 -r2.class == r3.class: true
    25.9 +r1.class !== r2.class: true
   25.10 +r2.class !== r3.class: true
   25.11  Got exception: java.lang.UnsupportedOperationException
   25.12  Got exception: java.lang.UnsupportedOperationException
   25.13  (new ExtendsList).size() = 0
   25.14 -(new ExtendsList(){}).size() = 0
   25.15 +(new (Java.extend(ExtendsList)){}).size() = 0
    26.1 --- a/test/script/sandbox/javaextend.js	Thu Jan 30 19:45:20 2014 +0530
    26.2 +++ b/test/script/sandbox/javaextend.js	Thu Jan 30 20:14:29 2014 +0100
    26.3 @@ -51,6 +51,21 @@
    26.4      print(e)
    26.5  }
    26.6  
    26.7 +// Can't extend a class with explicit non-overridable finalizer
    26.8 +try {
    26.9 +    Java.extend(model("ClassWithFinalFinalizer"))
   26.10 +} catch(e) {
   26.11 +    print(e)
   26.12 +}
   26.13 +
   26.14 +// Can't extend a class with inherited non-overridable finalizer
   26.15 +try {
   26.16 +    Java.extend(model("ClassWithInheritedFinalFinalizer"))
   26.17 +} catch(e) {
   26.18 +    print(e)
   26.19 +}
   26.20 +
   26.21 +
   26.22  // Can't extend two classes
   26.23  try {
   26.24      Java.extend(java.lang.Thread,java.lang.Number)
    27.1 --- a/test/script/sandbox/javaextend.js.EXPECTED	Thu Jan 30 19:45:20 2014 +0530
    27.2 +++ b/test/script/sandbox/javaextend.js.EXPECTED	Thu Jan 30 20:14:29 2014 +0100
    27.3 @@ -1,6 +1,8 @@
    27.4  TypeError: Can not extend final class jdk.nashorn.test.models.FinalClass.
    27.5  TypeError: Can not extend class jdk.nashorn.test.models.NoAccessibleConstructorClass as it has no public or protected constructors.
    27.6  TypeError: Can not extend/implement non-public class/interface jdk.nashorn.test.models.NonPublicClass.
    27.7 +TypeError: Can not extend class because jdk.nashorn.test.models.ClassWithFinalFinalizer has a final finalize method.
    27.8 +TypeError: Can not extend class because jdk.nashorn.test.models.ClassWithFinalFinalizer has a final finalize method.
    27.9  TypeError: Can not extend multiple classes java.lang.Number and java.lang.Thread. At most one of the specified types can be a class, the rest must all be interfaces.
   27.10  abcdabcd
   27.11  run-object
    28.1 --- a/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java	Thu Jan 30 19:45:20 2014 +0530
    28.2 +++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java	Thu Jan 30 20:14:29 2014 +0100
    28.3 @@ -33,8 +33,8 @@
    28.4  import java.util.Objects;
    28.5  import javax.script.Invocable;
    28.6  import javax.script.ScriptEngine;
    28.7 +import javax.script.ScriptEngineManager;
    28.8  import javax.script.ScriptException;
    28.9 -import javax.script.ScriptEngineManager;
   28.10  import org.testng.annotations.Test;
   28.11  
   28.12  /**
   28.13 @@ -130,6 +130,23 @@
   28.14          }
   28.15      }
   28.16  
   28.17 +
   28.18 +    @Test
   28.19 +    public void securitySystemExitFromFinalizerThread() throws ScriptException {
   28.20 +        if (System.getSecurityManager() == null) {
   28.21 +            // pass vacuously
   28.22 +            return;
   28.23 +        }
   28.24 +
   28.25 +        final ScriptEngineManager m = new ScriptEngineManager();
   28.26 +        final ScriptEngine e = m.getEngineByName("nashorn");
   28.27 +        e.eval("var o = Java.extend(Java.type('javax.imageio.spi.ServiceRegistry'), { deregisterAll: this.exit.bind(null, 1234)});\n" +
   28.28 +                "new o(new java.util.ArrayList().iterator())");
   28.29 +        System.gc();
   28.30 +        System.runFinalization();
   28.31 +        // NOTE: this test just exits the VM if it fails.
   28.32 +    }
   28.33 +
   28.34      @Test
   28.35      public void securitySystemLoadLibrary() {
   28.36          if (System.getSecurityManager() == null) {
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/test/src/jdk/nashorn/test/models/ClassWithFinalFinalizer.java	Thu Jan 30 20:14:29 2014 +0100
    29.3 @@ -0,0 +1,31 @@
    29.4 +/*
    29.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    29.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    29.7 + *
    29.8 + * This code is free software; you can redistribute it and/or modify it
    29.9 + * under the terms of the GNU General Public License version 2 only, as
   29.10 + * published by the Free Software Foundation.  Oracle designates this
   29.11 + * particular file as subject to the "Classpath" exception as provided
   29.12 + * by Oracle in the LICENSE file that accompanied this code.
   29.13 + *
   29.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   29.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   29.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   29.17 + * version 2 for more details (a copy is included in the LICENSE file that
   29.18 + * accompanied this code).
   29.19 + *
   29.20 + * You should have received a copy of the GNU General Public License version
   29.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   29.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   29.23 + *
   29.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   29.25 + * or visit www.oracle.com if you need additional information or have any
   29.26 + * questions.
   29.27 + */
   29.28 +
   29.29 +package jdk.nashorn.test.models;
   29.30 +
   29.31 +public class ClassWithFinalFinalizer {
   29.32 +    protected final void finalize() {
   29.33 +    }
   29.34 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/test/src/jdk/nashorn/test/models/ClassWithInheritedFinalFinalizer.java	Thu Jan 30 20:14:29 2014 +0100
    30.3 @@ -0,0 +1,29 @@
    30.4 +/*
    30.5 + * Copyright (c) 2010, 2013, 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.  Oracle designates this
   30.11 + * particular file as subject to the "Classpath" exception as provided
   30.12 + * by Oracle in the LICENSE file that accompanied this code.
   30.13 + *
   30.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   30.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   30.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   30.17 + * version 2 for more details (a copy is included in the LICENSE file that
   30.18 + * accompanied this code).
   30.19 + *
   30.20 + * You should have received a copy of the GNU General Public License version
   30.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   30.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   30.23 + *
   30.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   30.25 + * or visit www.oracle.com if you need additional information or have any
   30.26 + * questions.
   30.27 + */
   30.28 +
   30.29 +package jdk.nashorn.test.models;
   30.30 +
   30.31 +public class ClassWithInheritedFinalFinalizer extends ClassWithFinalFinalizer {
   30.32 +}

mercurial