/* * Copyright (c) 2010-2014, 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.codegen; import java.lang.invoke.MethodType; import java.util.Arrays; import java.util.NoSuchElementException; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.runtime.ScriptFunction; /** * A tuple containing function id, parameter types, return type and needsCallee flag. */ public final class TypeMap { private final int functionNodeId; private final Type[] paramTypes; private final Type returnType; private final boolean needsCallee; /** * Constructor * @param functionNodeId function node id * @param type method type found at runtime corresponding to parameter guess * @param needsCallee does the function using this type map need a callee */ public TypeMap(final int functionNodeId, final MethodType type, final boolean needsCallee) { final Type[] types = new Type[type.parameterCount()]; int pos = 0; for (final Class<?> p : type.parameterArray()) { types[pos++] = Type.typeFor(p); } this.functionNodeId = functionNodeId; this.paramTypes = types; this.returnType = Type.typeFor(type.returnType()); this.needsCallee = needsCallee; } /** * Returns the array of parameter types for a particular function node * @param functionNodeId the ID of the function node * @return an array of parameter types * @throws NoSuchElementException if the type map has no mapping for the requested function */ public Type[] getParameterTypes(final int functionNodeId) { assert this.functionNodeId == functionNodeId; return paramTypes.clone(); } MethodType getCallSiteType(final FunctionNode functionNode) { assert this.functionNodeId == functionNode.getId(); final Type[] types = paramTypes; MethodType mt = MethodType.methodType(returnType.getTypeClass()); if (needsCallee) { mt = mt.appendParameterTypes(ScriptFunction.class); } mt = mt.appendParameterTypes(Object.class); //this for (final Type type : types) { if (type == null) { return null; // not all parameter information is supplied } mt = mt.appendParameterTypes(type.getTypeClass()); } return mt; } /** * Does the function using this TypeMap need a callee argument. This is used * to compute correct param index offsets in {@link jdk.nashorn.internal.codegen.ApplySpecialization} * @return true if a callee is needed, false otherwise */ public boolean needsCallee() { return needsCallee; } /** * Get the parameter type for this parameter position, or * null if now known * @param functionNode functionNode * @param pos position * @return parameter type for this callsite if known */ Type get(final FunctionNode functionNode, final int pos) { assert this.functionNodeId == functionNode.getId(); final Type[] types = paramTypes; assert types == null || pos < types.length : "fn = " + functionNode.getId() + " " + "types=" + Arrays.toString(types) + " || pos=" + pos + " >= length=" + types.length + " in " + this; if (types != null && pos < types.length) { return types[pos]; } return null; } @Override public String toString() { return toString(""); } String toString(final String prefix) { final StringBuilder sb = new StringBuilder(); final int id = functionNodeId; sb.append(prefix).append('\t'); sb.append("function ").append(id).append('\n'); sb.append(prefix).append("\t\tparamTypes="); sb.append(Arrays.toString(paramTypes)); sb.append('\n'); sb.append(prefix).append("\t\treturnType="); final Type ret = returnType; sb.append(ret == null ? "N/A" : ret); sb.append('\n'); return sb.toString(); } }