src/jdk/nashorn/internal/runtime/CompiledFunction.java

Tue, 12 Mar 2013 15:30:53 +0100

author
lagergren
date
Tue, 12 Mar 2013 15:30:53 +0100
changeset 137
e15806b9d716
child 247
5a3f7867e19c
permissions
-rw-r--r--

8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
Reviewed-by: attila, jlaskey

     1 /*
     2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 package jdk.nashorn.internal.runtime;
    27 import java.lang.invoke.MethodHandle;
    28 import java.lang.invoke.MethodType;
    30 import jdk.nashorn.internal.codegen.types.Type;
    32 /**
    33  * An version of a JavaScript function, native or JavaScript.
    34  * Supports lazily generating a constructor version of the invocation.
    35  */
    36 final class CompiledFunction implements Comparable<CompiledFunction> {
    38     private final MethodHandle invoker;
    39     private MethodHandle constructor;
    41     CompiledFunction(final MethodHandle invoker) {
    42         this(invoker, null);
    43     }
    45     CompiledFunction(final MethodHandle invoker, final MethodHandle constructor) {
    46         this.invoker = invoker;
    47         this.constructor = constructor; //isConstructor
    48     }
    50     @Override
    51     public String toString() {
    52         return "<invoker=" + invoker + " ctor=" + constructor + ">";
    53     }
    55     MethodHandle getInvoker() {
    56         return invoker;
    57     }
    59     MethodHandle getConstructor() {
    60         return constructor;
    61     }
    63     void setConstructor(final MethodHandle constructor) {
    64         this.constructor = constructor;
    65     }
    67     boolean hasConstructor() {
    68         return constructor != null;
    69     }
    71     MethodType type() {
    72         return invoker.type();
    73     }
    75     @Override
    76     public int compareTo(final CompiledFunction o) {
    77         return weight() - o.weight();
    78     }
    80     private int weight() {
    81         return weight(type());
    82     }
    84     private static int weight(final MethodType type) {
    85         if (isVarArgsType(type)) {
    86             return Integer.MAX_VALUE; //if there is a varargs it should be the heavist and last fallback
    87         }
    89         int weight = Type.typeFor(type.returnType()).getWeight();
    90         for (final Class<?> paramType : type.parameterArray()) {
    91             final int pweight = Type.typeFor(paramType).getWeight();
    92             weight += pweight;
    93         }
    94         return weight;
    95     }
    97     private static boolean isVarArgsType(final MethodType type) {
    98         assert type.parameterCount() >= 1 : type;
    99         return type.parameterType(type.parameterCount() - 1) == Object[].class;
   100     }
   102     boolean moreGenericThan(final CompiledFunction o) {
   103         return weight() > o.weight();
   104     }
   106     boolean moreGenericThan(final MethodType type) {
   107         return weight() > weight(type);
   108     }
   110     /**
   111      * Check whether a given method descriptor is compatible with this invocation.
   112      * It is compatible if the types are narrower than the invocation type so that
   113      * a semantically equivalent linkage can be performed.
   114      *
   115      * @param typesc
   116      * @return
   117      */
   118     boolean typeCompatible(final MethodType type) {
   119         final Class<?>[] wantedParams   = type.parameterArray();
   120         final Class<?>[] existingParams = type().parameterArray();
   122         //if we are not examining a varargs type, the number of parameters must be the same
   123         if (wantedParams.length != existingParams.length && !isVarArgsType(type)) {
   124             return false;
   125         }
   127         //we only go as far as the shortest array. the only chance to make this work if
   128         //parameters lengths do not match is if our type ends with a varargs argument.
   129         //then every trailing parameter in the given callsite can be folded into it, making
   130         //us compatible (albeit slower than a direct specialization)
   131         final int lastParamIndex = Math.min(wantedParams.length, existingParams.length);
   132         for (int i = 0; i < lastParamIndex; i++) {
   133             final Type w = Type.typeFor(wantedParams[i]);
   134             final Type e = Type.typeFor(existingParams[i]);
   136             //don't specialize on booleans, we have the "true" vs int 1 ambiguity in resolution
   137             //we also currently don't support boolean as a javascript function callsite type.
   138             //it will always box.
   139             if (w.isBoolean()) {
   140                 return false;
   141             }
   143             //This callsite type has a vararg here. it will swallow all remaining args.
   144             //for consistency, check that it's the last argument
   145             if (e.isArray()) {
   146                 return true;
   147             }
   149             //Our arguments must be at least as wide as the wanted one, if not wider
   150             if (Type.widest(w, e) != e) {
   151                 //e.g. this invocation takes double and callsite says "object". reject. won't fit
   152                 //but if invocation takes a double and callsite says "int" or "long" or "double", that's fine
   153                 return false;
   154             }
   155         }
   157         return true; // anything goes for return type, take the convenient one and it will be upcasted thru dynalink magic.
   158     }
   162 }

mercurial