aboutsummaryrefslogtreecommitdiff
path: root/src/jdk/nashorn/internal/ir/IdentNode.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jdk/nashorn/internal/ir/IdentNode.java')
-rw-r--r--src/jdk/nashorn/internal/ir/IdentNode.java237
1 files changed, 198 insertions, 39 deletions
diff --git a/src/jdk/nashorn/internal/ir/IdentNode.java b/src/jdk/nashorn/internal/ir/IdentNode.java
index 30e8ed11..7059734d 100644
--- a/src/jdk/nashorn/internal/ir/IdentNode.java
+++ b/src/jdk/nashorn/internal/ir/IdentNode.java
@@ -28,29 +28,44 @@ package jdk.nashorn.internal.ir;
import static jdk.nashorn.internal.codegen.CompilerConstants.__DIR__;
import static jdk.nashorn.internal.codegen.CompilerConstants.__FILE__;
import static jdk.nashorn.internal.codegen.CompilerConstants.__LINE__;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+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;
+import jdk.nashorn.internal.parser.Token;
+import jdk.nashorn.internal.parser.TokenType;
/**
* IR representation for an identifier.
*/
@Immutable
-public final class IdentNode extends Expression implements PropertyKey, FunctionCall {
+public final class IdentNode extends Expression implements PropertyKey, FunctionCall, Optimistic, JoinPredecessor {
+ private static final long serialVersionUID = 1L;
+
private static final int PROPERTY_NAME = 1 << 0;
private static final int INITIALIZED_HERE = 1 << 1;
private static final int FUNCTION = 1 << 2;
private static final int FUTURESTRICT_NAME = 1 << 3;
+ private static final int IS_DECLARED_HERE = 1 << 4;
+ private static final int IS_DEAD = 1 << 5;
/** Identifier. */
private final String name;
- /** Type for a callsite, e.g. X in a get()X or a set(X)V */
- private final Type callSiteType;
+ /** Optimistic type */
+ private final Type type;
private final int flags;
+ private final int programPoint;
+
+ private final LocalVariableConversion conversion;
+
+ private Symbol symbol;
+
+
/**
* Constructor
*
@@ -60,16 +75,21 @@ public final class IdentNode extends Expression implements PropertyKey, Function
*/
public IdentNode(final long token, final int finish, final String name) {
super(token, finish);
- this.name = name.intern();
- this.callSiteType = null;
+ this.name = name;
+ this.type = null;
this.flags = 0;
+ this.programPoint = INVALID_PROGRAM_POINT;
+ this.conversion = null;
}
- private IdentNode(final IdentNode identNode, final String name, final Type callSiteType, final int flags) {
+ private IdentNode(final IdentNode identNode, final String name, final Type type, final int flags, final int programPoint, final LocalVariableConversion conversion) {
super(identNode);
this.name = name;
- this.callSiteType = callSiteType;
+ this.type = type;
this.flags = flags;
+ this.programPoint = programPoint;
+ this.conversion = conversion;
+ this.symbol = identNode.symbol;
}
/**
@@ -79,24 +99,33 @@ public final class IdentNode extends Expression implements PropertyKey, Function
*/
public IdentNode(final IdentNode identNode) {
super(identNode);
- this.name = identNode.getName();
- this.callSiteType = null;
- this.flags = identNode.flags;
+ this.name = identNode.getName();
+ this.type = identNode.type;
+ this.flags = identNode.flags;
+ this.conversion = identNode.conversion;
+ this.programPoint = INVALID_PROGRAM_POINT;
+ this.symbol = identNode.symbol;
}
- @Override
- public Type getType() {
- return callSiteType == null ? super.getType() : callSiteType;
+ /**
+ * Creates an identifier for the symbol. Normally used by code generator for creating temporary storage identifiers
+ * that must contain both a symbol and a type.
+ * @param symbol the symbol to create a temporary identifier for.
+ * @return a temporary identifier for the symbol.
+ */
+ public static IdentNode createInternalIdentifier(final Symbol symbol) {
+ return new IdentNode(Token.toDesc(TokenType.IDENT, 0, 0), 0, symbol.getName()).setSymbol(symbol);
}
@Override
- public boolean isAtom() {
- return true;
- }
-
- private boolean hasCallSiteType() {
- //this is an identity that's part of a getter or setter
- return callSiteType != null;
+ public Type getType(final Function<Symbol, Type> localVariableTypes) {
+ if(type != null) {
+ return type;
+ } else if(symbol != null && symbol.isScope()) {
+ return Type.OBJECT;
+ }
+ final Type symbolType = localVariableTypes.apply(symbol);
+ return symbolType == null ? Type.UNDEFINED : symbolType;
}
/**
@@ -114,14 +143,10 @@ public final class IdentNode extends Expression implements PropertyKey, Function
}
@Override
- public void toString(final StringBuilder sb) {
- if (hasCallSiteType()) {
- sb.append('{');
- final String desc = getType().getDescriptor();
- sb.append(desc.charAt(desc.length() - 1) == ';' ? 'O' : getType().getDescriptor());
- sb.append('}');
+ public void toString(final StringBuilder sb, final boolean printType) {
+ if (printType) {
+ optimisticTypeToString(sb, symbol == null || !symbol.hasSlot());
}
-
sb.append(name);
}
@@ -144,11 +169,36 @@ public final class IdentNode extends Expression implements PropertyKey, Function
}
/**
+ * Return the Symbol the compiler has assigned to this identifier. The symbol is a description of the storage
+ * location for the identifier.
+ *
+ * @return the symbol
+ */
+ public Symbol getSymbol() {
+ return symbol;
+ }
+
+ /**
+ * Assign a symbol to this identifier. See {@link IdentNode#getSymbol()} for explanation of what a symbol is.
+ *
+ * @param symbol the symbol
+ * @return new node
+ */
+ public IdentNode setSymbol(final Symbol symbol) {
+ if (this.symbol == symbol) {
+ return this;
+ }
+ final IdentNode newIdent = (IdentNode)clone();
+ newIdent.symbol = symbol;
+ return newIdent;
+ }
+
+ /**
* Check if this IdentNode is a property name
* @return true if this is a property name
*/
public boolean isPropertyName() {
- return (flags & PROPERTY_NAME) != 0;
+ return (flags & PROPERTY_NAME) == PROPERTY_NAME;
}
/**
@@ -159,7 +209,7 @@ public final class IdentNode extends Expression implements PropertyKey, Function
if (isPropertyName()) {
return this;
}
- return new IdentNode(this, name, callSiteType, flags | PROPERTY_NAME);
+ return new IdentNode(this, name, type, flags | PROPERTY_NAME, programPoint, conversion);
}
/**
@@ -167,7 +217,7 @@ public final class IdentNode extends Expression implements PropertyKey, Function
* @return true if this is a future strict name
*/
public boolean isFutureStrictName() {
- return (flags & FUTURESTRICT_NAME) != 0;
+ return (flags & FUTURESTRICT_NAME) == FUTURESTRICT_NAME;
}
/**
@@ -178,7 +228,7 @@ public final class IdentNode extends Expression implements PropertyKey, Function
if (isFutureStrictName()) {
return this;
}
- return new IdentNode(this, name, callSiteType, flags | FUTURESTRICT_NAME);
+ return new IdentNode(this, name, type, flags | FUTURESTRICT_NAME, programPoint, conversion);
}
/**
@@ -186,7 +236,7 @@ public final class IdentNode extends Expression implements PropertyKey, Function
* @return true if IdentNode is initialized on creation
*/
public boolean isInitializedHere() {
- return (flags & INITIALIZED_HERE) != 0;
+ return (flags & INITIALIZED_HERE) == INITIALIZED_HERE;
}
/**
@@ -197,22 +247,69 @@ public final class IdentNode extends Expression implements PropertyKey, Function
if (isInitializedHere()) {
return this;
}
- return new IdentNode(this, name, callSiteType, flags | INITIALIZED_HERE);
+ return new IdentNode(this, name, type, flags | INITIALIZED_HERE, programPoint, conversion);
+ }
+
+ /**
+ * Is this a LET or CONST identifier used before its declaration?
+ *
+ * @return true if identifier is dead
+ */
+ public boolean isDead() {
+ return (flags & IS_DEAD) != 0;
+ }
+
+ /**
+ * Flag this IdentNode as a LET or CONST identifier used before its declaration.
+ *
+ * @return a new IdentNode equivalent to this but marked as dead.
+ */
+ public IdentNode markDead() {
+ return new IdentNode(this, name, type, flags | IS_DEAD, programPoint, conversion);
}
/**
- * Check if this IdentNode is a special identity, currently __DIR__, __FILE__
- * or __LINE__
+ * Is this IdentNode declared here?
*
- * @return true if this IdentNode is special
+ * @return true if identifier is declared here
*/
- public boolean isSpecialIdentity() {
+ public boolean isDeclaredHere() {
+ return (flags & IS_DECLARED_HERE) != 0;
+ }
+
+ /**
+ * Flag this IdentNode as being declared here.
+ *
+ * @return a new IdentNode equivalent to this but marked as declared here.
+ */
+ public IdentNode setIsDeclaredHere() {
+ if (isDeclaredHere()) {
+ return this;
+ }
+ return new IdentNode(this, name, type, flags | IS_DECLARED_HERE, programPoint, conversion);
+ }
+
+ /**
+ * Check if the name of this IdentNode is same as that of a compile-time property (currently __DIR__, __FILE__, and
+ * __LINE__).
+ *
+ * @return true if this IdentNode's name is same as that of a compile-time property
+ */
+ public boolean isCompileTimePropertyName() {
return name.equals(__DIR__.symbolName()) || name.equals(__FILE__.symbolName()) || name.equals(__LINE__.symbolName());
}
@Override
public boolean isFunction() {
- return (flags & FUNCTION) != 0;
+ return (flags & FUNCTION) == FUNCTION;
+ }
+
+ @Override
+ public IdentNode setType(final Type type) {
+ if (this.type == type) {
+ return this;
+ }
+ return new IdentNode(this, name, type, flags, programPoint, conversion);
}
/**
@@ -223,6 +320,68 @@ public final class IdentNode extends Expression implements PropertyKey, Function
if (isFunction()) {
return this;
}
- return new IdentNode(this, name, callSiteType, flags | FUNCTION);
+ return new IdentNode(this, name, type, flags | FUNCTION, programPoint, conversion);
+ }
+
+ /**
+ * Mark this node as not being the callee operand of a {@link CallNode}.
+ * @return an ident node identical to this one in all aspects except with its function flag unset.
+ */
+ public IdentNode setIsNotFunction() {
+ if (! isFunction()) {
+ return this;
+ }
+ return new IdentNode(this, name, type, flags & ~FUNCTION, programPoint, conversion);
+ }
+
+ @Override
+ public int getProgramPoint() {
+ return programPoint;
+ }
+
+ @Override
+ public Optimistic setProgramPoint(final int programPoint) {
+ if (this.programPoint == programPoint) {
+ return this;
+ }
+ return new IdentNode(this, name, type, flags, programPoint, conversion);
+ }
+
+ @Override
+ public Type getMostOptimisticType() {
+ return Type.INT;
+ }
+
+ @Override
+ public Type getMostPessimisticType() {
+ return Type.OBJECT;
+ }
+
+ @Override
+ public boolean canBeOptimistic() {
+ return true;
+ }
+
+ @Override
+ public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+ if(this.conversion == conversion) {
+ return this;
+ }
+ return new IdentNode(this, name, type, flags, programPoint, conversion);
+ }
+
+ /**
+ * Is this an internal symbol, i.e. one that starts with ':'. Those can
+ * never be optimistic.
+ * @return true if internal symbol
+ */
+ public boolean isInternal() {
+ assert name != null;
+ return name.charAt(0) == ':';
+ }
+
+ @Override
+ public LocalVariableConversion getLocalVariableConversion() {
+ return conversion;
}
}