8011065: Problems when script implements an interface with variadic methods

Tue, 23 Apr 2013 12:52:29 +0200

author
attila
date
Tue, 23 Apr 2013 12:52:29 +0200
changeset 217
0547a1c76259
parent 215
cfda59f3d827
child 218
32036918585d

8011065: Problems when script implements an interface with variadic methods
Reviewed-by: jlaskey, hannesw, sundar

src/jdk/nashorn/internal/codegen/CodeGenerator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptObject.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/JavaAdapterServices.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/api/scripting/VariableArityTestInterface.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Mon Apr 22 19:57:57 2013 +0530
     1.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Tue Apr 23 12:52:29 2013 +0200
     1.3 @@ -664,7 +664,7 @@
     1.4                      final int useCount = symbol.getUseCount();
     1.5  
     1.6                      // Threshold for generating shared scope callsite is lower for fast scope symbols because we know
     1.7 -                    // we can dial in the correct scope. However, we als need to enable it for non-fast scopes to
     1.8 +                    // we can dial in the correct scope. However, we also need to enable it for non-fast scopes to
     1.9                      // support huge scripts like mandreel.js.
    1.10                      if (callNode.isEval()) {
    1.11                          evalCall(node, flags);
     2.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Apr 22 19:57:57 2013 +0530
     2.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Tue Apr 23 12:52:29 2013 +0200
     2.3 @@ -28,6 +28,7 @@
     2.4  import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
     2.5  import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCall;
     2.6  import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
     2.7 +import static jdk.nashorn.internal.lookup.Lookup.MH;
     2.8  import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
     2.9  import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
    2.10  import static jdk.nashorn.internal.runtime.PropertyDescriptor.CONFIGURABLE;
    2.11 @@ -39,7 +40,6 @@
    2.12  import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
    2.13  import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow;
    2.14  import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
    2.15 -import static jdk.nashorn.internal.lookup.Lookup.MH;
    2.16  
    2.17  import java.lang.invoke.MethodHandle;
    2.18  import java.lang.invoke.MethodHandles;
    2.19 @@ -61,12 +61,13 @@
    2.20  import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
    2.21  import jdk.nashorn.internal.codegen.CompilerConstants.Call;
    2.22  import jdk.nashorn.internal.codegen.ObjectClassGenerator;
    2.23 +import jdk.nashorn.internal.lookup.Lookup;
    2.24 +import jdk.nashorn.internal.lookup.MethodHandleFactory;
    2.25  import jdk.nashorn.internal.objects.AccessorPropertyDescriptor;
    2.26  import jdk.nashorn.internal.objects.DataPropertyDescriptor;
    2.27  import jdk.nashorn.internal.runtime.arrays.ArrayData;
    2.28  import jdk.nashorn.internal.runtime.linker.Bootstrap;
    2.29 -import jdk.nashorn.internal.lookup.Lookup;
    2.30 -import jdk.nashorn.internal.lookup.MethodHandleFactory;
    2.31 +import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
    2.32  import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
    2.33  import jdk.nashorn.internal.runtime.linker.NashornGuards;
    2.34  
    2.35 @@ -2139,8 +2140,11 @@
    2.36       *
    2.37       * Make sure arguments are paired correctly.
    2.38       * @param methodHandle MethodHandle to adjust.
    2.39 -     * @param callType     MethodType of caller.
    2.40 -     * @param callerVarArg true if the caller is vararg, false otherwise, null if it should be inferred.
    2.41 +     * @param callType     MethodType of the call site.
    2.42 +     * @param callerVarArg true if the caller is vararg, false otherwise, null if it should be inferred from the
    2.43 +     * {@code callType}; basically, if the last parameter type of the call site is an array, it'll be considered a
    2.44 +     * variable arity call site. These are ordinarily rare; Nashorn code generator creates variable arity call sites
    2.45 +     * when the call has more than {@link LinkerCallSite#ARGLIMIT} parameters.
    2.46       *
    2.47       * @return method handle with adjusted arguments
    2.48       */
    2.49 @@ -2155,7 +2159,7 @@
    2.50          final int callCount      = callType.parameterCount();
    2.51  
    2.52          final boolean isCalleeVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray();
    2.53 -        final boolean isCallerVarArg = callerVarArg != null ? callerVarArg.booleanValue() : (callCount > 1 &&
    2.54 +        final boolean isCallerVarArg = callerVarArg != null ? callerVarArg.booleanValue() : (callCount > 0 &&
    2.55                  callType.parameterType(callCount - 1).isArray());
    2.56  
    2.57          if (callCount < parameterCount) {
     3.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Mon Apr 22 19:57:57 2013 +0530
     3.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java	Tue Apr 23 12:52:29 2013 +0200
     3.3 @@ -127,9 +127,9 @@
     3.4      private static final Type METHOD_TYPE_TYPE = Type.getType(MethodType.class);
     3.5      private static final Type METHOD_HANDLE_TYPE = Type.getType(MethodHandle.class);
     3.6      private static final String GET_HANDLE_OBJECT_DESCRIPTOR = Type.getMethodDescriptor(METHOD_HANDLE_TYPE,
     3.7 -            OBJECT_TYPE, STRING_TYPE, METHOD_TYPE_TYPE, Type.BOOLEAN_TYPE);
     3.8 +            OBJECT_TYPE, STRING_TYPE, METHOD_TYPE_TYPE);
     3.9      private static final String GET_HANDLE_FUNCTION_DESCRIPTOR = Type.getMethodDescriptor(METHOD_HANDLE_TYPE,
    3.10 -            SCRIPT_FUNCTION_TYPE, METHOD_TYPE_TYPE, Type.BOOLEAN_TYPE);
    3.11 +            SCRIPT_FUNCTION_TYPE, METHOD_TYPE_TYPE);
    3.12      private static final String GET_CLASS_INITIALIZER_DESCRIPTOR = Type.getMethodDescriptor(SCRIPT_OBJECT_TYPE);
    3.13      private static final Type RUNTIME_EXCEPTION_TYPE = Type.getType(RuntimeException.class);
    3.14      private static final Type THROWABLE_TYPE = Type.getType(Throwable.class);
    3.15 @@ -315,7 +315,6 @@
    3.16              mv.dup();
    3.17              mv.aconst(mi.getName());
    3.18              mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
    3.19 -            mv.iconst(mi.method.isVarArgs() ? 1 : 0);
    3.20              mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_OBJECT_DESCRIPTOR);
    3.21              mv.putstatic(generatedClassName, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
    3.22          }
    3.23 @@ -459,7 +458,6 @@
    3.24                      mv.aconst(mi.getName());
    3.25                  }
    3.26                  mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
    3.27 -                mv.iconst(mi.method.isVarArgs() ? 1 : 0);
    3.28                  mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", getHandleDescriptor);
    3.29              }
    3.30              mv.putfield(generatedClassName, mi.methodHandleInstanceFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
     4.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java	Mon Apr 22 19:57:57 2013 +0530
     4.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java	Tue Apr 23 12:52:29 2013 +0200
     4.3 @@ -50,12 +50,11 @@
     4.4       * handles for their abstract method implementations.
     4.5       * @param fn the script function
     4.6       * @param type the method type it has to conform to
     4.7 -     * @param varArg if the Java method for which the function is being adapted is a variable arity method
     4.8       * @return the appropriately adapted method handle for invoking the script function.
     4.9       */
    4.10 -    public static MethodHandle getHandle(final ScriptFunction fn, final MethodType type, final boolean varArg) {
    4.11 +    public static MethodHandle getHandle(final ScriptFunction fn, final MethodType type) {
    4.12          // JS "this" will be null for SAMs
    4.13 -        return adaptHandle(fn.getBoundInvokeHandle(null), type, varArg);
    4.14 +        return adaptHandle(fn.getBoundInvokeHandle(null), type);
    4.15      }
    4.16  
    4.17      /**
    4.18 @@ -66,12 +65,11 @@
    4.19       * @param obj the script obj
    4.20       * @param name the name of the property that contains the function
    4.21       * @param type the method type it has to conform to
    4.22 -     * @param varArg if the Java method for which the function is being adapted is a variable arity method
    4.23       * @return the appropriately adapted method handle for invoking the script function, or null if the value of the
    4.24       * property is either null or undefined, or "toString" was requested as the name, but the object doesn't directly
    4.25       * define it but just inherits it through prototype.
    4.26       */
    4.27 -    public static MethodHandle getHandle(final Object obj, final String name, final MethodType type, final boolean varArg) {
    4.28 +    public static MethodHandle getHandle(final Object obj, final String name, final MethodType type) {
    4.29          if (! (obj instanceof ScriptObject)) {
    4.30              throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
    4.31          }
    4.32 @@ -84,7 +82,7 @@
    4.33  
    4.34          final Object fnObj = sobj.get(name);
    4.35          if (fnObj instanceof ScriptFunction) {
    4.36 -            return adaptHandle(((ScriptFunction)fnObj).getBoundInvokeHandle(sobj), type, varArg);
    4.37 +            return adaptHandle(((ScriptFunction)fnObj).getBoundInvokeHandle(sobj), type);
    4.38          } else if(fnObj == null || fnObj instanceof Undefined) {
    4.39              return null;
    4.40          } else {
    4.41 @@ -108,7 +106,7 @@
    4.42          classOverrides.set(overrides);
    4.43      }
    4.44  
    4.45 -    private static MethodHandle adaptHandle(final MethodHandle handle, final MethodType type, final boolean varArg) {
    4.46 -        return Bootstrap.getLinkerServices().asType(ScriptObject.pairArguments(handle, type, varArg), type);
    4.47 +    private static MethodHandle adaptHandle(final MethodHandle handle, final MethodType type) {
    4.48 +        return Bootstrap.getLinkerServices().asType(ScriptObject.pairArguments(handle, type, false), type);
    4.49      }
    4.50  }
     5.1 --- a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Mon Apr 22 19:57:57 2013 +0530
     5.2 +++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java	Tue Apr 23 12:52:29 2013 +0200
     5.3 @@ -906,4 +906,26 @@
     5.4              fail(se.getMessage());
     5.5          }
     5.6      }
     5.7 +
     5.8 +    @Test
     5.9 +    /**
    5.10 +     * Tests whether invocation of a JavaScript method through a variable arity Java method will pass the vararg array.
    5.11 +     * Both non-vararg and vararg JavaScript methods are tested.
    5.12 +     * @throws ScriptException
    5.13 +     */
    5.14 +    public void variableArityInterfaceTest() throws ScriptException {
    5.15 +        final ScriptEngineManager m = new ScriptEngineManager();
    5.16 +        final ScriptEngine e = m.getEngineByName("nashorn");
    5.17 +        e.eval(
    5.18 +            "function test1(i, strings) {" +
    5.19 +            "    return 'i == ' + i + ', strings instanceof java.lang.String[] == ' + (strings instanceof Java.type('java.lang.String[]')) + ', strings == ' + java.util.Arrays.toString(strings)" +
    5.20 +            "}" +
    5.21 +            "function test2() {" +
    5.22 +            "    return 'arguments[0] == ' + arguments[0] + ', arguments[1] instanceof java.lang.String[] == ' + (arguments[1] instanceof Java.type('java.lang.String[]')) + ', arguments[1] == ' + java.util.Arrays.toString(arguments[1])" +
    5.23 +            "}"
    5.24 +        );
    5.25 +        final VariableArityTestInterface itf = ((Invocable)e).getInterface(VariableArityTestInterface.class);
    5.26 +        Assert.assertEquals(itf.test1(42, "a", "b"), "i == 42, strings instanceof java.lang.String[] == true, strings == [a, b]");
    5.27 +        Assert.assertEquals(itf.test2(44, "c", "d", "e"), "arguments[0] == 44, arguments[1] instanceof java.lang.String[] == true, arguments[1] == [c, d, e]");
    5.28 +    }
    5.29  }
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/test/src/jdk/nashorn/api/scripting/VariableArityTestInterface.java	Tue Apr 23 12:52:29 2013 +0200
     6.3 @@ -0,0 +1,31 @@
     6.4 +/*
     6.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.7 + *
     6.8 + * This code is free software; you can redistribute it and/or modify it
     6.9 + * under the terms of the GNU General Public License version 2 only, as
    6.10 + * published by the Free Software Foundation.  Oracle designates this
    6.11 + * particular file as subject to the "Classpath" exception as provided
    6.12 + * by Oracle in the LICENSE file that accompanied this code.
    6.13 + *
    6.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    6.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    6.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    6.17 + * version 2 for more details (a copy is included in the LICENSE file that
    6.18 + * accompanied this code).
    6.19 + *
    6.20 + * You should have received a copy of the GNU General Public License version
    6.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    6.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    6.23 + *
    6.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    6.25 + * or visit www.oracle.com if you need additional information or have any
    6.26 + * questions.
    6.27 + */
    6.28 +
    6.29 +package jdk.nashorn.api.scripting;
    6.30 +
    6.31 +public interface VariableArityTestInterface {
    6.32 +    public String test1(int i, String... strings);
    6.33 +    public String test2(int i, String... strings);
    6.34 +}

mercurial