diff options
Diffstat (limited to 'src/jdk/nashorn/internal/ir/RuntimeNode.java')
-rw-r--r-- | src/jdk/nashorn/internal/ir/RuntimeNode.java | 133 |
1 files changed, 111 insertions, 22 deletions
diff --git a/src/jdk/nashorn/internal/ir/RuntimeNode.java b/src/jdk/nashorn/internal/ir/RuntimeNode.java index 269cb905..4eca8ff0 100644 --- a/src/jdk/nashorn/internal/ir/RuntimeNode.java +++ b/src/jdk/nashorn/internal/ir/RuntimeNode.java @@ -25,10 +25,12 @@ package jdk.nashorn.internal.ir; -import java.util.ArrayList; +import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; + import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.function.Function; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.annotations.Immutable; import jdk.nashorn.internal.ir.visitor.NodeVisitor; @@ -38,7 +40,8 @@ import jdk.nashorn.internal.parser.TokenType; * IR representation for a runtime call. */ @Immutable -public class RuntimeNode extends Expression { +public class RuntimeNode extends Expression implements Optimistic { + private static final long serialVersionUID = 1L; /** * Request enum used for meta-information about the runtime request @@ -77,7 +80,11 @@ public class RuntimeNode extends Expression { /** !== operator with at least one object */ NE_STRICT(TokenType.NE_STRICT, Type.BOOLEAN, 2, true), /** != operator with at least one object */ - NE(TokenType.NE, Type.BOOLEAN, 2, true); + NE(TokenType.NE, Type.BOOLEAN, 2, true), + /** is undefined */ + IS_UNDEFINED(TokenType.EQ_STRICT, Type.BOOLEAN, 2), + /** is not undefined */ + IS_NOT_UNDEFINED(TokenType.NE_STRICT, Type.BOOLEAN, 2); /** token type */ private final TokenType tokenType; @@ -163,9 +170,14 @@ public class RuntimeNode extends Expression { * @param node the node * @return request type */ - public static Request requestFor(final Node node) { - assert node.isComparison(); + public static Request requestFor(final Expression node) { switch (node.tokenType()) { + case TYPEOF: + return Request.TYPEOF; + case IN: + return Request.IN; + case INSTANCEOF: + return Request.INSTANCEOF; case EQ_STRICT: return Request.EQ_STRICT; case NE_STRICT: @@ -189,6 +201,17 @@ public class RuntimeNode extends Expression { } /** + * Is this an undefined check? + * + * @param request request + * + * @return true if undefined check + */ + public static boolean isUndefinedCheck(final Request request) { + return request == IS_UNDEFINED || request == IS_NOT_UNDEFINED; + } + + /** * Is this an EQ or EQ_STRICT? * * @param request a request @@ -211,6 +234,17 @@ public class RuntimeNode extends Expression { } /** + * Is this strict? + * + * @param request a request + * + * @return true if script + */ + public static boolean isStrict(final Request request) { + return request == EQ_STRICT || request == NE_STRICT; + } + + /** * If this request can be reversed, return the reverse request * Eq EQ {@literal ->} NE. * @@ -285,6 +319,8 @@ public class RuntimeNode extends Expression { case LT: case GE: case GT: + case IS_UNDEFINED: + case IS_NOT_UNDEFINED: return true; default: return false; @@ -301,6 +337,8 @@ public class RuntimeNode extends Expression { /** is final - i.e. may not be removed again, lower in the code pipeline */ private final boolean isFinal; + private final int programPoint; + /** * Constructor * @@ -315,14 +353,16 @@ public class RuntimeNode extends Expression { this.request = request; this.args = args; this.isFinal = false; + this.programPoint = INVALID_PROGRAM_POINT; } - private RuntimeNode(final RuntimeNode runtimeNode, final Request request, final boolean isFinal, final List<Expression> args) { + private RuntimeNode(final RuntimeNode runtimeNode, final Request request, final boolean isFinal, final List<Expression> args, final int programPoint) { super(runtimeNode); this.request = request; this.args = args; this.isFinal = isFinal; + this.programPoint = programPoint; } /** @@ -361,6 +401,7 @@ public class RuntimeNode extends Expression { this.request = request; this.args = args; this.isFinal = false; + this.programPoint = parent instanceof Optimistic ? ((Optimistic)parent).getProgramPoint() : INVALID_PROGRAM_POINT; } /** @@ -370,20 +411,32 @@ public class RuntimeNode extends Expression { * @param request the request */ public RuntimeNode(final UnaryNode parent, final Request request) { - this(parent, request, parent.rhs()); + this(parent, request, parent.getExpression()); } /** - * Constructor + * Constructor used to replace a binary node with a runtime request. * * @param parent parent node from which to inherit source, token, finish and arguments - * @param request the request */ - public RuntimeNode(final BinaryNode parent, final Request request) { - this(parent, request, parent.lhs(), parent.rhs()); + public RuntimeNode(final BinaryNode parent) { + this(parent, Request.requestFor(parent), parent.lhs(), parent.rhs()); } /** + * Reset the request for this runtime node + * @param request request + * @return new runtime node or same if same request + */ + public RuntimeNode setRequest(final Request request) { + if (this.request == request) { + return this; + } + return new RuntimeNode(this, request, isFinal, args, programPoint); + } + + + /** * Is this node final - i.e. it can never be replaced with other nodes again * @return true if final */ @@ -400,32 +453,28 @@ public class RuntimeNode extends Expression { if (this.isFinal == isFinal) { return this; } - return new RuntimeNode(this, request, isFinal, args); + return new RuntimeNode(this, request, isFinal, args, programPoint); } /** * Return type for the ReferenceNode */ @Override - public Type getType() { + public Type getType(final Function<Symbol, Type> localVariableTypes) { return request.getReturnType(); } @Override public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { if (visitor.enterRuntimeNode(this)) { - final List<Expression> newArgs = new ArrayList<>(); - for (final Node arg : args) { - newArgs.add((Expression)arg.accept(visitor)); - } - return visitor.leaveRuntimeNode(setArgs(newArgs)); + return visitor.leaveRuntimeNode(setArgs(Node.accept(visitor, args))); } return this; } @Override - public void toString(final StringBuilder sb) { + public void toString(final StringBuilder sb, final boolean printType) { sb.append("ScriptRuntime."); sb.append(request); sb.append('('); @@ -439,7 +488,7 @@ public class RuntimeNode extends Expression { first = false; } - arg.toString(sb); + arg.toString(sb, printType); } sb.append(')'); @@ -453,11 +502,16 @@ public class RuntimeNode extends Expression { return Collections.unmodifiableList(args); } - private RuntimeNode setArgs(final List<Expression> args) { + /** + * Set the arguments of this runtime node + * @param args new arguments + * @return new runtime node, or identical if no change + */ + public RuntimeNode setArgs(final List<Expression> args) { if (this.args == args) { return this; } - return new RuntimeNode(this, request, isFinal, args); + return new RuntimeNode(this, request, isFinal, args, programPoint); } /** @@ -483,4 +537,39 @@ public class RuntimeNode extends Expression { } return true; } + +//TODO these are blank for now: + + @Override + public int getProgramPoint() { + return programPoint; + } + + @Override + public RuntimeNode setProgramPoint(final int programPoint) { + if(this.programPoint == programPoint) { + return this; + } + return new RuntimeNode(this, request, isFinal, args, programPoint); + } + + @Override + public boolean canBeOptimistic() { + return false; + } + + @Override + public Type getMostOptimisticType() { + return getType(); + } + + @Override + public Type getMostPessimisticType() { + return getType(); + } + + @Override + public RuntimeNode setType(final Type type) { + return this; + } } |