blob: a26e6b93f5671e15936343dd8bb49d399ff64905 [file] [log] [blame]
/*
* 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();
}
}