alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (CompiledFunction.java)

This example Java source code file (CompiledFunction.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

class, comparable, compiledfunction, methodhandle, methodtype, override, string

The CompiledFunction.java Java example source code

/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package jdk.nashorn.internal.runtime;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;

import jdk.nashorn.internal.codegen.types.Type;

/**
 * An version of a JavaScript function, native or JavaScript.
 * Supports lazily generating a constructor version of the invocation.
 */
final class CompiledFunction implements Comparable<CompiledFunction> {

    /** The method type may be more specific than the invoker, if. e.g.
     *  the invoker is guarded, and a guard with a generic object only
     *  fallback, while the target is more specific, we still need the
     *  more specific type for sorting */
    private final MethodType   type;
    private final MethodHandle invoker;
    private MethodHandle constructor;

    CompiledFunction(final MethodType type, final MethodHandle invoker) {
        this(type, invoker, null);
    }

    CompiledFunction(final MethodType type, final MethodHandle invoker, final MethodHandle constructor) {
        assert type != null;
        this.type        = type;
        this.invoker     = invoker;
        this.constructor = constructor;
    }

    @Override
    public String toString() {
        return "<callSiteType= " + type + " invoker=" + invoker + " ctor=" + constructor + ">";
    }

    MethodHandle getInvoker() {
        return invoker;
    }

    MethodHandle getConstructor() {
        return constructor;
    }

    void setConstructor(final MethodHandle constructor) {
        this.constructor = constructor;
    }

    boolean hasConstructor() {
        return constructor != null;
    }

    MethodType type() {
        return type;
    }

    @Override
    public int compareTo(final CompiledFunction o) {
        return compareMethodTypes(type(), o.type());
    }

    private static int compareMethodTypes(final MethodType ownType, final MethodType otherType) {
        // Comparable interface demands that compareTo() should only return 0 if objects are equal.
        // Failing to meet this requirement causes same weight functions to replace each other in TreeSet,
        // so we go some lengths to come up with an ordering between same weight functions,
        // first falling back to parameter count and then to hash code.
        if (ownType.equals(otherType)) {
            return 0;
        }

        final int diff = weight(ownType) - weight(otherType);
        if (diff != 0) {
            return diff;
        }
        if (ownType.parameterCount() != otherType.parameterCount()) {
            return ownType.parameterCount() - otherType.parameterCount();
        }
        // We're just interested in not returning 0 here, not correct ordering
        return ownType.hashCode() - otherType.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        return obj instanceof CompiledFunction && type().equals(((CompiledFunction)obj).type());
    }

    @Override
    public int hashCode() {
        return type().hashCode();
    }

    private int weight() {
        return weight(type());
    }

    private static int weight(final MethodType type) {
        if (isVarArgsType(type)) {
            return Integer.MAX_VALUE; //if there is a varargs it should be the heavist and last fallback
        }

        int weight = Type.typeFor(type.returnType()).getWeight();
        for (final Class<?> paramType : type.parameterArray()) {
            final int pweight = Type.typeFor(paramType).getWeight() * 2; //params are more important than call types as return values are always specialized
            weight += pweight;
        }
        return weight;
    }

    private static boolean isVarArgsType(final MethodType type) {
        assert type.parameterCount() >= 1 : type;
        return type.parameterType(type.parameterCount() - 1) == Object[].class;
    }

    boolean moreGenericThan(final CompiledFunction o) {
        return weight() > o.weight();
    }

    boolean moreGenericThan(final MethodType mt) {
        return weight() > weight(mt);
    }

    /**
     * Check whether a given method descriptor is compatible with this invocation.
     * It is compatible if the types are narrower than the invocation type so that
     * a semantically equivalent linkage can be performed.
     *
     * @param mt type to check against
     * @return true if types are compatible
     */
    boolean typeCompatible(final MethodType mt) {
        final int wantedParamCount   = mt.parameterCount();
        final int existingParamCount = type.parameterCount();

        //if we are not examining a varargs type, the number of parameters must be the same
        if (wantedParamCount != existingParamCount && !isVarArgsType(mt)) {
            return false;
        }

        //we only go as far as the shortest array. the only chance to make this work if
        //parameters lengths do not match is if our type ends with a varargs argument.
        //then every trailing parameter in the given callsite can be folded into it, making
        //us compatible (albeit slower than a direct specialization)
        final int lastParamIndex = Math.min(wantedParamCount, existingParamCount);
        for (int i = 0; i < lastParamIndex; i++) {
            final Type w = Type.typeFor(mt.parameterType(i));
            final Type e = Type.typeFor(type.parameterType(i));

            //don't specialize on booleans, we have the "true" vs int 1 ambiguity in resolution
            //we also currently don't support boolean as a javascript function callsite type.
            //it will always box.
            if (w.isBoolean()) {
                return false;
            }

            //This callsite type has a vararg here. it will swallow all remaining args.
            //for consistency, check that it's the last argument
            if (e.isArray()) {
                return true;
            }

            //Our arguments must be at least as wide as the wanted one, if not wider
            if (Type.widest(w, e) != e) {
                //e.g. this invocation takes double and callsite says "object". reject. won't fit
                //but if invocation takes a double and callsite says "int" or "long" or "double", that's fine
                return false;
            }
        }

        return true; // anything goes for return type, take the convenient one and it will be upcasted thru dynalink magic.
    }



}

Other Java examples (source code examples)

Here is a short list of links related to this Java CompiledFunction.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.