8023017: SUB missing for widest op == number for BinaryNode

Reviewed-by: sundar, jlaskey
This commit is contained in:
Marcus Lagergren 2013-08-16 18:51:53 +02:00
parent c5193485ad
commit 9de0661d63
19 changed files with 66 additions and 39 deletions

View file

@ -317,7 +317,8 @@ public final class ObjectClassGenerator {
final String className = getClassName(fieldCount); final String className = getClassName(fieldCount);
final String superName = className(ScriptObject.class); final String superName = className(ScriptObject.class);
final ClassEmitter classEmitter = newClassEmitter(className, superName); final ClassEmitter classEmitter = newClassEmitter(className, superName);
final List<String> initFields = addFields(classEmitter, fieldCount);
addFields(classEmitter, fieldCount);
final MethodEmitter init = newInitMethod(classEmitter); final MethodEmitter init = newInitMethod(classEmitter);
init.returnVoid(); init.returnVoid();

View file

@ -45,9 +45,11 @@ public abstract class ObjectCreator {
/** Code generator */ /** Code generator */
protected final CodeGenerator codegen; protected final CodeGenerator codegen;
private final boolean isScope; /** Property map */
private final boolean hasArguments; protected PropertyMap propertyMap;
protected PropertyMap propertyMap;
private final boolean isScope;
private final boolean hasArguments;
/** /**
* Constructor * Constructor

View file

@ -99,6 +99,7 @@ public final class BinaryNode extends Expression implements Assignment<Expressio
case DIV: case DIV:
case MOD: case MOD:
case MUL: case MUL:
case SUB:
case ASSIGN_DIV: case ASSIGN_DIV:
case ASSIGN_MOD: case ASSIGN_MOD:
case ASSIGN_MUL: case ASSIGN_MUL:

View file

@ -33,6 +33,14 @@ import jdk.nashorn.internal.codegen.Label;
* a {@code break} statement * a {@code break} statement
*/ */
public interface BreakableNode extends LexicalContextNode { public interface BreakableNode extends LexicalContextNode {
/**
* Ensure that any labels in this breakable node are unique so
* that new jumps won't go to old parts of the tree. Used for
* example for cloning finally blocks
*
* @param lc the lexical context
* @return node after labels have been made unique
*/
public abstract Node ensureUniqueLabels(final LexicalContext lc); public abstract Node ensureUniqueLabels(final LexicalContext lc);
/** /**

View file

@ -161,13 +161,13 @@ public final class IdentNode extends Expression implements PropertyKey, TypeOver
* converting to object, for example if the symbol is used as the left hand side of an * converting to object, for example if the symbol is used as the left hand side of an
* assignment such as in the code below.</p> * assignment such as in the code below.</p>
* *
* <pre>{@code * <pre>
* try { * try {
* return 2; * return 2;
* } finally { * } finally {
* return 3; * return 3;
* } * }
* }</pre> * }
* *
* @return true if can have callsite type * @return true if can have callsite type
*/ */

View file

@ -44,8 +44,14 @@ public interface LexicalContextNode {
Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor); Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor);
// Would be a default method on Java 8 // Would be a default method on Java 8
/**
* Helper class for accept for items of this lexical context, delegates to the
* subclass accept and makes sure that the node is on the context before accepting
* and gets popped after accepting (and that the stack is consistent in that the
* node has been replaced with the possible new node resulting in visitation)
*/
static class Acceptor { static class Acceptor {
static Node accept(LexicalContextNode node, final NodeVisitor<? extends LexicalContext> visitor) { static Node accept(final LexicalContextNode node, final NodeVisitor<? extends LexicalContext> visitor) {
final LexicalContext lc = visitor.getLexicalContext(); final LexicalContext lc = visitor.getLexicalContext();
lc.push(node); lc.push(node);
final LexicalContextNode newNode = (LexicalContextNode)node.accept(lc, visitor); final LexicalContextNode newNode = (LexicalContextNode)node.accept(lc, visitor);

View file

@ -266,9 +266,8 @@ public final class NativeArguments extends ScriptObject {
final ScriptObject proto = global.getObjectPrototype(); final ScriptObject proto = global.getObjectPrototype();
if (isStrict) { if (isStrict) {
return new NativeStrictArguments(arguments, numParams, proto, global.getStrictArgumentsMap()); return new NativeStrictArguments(arguments, numParams, proto, global.getStrictArgumentsMap());
} else {
return new NativeArguments(arguments, callee, numParams, proto, global.getArgumentsMap());
} }
return new NativeArguments(arguments, callee, numParams, proto, global.getArgumentsMap());
} }
/** /**

View file

@ -638,9 +638,9 @@ public final class NativeArray extends ScriptObject {
if (isScriptArray || obj instanceof Iterable || (obj != null && obj.getClass().isArray())) { if (isScriptArray || obj instanceof Iterable || (obj != null && obj.getClass().isArray())) {
final Iterator<Object> iter = arrayLikeIterator(obj, true); final Iterator<Object> iter = arrayLikeIterator(obj, true);
if (iter.hasNext()) { if (iter.hasNext()) {
for(int i = 0; iter.hasNext(); ++i) { for (int i = 0; iter.hasNext(); ++i) {
final Object value = iter.next(); final Object value = iter.next();
if(value == ScriptRuntime.UNDEFINED && isScriptObject && !((ScriptObject)obj).has(i)) { if (value == ScriptRuntime.UNDEFINED && isScriptObject && !((ScriptObject)obj).has(i)) {
// TODO: eventually rewrite arrayLikeIterator to use a three-state enum for handling // TODO: eventually rewrite arrayLikeIterator to use a three-state enum for handling
// UNDEFINED instead of an "includeUndefined" boolean with states SKIP, INCLUDE, // UNDEFINED instead of an "includeUndefined" boolean with states SKIP, INCLUDE,
// RETURN_EMPTY. Until then, this is how we'll make sure that empty elements don't make it // RETURN_EMPTY. Until then, this is how we'll make sure that empty elements don't make it

View file

@ -160,10 +160,10 @@ public class Parser extends AbstractParser {
if (this.scripting) { if (this.scripting) {
this.lineInfoReceiver = new Lexer.LineInfoReceiver() { this.lineInfoReceiver = new Lexer.LineInfoReceiver() {
@Override @Override
public void lineInfo(final int line, final int linePosition) { public void lineInfo(final int receiverLine, final int receiverLinePosition) {
// update the parser maintained line information // update the parser maintained line information
Parser.this.line = line; Parser.this.line = receiverLine;
Parser.this.linePosition = linePosition; Parser.this.linePosition = receiverLinePosition;
} }
}; };
} else { } else {

View file

@ -48,6 +48,7 @@ import java.security.Permissions;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.security.ProtectionDomain; import java.security.ProtectionDomain;
import java.util.Map; import java.util.Map;
import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.util.CheckClassAdapter; import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.api.scripting.ScriptObjectMirror;
@ -888,6 +889,7 @@ public final class Context {
return script; return script;
} }
@SuppressWarnings("static-method")
private ScriptLoader createNewLoader() { private ScriptLoader createNewLoader() {
return AccessController.doPrivileged( return AccessController.doPrivileged(
new PrivilegedAction<ScriptLoader>() { new PrivilegedAction<ScriptLoader>() {

View file

@ -47,7 +47,7 @@ import jdk.nashorn.internal.parser.TokenType;
* This is a subclass that represents a script function that may be regenerated, * This is a subclass that represents a script function that may be regenerated,
* for example with specialization based on call site types, or lazily generated. * for example with specialization based on call site types, or lazily generated.
* The common denominator is that it can get new invokers during its lifespan, * The common denominator is that it can get new invokers during its lifespan,
* unlike {@link FinalScriptFunctionData} * unlike {@code FinalScriptFunctionData}
*/ */
public final class RecompilableScriptFunctionData extends ScriptFunctionData { public final class RecompilableScriptFunctionData extends ScriptFunctionData {

View file

@ -553,19 +553,18 @@ public abstract class ScriptFunction extends ScriptObject {
private static MethodHandle bindToNameIfNeeded(final MethodHandle methodHandle, final String bindName) { private static MethodHandle bindToNameIfNeeded(final MethodHandle methodHandle, final String bindName) {
if (bindName == null) { if (bindName == null) {
return methodHandle; return methodHandle;
} else {
// if it is vararg method, we need to extend argument array with
// a new zeroth element that is set to bindName value.
final MethodType methodType = methodHandle.type();
final int parameterCount = methodType.parameterCount();
final boolean isVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray();
if (isVarArg) {
return MH.filterArguments(methodHandle, 1, MH.insertArguments(ADD_ZEROTH_ELEMENT, 1, bindName));
} else {
return MH.insertArguments(methodHandle, 1, bindName);
}
} }
// if it is vararg method, we need to extend argument array with
// a new zeroth element that is set to bindName value.
final MethodType methodType = methodHandle.type();
final int parameterCount = methodType.parameterCount();
final boolean isVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray();
if (isVarArg) {
return MH.filterArguments(methodHandle, 1, MH.insertArguments(ADD_ZEROTH_ELEMENT, 1, bindName));
}
return MH.insertArguments(methodHandle, 1, bindName);
} }
/** /**

View file

@ -2012,9 +2012,10 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc); final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc);
if (find != null) { if (find != null) {
final Object value = getObjectValue(find); final Object value = getObjectValue(find);
ScriptFunction func = null; ScriptFunction func = null;
MethodHandle methodHandle = null; MethodHandle methodHandle = null;
if (value instanceof ScriptFunction) { if (value instanceof ScriptFunction) {
func = (ScriptFunction)value; func = (ScriptFunction)value;
methodHandle = getCallMethodHandle(func, desc.getMethodType(), name); methodHandle = getCallMethodHandle(func, desc.getMethodType(), name);
@ -3219,6 +3220,11 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
return property; return property;
} }
/**
* Write a value to a spill slot
* @param slot the slot index
* @param value the value
*/
protected final void setSpill(final int slot, final Object value) { protected final void setSpill(final int slot, final Object value) {
if (spill == null) { if (spill == null) {
// create new spill. // create new spill.
@ -3233,6 +3239,11 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
spill[slot] = value; spill[slot] = value;
} }
/**
* Get a value from a spill slot
* @param slot the slot index
* @return the value in the spill slot with the given index
*/
protected Object getSpill(final int slot) { protected Object getSpill(final int slot) {
return spill != null && slot < spill.length ? spill[slot] : null; return spill != null && slot < spill.length ? spill[slot] : null;
} }

View file

@ -132,7 +132,7 @@ abstract public class ArrayLikeIterator<T> implements Iterator<T> {
} }
if (obj instanceof List) { if (obj instanceof List) {
return new JavaListIterator((List)obj, includeUndefined); return new JavaListIterator((List<?>)obj, includeUndefined);
} }
if (obj != null && obj.getClass().isArray()) { if (obj != null && obj.getClass().isArray()) {
@ -165,7 +165,7 @@ abstract public class ArrayLikeIterator<T> implements Iterator<T> {
} }
if (obj instanceof List) { if (obj instanceof List) {
return new ReverseJavaListIterator((List)obj, includeUndefined); return new ReverseJavaListIterator((List<?>)obj, includeUndefined);
} }
if (obj != null && obj.getClass().isArray()) { if (obj != null && obj.getClass().isArray()) {

View file

@ -98,9 +98,8 @@ final class LongArrayData extends ArrayData {
final int length = (int) length(); final int length = (int) length();
if (type == Double.class) { if (type == Double.class) {
return new NumberArrayData(LongArrayData.toDoubleArray(array, length), length); return new NumberArrayData(LongArrayData.toDoubleArray(array, length), length);
} else {
return new ObjectArrayData(LongArrayData.toObjectArray(array, length), length);
} }
return new ObjectArrayData(LongArrayData.toObjectArray(array, length), length);
} }
@Override @Override

View file

@ -60,7 +60,7 @@ class SparseArrayData extends ArrayData {
@Override @Override
public ArrayData copy() { public ArrayData copy() {
return new SparseArrayData(underlying.copy(), length(), new TreeMap<Long, Object>(sparseMap)); return new SparseArrayData(underlying.copy(), length(), new TreeMap<>(sparseMap));
} }
@Override @Override

View file

@ -29,7 +29,7 @@ import jdk.internal.dynalink.beans.BeansLinker;
/** /**
* Represents a Dynalink dynamic method bound to a receiver. Note that objects of this class are just the tuples of * Represents a Dynalink dynamic method bound to a receiver. Note that objects of this class are just the tuples of
* a method and a bound this, without any behavior. All the behavior is defined in the {@link BoundDynamicMethodLinker}. * a method and a bound this, without any behavior. All the behavior is defined in the {@code BoundDynamicMethodLinker}.
*/ */
final class BoundDynamicMethod { final class BoundDynamicMethod {
private final Object dynamicMethod; private final Object dynamicMethod;

View file

@ -37,7 +37,7 @@ import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
import jdk.internal.dynalink.support.Guards; import jdk.internal.dynalink.support.Guards;
/** /**
* Links {@link BoundDynamicMethod} objects. Passes through to Dynalink's BeansLinker for linking a dynamic method * Links {@code BoundDynamicMethod} objects. Passes through to Dynalink's BeansLinker for linking a dynamic method
* (they only respond to "dyn:call"), and modifies the returned invocation to deal with the receiver binding. * (they only respond to "dyn:call"), and modifies the returned invocation to deal with the receiver binding.
*/ */
final class BoundDynamicMethodLinker implements TypeBasedGuardingDynamicLinker { final class BoundDynamicMethodLinker implements TypeBasedGuardingDynamicLinker {

View file

@ -114,9 +114,8 @@ final class JavaAdapterClassLoader {
if(name.equals(className)) { if(name.equals(className)) {
assert classBytes != null : "what? already cleared .class bytes!!"; assert classBytes != null : "what? already cleared .class bytes!!";
return defineClass(name, classBytes, 0, classBytes.length, GENERATED_PROTECTION_DOMAIN); return defineClass(name, classBytes, 0, classBytes.length, GENERATED_PROTECTION_DOMAIN);
} else {
throw new ClassNotFoundException(name);
} }
throw new ClassNotFoundException(name);
} }
}; };
} }