8073733: TypeError messages with "call" and "new" could be improved

Reviewed-by: attila, mhaupt
This commit is contained in:
Athijegannathan Sundararajan 2015-08-04 18:18:54 +05:30
parent d2e2494f9e
commit b2ad94c8e5
10 changed files with 322 additions and 231 deletions

View File

@ -1480,7 +1480,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
@Override
void consumeStack() {
dynamicCall(2 + argsCount, flags);
dynamicCall(2 + argsCount, flags, ident.getName());
}
}.emit();
}
@ -1538,7 +1538,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
@Override
void consumeStack() {
// Ordinary call
dynamicCall(2 + argsCount, flags);
dynamicCall(2 + argsCount, flags, "eval");
method._goto(eval_done);
method.label(invoke_direct_eval);
@ -1610,7 +1610,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
@Override
void consumeStack() {
dynamicCall(2 + argCount, flags);
dynamicCall(2 + argCount, flags, node.getProperty());
}
}.emit();
@ -1637,7 +1637,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
void consumeStack() {
final int flags = getCallSiteFlags();
//assert callNodeType.equals(callee.getReturnType()) : callNodeType + " != " + callee.getReturnType();
dynamicCall(2 + argsCount, flags);
dynamicCall(2 + argsCount, flags, origCallee.getName());
}
}.emit();
return false;
@ -1667,7 +1667,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
@Override
void consumeStack() {
final int flags = getCallSiteFlags();
dynamicCall(2 + argsCount, flags);
dynamicCall(2 + argsCount, flags, null);
}
}.emit();
return false;
@ -1687,7 +1687,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
@Override
void consumeStack() {
final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
dynamicCall(2 + argsCount, flags);
dynamicCall(2 + argsCount, flags, null);
}
}.emit();
return false;
@ -3707,10 +3707,12 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
final CallNode callNode = (CallNode)unaryNode.getExpression();
final List<Expression> args = callNode.getArgs();
final Expression func = callNode.getFunction();
// Load function reference.
loadExpressionAsObject(callNode.getFunction()); // must detect type error
loadExpressionAsObject(func); // must detect type error
method.dynamicNew(1 + loadArgs(args), getCallSiteFlags());
method.dynamicNew(1 + loadArgs(args), getCallSiteFlags(),
func instanceof IdentNode? ((IdentNode)func).getName() : null);
}
private void loadNOT(final UnaryNode unaryNode) {
@ -4818,11 +4820,11 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
return method.dynamicGetIndex(resultBounds.within(expression.getType()), nonOptimisticFlags(flags), isMethod);
}
MethodEmitter dynamicCall(final int argCount, final int flags) {
MethodEmitter dynamicCall(final int argCount, final int flags, final String msg) {
if (isOptimistic) {
return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags));
return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags), msg);
}
return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags));
return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags), msg);
}
int getOptimisticFlags(final int flags) {

View File

@ -2132,10 +2132,25 @@ public class MethodEmitter {
* @return the method emitter
*/
MethodEmitter dynamicNew(final int argCount, final int flags) {
return dynamicNew(argCount, flags, null);
}
/**
* Generate a dynamic new
*
* @param argCount number of arguments
* @param flags callsite flags
* @param msg additional message to be used when reporting error
*
* @return the method emitter
*/
MethodEmitter dynamicNew(final int argCount, final int flags, final String msg) {
assert !isOptimistic(flags);
debug("dynamic_new", "argcount=", argCount);
final String signature = getDynamicSignature(Type.OBJECT, argCount);
method.visitInvokeDynamicInsn("dyn:new", signature, LINKERBOOTSTRAP, flags);
method.visitInvokeDynamicInsn(
msg != null && msg.length() < LARGE_STRING_THRESHOLD? "dyn:new:" + NameCodec.encode(msg) : "dyn:new",
signature, LINKERBOOTSTRAP, flags);
pushType(Type.OBJECT); //TODO fix result type
return this;
}
@ -2150,10 +2165,26 @@ public class MethodEmitter {
* @return the method emitter
*/
MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags) {
return dynamicCall(returnType, argCount, flags, null);
}
/**
* Generate a dynamic call
*
* @param returnType return type
* @param argCount number of arguments
* @param flags callsite flags
* @param msg additional message to be used when reporting error
*
* @return the method emitter
*/
MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags, final String msg) {
debug("dynamic_call", "args=", argCount, "returnType=", returnType);
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);
method.visitInvokeDynamicInsn(
msg != null && msg.length() < LARGE_STRING_THRESHOLD? "dyn:call:" + NameCodec.encode(msg) : "dyn:call",
signature, LINKERBOOTSTRAP, flags);
pushType(returnType);
return this;

View File

@ -169,7 +169,7 @@ class SharedScopeCall {
slot += type.getSlots();
}
// Shared scope calls disabled in optimistic world. TODO is this right?
method.dynamicCall(returnType, 2 + paramTypes.length, flags);
method.dynamicCall(returnType, 2 + paramTypes.length, flags, symbol.getName());
}
method._return(returnType);

View File

