8007215: Varargs broken for the case of passing more than the arg limit arguments

Reviewed-by: jlaskey, attila
This commit is contained in:
Marcus Lagergren 2013-02-04 16:20:05 +01:00
parent bd2303d9e4
commit 8b7a8d75b3
13 changed files with 113 additions and 67 deletions

View File

@ -44,7 +44,7 @@ public class NashornException extends RuntimeException {
// script column number
private int column;
// script source name used for "engine.js"
/** script source name used for "engine.js" */
protected static final String ENGINE_SCRIPT_SOURCE_NAME = "nashorn:engine/resources/engine.js";
/**

View File

@ -26,7 +26,6 @@
package jdk.nashorn.api.scripting;
import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.io.IOException;

View File

@ -490,15 +490,15 @@ public final class CodeGenerator extends NodeOperatorVisitor {
return null;
}
private MethodEmitter loadArgs(final List<Node> args) {
private int loadArgs(final List<Node> args) {
return loadArgs(args, null, false, args.size());
}
private MethodEmitter loadArgs(final List<Node> args, final String signature, final boolean isVarArg, final int argCount) {
private int loadArgs(final List<Node> args, final String signature, final boolean isVarArg, final int argCount) {
// arg have already been converted to objects here.
if (isVarArg || argCount > LinkerCallSite.ARGLIMIT) {
loadArgsArray(args);
return method;
return 1;
}
// pad with undefined if size is too short. argCount is the real number of args
@ -520,7 +520,7 @@ public final class CodeGenerator extends NodeOperatorVisitor {
n++;
}
return method;
return argCount;
}
@Override
@ -556,9 +556,8 @@ public final class CodeGenerator extends NodeOperatorVisitor {
load(node);
method.convert(Type.OBJECT); // foo() makes no sense if foo == 3
// ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly.
method.loadNull();
loadArgs(args);
method.dynamicCall(callNode.getType(), args.size(), flags);
method.loadNull(); //the 'this'
method.dynamicCall(callNode.getType(), 2 + loadArgs(args), flags);
}
private void evalCall(final IdentNode node, final int flags) {
@ -597,8 +596,7 @@ public final class CodeGenerator extends NodeOperatorVisitor {
// This is some scope 'eval' or global eval replaced by user
// but not the built-in ECMAScript 'eval' function call
method.loadNull();
loadArgs(args);
method.dynamicCall(callNode.getType(), args.size(), flags);
method.dynamicCall(callNode.getType(), 2 + loadArgs(args), flags);
method.label(eval_done);
}
@ -638,8 +636,7 @@ public final class CodeGenerator extends NodeOperatorVisitor {
method.dup();
method.dynamicGet(node.getType(), node.getProperty().getName(), getCallSiteFlags(), true);
method.swap();
loadArgs(args);
method.dynamicCall(callNode.getType(), args.size(), getCallSiteFlags());
method.dynamicCall(callNode.getType(), 2 + loadArgs(args), getCallSiteFlags());
assert method.peekType().equals(callNode.getType());
return null;
@ -682,8 +679,7 @@ public final class CodeGenerator extends NodeOperatorVisitor {
}
method.dynamicGetIndex(node.getType(), getCallSiteFlags(), true);
method.swap();
loadArgs(args);
method.dynamicCall(callNode.getType(), args.size(), getCallSiteFlags());
method.dynamicCall(callNode.getType(), 2 + loadArgs(args), getCallSiteFlags());
assert method.peekType().equals(callNode.getType());
return null;
@ -695,9 +691,7 @@ public final class CodeGenerator extends NodeOperatorVisitor {
load(function);
method.convert(Type.OBJECT); //TODO, e.g. booleans can be used as functions
method.loadNull(); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE
loadArgs(args);
method.dynamicCall(callNode.getType(), args.size(), getCallSiteFlags() | CALLSITE_SCOPE);
method.dynamicCall(callNode.getType(), 2 + loadArgs(args), getCallSiteFlags() | CALLSITE_SCOPE);
assert method.peekType().equals(callNode.getType());
return null;
@ -1611,7 +1605,7 @@ public final class CodeGenerator extends NodeOperatorVisitor {
// Get the request arguments.
final List<Node> args = runtimeNode.getArgs();
if (nullCheck(runtimeNode, args, new FunctionSignature(false, runtimeNode.getType(), args).toString())) {
if (nullCheck(runtimeNode, args, new FunctionSignature(false, false, runtimeNode.getType(), args).toString())) {
return null;
}
@ -1627,6 +1621,7 @@ public final class CodeGenerator extends NodeOperatorVisitor {
CompilerConstants.className(ScriptRuntime.class),
runtimeNode.getRequest().toString(),
new FunctionSignature(
false,
false,
runtimeNode.getType(),
runtimeNode.getArgs().size()).toString());
@ -2292,10 +2287,7 @@ public final class CodeGenerator extends NodeOperatorVisitor {
// Load function reference.
load(callNode.getFunction()).convert(Type.OBJECT); // must detect type error
// Load arguments.
loadArgs(args);
method.dynamicNew(args.size(), getCallSiteFlags());
method.dynamicNew(1 + loadArgs(args), getCallSiteFlags());
method.store(unaryNode.getSymbol());
return null;
@ -2884,7 +2876,10 @@ public final class CodeGenerator extends NodeOperatorVisitor {
final Label falseLabel = new Label("ternary_false");
final Label exitLabel = new Label("ternary_exit");
final Type widest = Type.widest(rhs.getType(), third.getType());
Type widest = Type.widest(rhs.getType(), third.getType());
if (rhs.getType().isArray() || third.getType().isArray()) { //loadArray creates a Java array type on the stack, calls global allocate, which creates a native array type
widest = Type.OBJECT;
}
load(lhs);
assert lhs.getType().isBoolean() : "lhs in ternary must be boolean";
@ -3159,7 +3154,6 @@ public final class CodeGenerator extends NodeOperatorVisitor {
}
private void epilogue() {
final Symbol targetSymbol = target.getSymbol();
final FunctionNode currentFunction = getCurrentFunctionNode();
/**
@ -3176,7 +3170,7 @@ public final class CodeGenerator extends NodeOperatorVisitor {
@Override
protected Node enterDefault(Node node) {
throw new AssertionError("Unexpected node " + node + " in store epilogue");
};
}
@Override
public Node enter(final UnaryNode node) {
@ -3261,7 +3255,7 @@ public final class CodeGenerator extends NodeOperatorVisitor {
private MethodEmitter globalAllocateArray(final ArrayType type) {
//make sure the native array is treated as an array type
return method.invokeStatic(Compiler.GLOBAL_OBJECT, "allocate", methodDescriptor(Object.class, type.getTypeClass()), type);
return method.invokeStatic(Compiler.GLOBAL_OBJECT, "allocate", "(" + type.getDescriptor() + ")Ljdk/nashorn/internal/objects/NativeArray;");
}
private MethodEmitter globalIsEval() {

View File

@ -49,19 +49,6 @@ public final class FunctionSignature {
/** valid Java descriptor string for function */
private final String descriptor;
/**
* Constructor
*
* Create a FunctionSignature given arguments as AST Nodes
*
* @param hasSelf does the function have a self slot?
* @param retType what is the return type
* @param args argument list of AST Nodes
*/
public FunctionSignature(final boolean hasSelf, final Type retType, final List<? extends Node> args) {
this(hasSelf, false, retType, FunctionSignature.typeArray(args));
}
/**
* Constructor
*
@ -82,11 +69,12 @@ public final class FunctionSignature {
* Create a FunctionSignature given arguments as AST Nodes
*
* @param hasSelf does the function have a self slot?
* @param hasCallee does the function need a callee variable
* @param retType what is the return type
* @param nArgs number of arguments
*/
public FunctionSignature(final boolean hasSelf, final Type retType, final int nArgs) {
this(hasSelf, false, retType, FunctionSignature.objectArgs(nArgs));
public FunctionSignature(final boolean hasSelf, final boolean hasCallee, final Type retType, final int nArgs) {
this(hasSelf, hasCallee, retType, FunctionSignature.objectArgs(nArgs));
}
/**
@ -99,7 +87,7 @@ public final class FunctionSignature {
* @param retType what is the return type
* @param argTypes argument list of AST Nodes
*/
public FunctionSignature(final boolean hasSelf, final boolean hasCallee, final Type retType, final Type... argTypes) {
private FunctionSignature(final boolean hasSelf, final boolean hasCallee, final Type retType, final Type... argTypes) {
final boolean isVarArg;
int count = 1;

View File

@ -1759,23 +1759,19 @@ public class MethodEmitter implements Emitter {
*
* @return function signature for stack contents
*/
private String getDynamicSignature(final Type returnType, final int argCount, final boolean hasSelf) {
final Iterator<Type> iter = stack.iterator();
final Type[] argTypes = new Type[argCount];
private String getDynamicSignature(final Type returnType, final int argCount) {
final Iterator<Type> iter = stack.iterator();
final Type[] paramTypes = new Type[argCount];
for (int i = argCount - 1; i >= 0; i--) {
argTypes[i] = iter.next();
paramTypes[i] = iter.next();
}
final FunctionSignature sig = new FunctionSignature(hasSelf, false, returnType, argTypes);
final String descriptor = Type.getMethodDescriptor(returnType, paramTypes);
for (int i = 0; i < argCount; i++) {
popType(argTypes[argCount - i - 1]);
}
for (int i = 0 ; i < sig.size() - argTypes.length; i++) {
popType(Type.OBJECT);
popType(paramTypes[argCount - i - 1]);
}
return sig.toString();
return descriptor;
}
/**
@ -1788,7 +1784,7 @@ public class MethodEmitter implements Emitter {
*/
public MethodEmitter dynamicNew(final int argCount, final int flags) {
debug("dynamic_new", "argcount=" + argCount);
final String signature = getDynamicSignature(Type.OBJECT, argCount, true);
final String signature = getDynamicSignature(Type.OBJECT, argCount);
method.visitInvokeDynamicInsn("dyn:new", signature, LINKERBOOTSTRAP, flags);
pushType(Type.OBJECT); //TODO fix result type
return this;
@ -1805,7 +1801,7 @@ public class MethodEmitter implements Emitter {
*/
public MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags) {
debug("dynamic_call", "args=" + argCount, "returnType=" + returnType);
final String signature = getDynamicSignature(returnType, argCount + 1, true);
final String signature = getDynamicSignature(returnType, argCount); // +1 because the function itself is the 1st parameter for dynamic calls (what you call - call target)
debug(" signature", signature);
method.visitInvokeDynamicInsn("dyn:call", signature, LINKERBOOTSTRAP, flags);
pushType(returnType);
@ -1824,7 +1820,7 @@ public class MethodEmitter implements Emitter {
*/
public MethodEmitter dynamicRuntimeCall(final String name, final Type returnType, final RuntimeNode.Request request) {
debug("dynamic_runtime_call", name, "args=" + request.getArity(), "returnType=" + returnType);
final String signature = getDynamicSignature(returnType, request.getArity(), false);
final String signature = getDynamicSignature(returnType, request.getArity());
debug(" signature", signature);
method.visitInvokeDynamicInsn(name, signature, RUNTIMEBOOTSTRAP);
pushType(returnType);
@ -2198,6 +2194,11 @@ public class MethodEmitter implements Emitter {
sb.append("this");
} else if (t.isObject()) {
String desc = t.getDescriptor();
int i;
for (i = 0; desc.charAt(i) == '[' && i < desc.length(); i++) {
sb.append('[');
}
desc = desc.substring(i);
final int slash = desc.lastIndexOf('/');
if (slash != -1) {
desc = desc.substring(slash + 1, desc.length() - 1);

View File

@ -327,17 +327,21 @@ public class RuntimeCallSite extends MutableCallSite {
}
}
addcheck = MH.explicitCastArguments(addcheck, type().changeReturnType(boolean.class));
guard = MH.guardWithTest(guard, addcheck,
guard = MH.guardWithTest(upcastGuard(guard), addcheck,
MH.dropArguments(MH.constant(boolean.class, false), 0, type().parameterArray()));
}
return MH.guardWithTest(guard, mh, fallback);
return MH.guardWithTest(upcastGuard(guard), mh, fallback);
}
// generic fallback
return MH.explicitCastArguments(Lookup.filterReturnType(GENERIC_METHODS.get(request.name()), type().returnType()), type());
}
private MethodHandle upcastGuard(final MethodHandle guard) {
return MH.asType(guard, type().changeReturnType(boolean.class));
}
/**
* This is public just so that the generated specialization code can
* use it to get the next wider typed method

View File

@ -163,7 +163,7 @@ public class SharedScopeCall {
slot++;
}
}
method.dynamicCall(returnType, paramTypes.length, flags);
method.dynamicCall(returnType, 2 + paramTypes.length, flags);
}
method._return(returnType);

View File

@ -1158,7 +1158,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
* @param initial object values.
* @return the new array
*/
public static Object allocate(final Object[] initial) {
public static NativeArray allocate(final Object[] initial) {
return new NativeArray(initial);
}
@ -1168,7 +1168,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
* @param initial number values.
* @return the new array
*/
public static Object allocate(final double[] initial) {
public static NativeArray allocate(final double[] initial) {
return new NativeArray(initial);
}
@ -1178,7 +1178,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
* @param initial number values.
* @return the new array
*/
public static Object allocate(final long[] initial) {
public static NativeArray allocate(final long[] initial) {
return new NativeArray(initial);
}
@ -1188,7 +1188,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
* @param initial number values.
* @return the new array
*/
public static Object allocate(final int[] initial) {
public static NativeArray allocate(final int[] initial) {
return new NativeArray(initial);
}

View File

@ -31,7 +31,6 @@ import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import javax.script.ScriptException;
import jdk.nashorn.api.scripting.NashornException;
import jdk.nashorn.api.scripting.NashornScriptEngine;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
import jdk.nashorn.internal.codegen.CompilerConstants.FieldAccess;
import jdk.nashorn.internal.scripts.JS$;

View File

@ -721,7 +721,15 @@ public abstract class ScriptFunction extends ScriptObject {
return hasCalleeParameter() ? MH.bindTo(bound, this) : bound;
}
/**
* Check whether the ScriptFunction has callee parameter
* @return true if callee parameter
*/
protected abstract boolean hasCalleeParameter();
/**
* Flag ScriptFunction as needing a callee parameter
*/
protected abstract void setHasCalleeParameter();
/**

View File

@ -86,7 +86,6 @@ import org.dynalang.dynalink.support.CallSiteDescriptorFactory;
* </ul>
*/
public abstract class ScriptObject extends PropertyListenerManager implements PropertyAccess {
/** Search fall back routine name for "no such method" */
@ -1710,7 +1709,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
if (methodHandle != null) {
assert methodHandle.type().returnType().equals(returnType);
final ScriptFunction getter = find.getGetterFunction();
if (find.isSelf()) {
return new GuardedInvocation(methodHandle, ObjectClassGenerator.OBJECT_FIELDS_ONLY &&
NashornCallSiteDescriptor.isFastScope(desc) && !property.canChangeType() ? null : guard);

View File

@ -0,0 +1,52 @@
/*
* 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.
*
* 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.
*/
/**
* Varargs based on too many parameters broke. Regression test.
*
* @test
* @run
*/
function f() {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
var a = arguments[i];
sum += a;
}
return sum;
}
var res;
res = f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249);
print(res);
res = f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250);
print(res);
res = f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251);
print(res);

View File

@ -0,0 +1,3 @@
31125
31375
31626