@ -96,8 +96,12 @@ public final class Undefined extends DefaultPropertyAccess {
switch (operator) {
case "new":
case "call":
throw lookupTypeError("cant.call.undefined", desc);
case "call": {
final String name = desc.getNameTokenCount() > 2? desc.getNameToken(2) : null;
final String msg = name != null? "cant.call.undefined.arg" : "cant.call.undefined";
throw typeError(msg, name);
}
case "callMethod":
throw lookupTypeError("cant.read.property.of.undefined", desc);
// NOTE: we support getElem and setItem as JavaScript doesn't distinguish items from properties. Nashorn itself
@ -125,7 +129,8 @@ public final class Undefined extends DefaultPropertyAccess {
}
private static ECMAException lookupTypeError(final String msg, final CallSiteDescriptor desc) {
return typeError(msg, desc.getNameTokenCount() > 2 ? desc.getNameToken(2) : null);
final String name = desc.getNameToken(2);
return typeError(msg, name != null && !name.isEmpty()? name : null);
}
private static final MethodHandle GET_METHOD = findOwnMH("get", Object.class, Object.class);

View File

@ -150,7 +150,7 @@ public final class NashornCallSiteDescriptor extends AbstractCallSiteDescriptor
public static NashornCallSiteDescriptor get(final MethodHandles.Lookup lookup, final String name,
final MethodType methodType, final int flags) {
final String[] tokenizedName = CallSiteDescriptorFactory.tokenizeName(name);
assert tokenizedName.length == 2 || tokenizedName.length == 3;
assert tokenizedName.length >= 2;
assert "dyn".equals(tokenizedName[0]);
assert tokenizedName[1] != null;
// TODO: see if we can move mangling/unmangling into Dynalink

View File

@ -87,6 +87,7 @@ type.error.no.reflection.with.classfilter=Java reflection not supported when cla
# operations not permitted on undefined
type.error.cant.call.undefined=Cannot call undefined
type.error.cant.call.undefined.arg=Cannot call "{0}" that has undefined value
type.error.cant.read.property.of.undefined=Cannot read property "{0}" from undefined
type.error.cant.set.property.of.undefined=Cannot set property "{0}" of undefined
type.error.cant.delete.property.of.undefined=Cannot delete property "{0}" of undefined

View File

@ -1,182 +1,182 @@
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
TypeError: Cannot call undefined
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such method _,0
no such method _,1
no such method _,2
no such method _,3
no such method _,4
no such method _,5
no such method _,6
no such method _,7
no such method _,8
no such method _,9
no such method _,10
no such method _,11
no such method _,12
no such method _,13
no such method _,14
no such method _,15
no such method _,16
no such method _,17
no such method _,18
no such method _,19
no such method _,20
no such method _,21
no such method _,22
no such method _,23
no such method _,24
no such method _,25
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
TypeError: Cannot call undefined
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
TypeError: Cannot call "_" that has undefined value
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such method _,0
no such method _,1
no such method _,2
no such method _,3
no such method _,4
no such method _,5
no such method _,6
no such method _,7
no such method _,8
no such method _,9
no such method _,10
no such method _,11
no such method _,12
no such method _,13
no such method _,14
no such method _,15
no such method _,16
no such method _,17
no such method _,18
no such method _,19
no such method _,20
no such method _,21
no such method _,22
no such method _,23
no such method _,24
no such method _,25
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
TypeError: Cannot call "_" that has undefined value
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _
no such property _

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2015, 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.
*/
/**
* JDK-8073733: TypeError messages with "call" and "new" could be improved
*
* @test
* @run
*/
var func = undefined;
try {
func();
} catch (e) {
print(e);
}
var obj = {};
try {
obj.foo();
} catch (e) {
print(e);
}
try {
new func();
} catch (e) {
print(e);
}

View File

@ -0,0 +1,3 @@
TypeError: Cannot call "func" that has undefined value
TypeError: Cannot call "foo" that has undefined value
TypeError: Cannot call "func" that has undefined value

View File

@ -1,31 +1,31 @@
Error is a function
EvalError is a function
RangeError is a function
ReferenceError is a function
SyntaxError is a function
TypeError is a function
URIError is a function
Error.arity 1
EvalError.arity 1
RangeError.arity 1
ReferenceError.arity 1
SyntaxError.arity 1
TypeError.arity 1
URIError.arity 1
true
my error
Error
thrown @ 49
true
ReferenceError
"foo" is not defined
true
TypeError
Cannot call undefined
Error
EvalError
RangeError
ReferenceError
SyntaxError
TypeError
URIError
Error is a function
EvalError is a function
RangeError is a function
ReferenceError is a function
SyntaxError is a function
TypeError is a function
URIError is a function
Error.arity 1
EvalError.arity 1
RangeError.arity 1
ReferenceError.arity 1
SyntaxError.arity 1
TypeError.arity 1
URIError.arity 1
true
my error
Error
thrown @ 49
true
ReferenceError
"foo" is not defined
true
TypeError
Cannot call "foo_method" that has undefined value
Error
EvalError
RangeError
ReferenceError
SyntaxError
TypeError
URIError