aboutsummaryrefslogtreecommitdiff
path: root/src/jdk/nashorn/internal/codegen/Attr.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jdk/nashorn/internal/codegen/Attr.java')
-rw-r--r--src/jdk/nashorn/internal/codegen/Attr.java129
1 files changed, 61 insertions, 68 deletions
diff --git a/src/jdk/nashorn/internal/codegen/Attr.java b/src/jdk/nashorn/internal/codegen/Attr.java
index 29430062..813d3fc9 100644
--- a/src/jdk/nashorn/internal/codegen/Attr.java
+++ b/src/jdk/nashorn/internal/codegen/Attr.java
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.codegen;
import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
+import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR;
import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE;
import static jdk.nashorn.internal.codegen.CompilerConstants.EXCEPTION_PREFIX;
import static jdk.nashorn.internal.codegen.CompilerConstants.ITERATOR_PREFIX;
@@ -172,7 +173,9 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL);
if (functionNode.needsArguments()) {
initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED);
- addLocalDef(ARGUMENTS.symbolName());
+ final String argumentsName = ARGUMENTS_VAR.symbolName();
+ newType(defineSymbol(body, argumentsName, IS_VAR | IS_ALWAYS_DEFINED), Type.typeFor(ARGUMENTS_VAR.type()));
+ addLocalDef(argumentsName);
}
}
@@ -491,30 +494,29 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
objectifySymbols(body);
}
- if (body.getFlag(Block.NEEDS_SELF_SYMBOL)) {
- final IdentNode callee = compilerConstant(CALLEE);
- VarNode selfInit =
- new VarNode(
- newFunctionNode.getLineNumber(),
- newFunctionNode.getToken(),
- newFunctionNode.getFinish(),
- newFunctionNode.getIdent(),
- callee);
-
- LOG.info("Accepting self symbol init ", selfInit, " for ", newFunctionNode.getName());
-
- final List<Statement> newStatements = new ArrayList<>();
- assert callee.getSymbol() != null && callee.getSymbol().hasSlot();
-
- final IdentNode name = selfInit.getName();
- final Symbol nameSymbol = body.getExistingSymbol(name.getName());
+ List<VarNode> syntheticInitializers = null;
- assert nameSymbol != null;
+ if (body.getFlag(Block.NEEDS_SELF_SYMBOL)) {
+ syntheticInitializers = new ArrayList<>(2);
+ LOG.info("Accepting self symbol init for ", newFunctionNode.getName());
+ // "var fn = :callee"
+ syntheticInitializers.add(createSyntheticInitializer(newFunctionNode.getIdent(), CALLEE, newFunctionNode));
+ }
- selfInit = selfInit.setName((IdentNode)name.setSymbol(lc, nameSymbol));
+ if(newFunctionNode.needsArguments()) {
+ if(syntheticInitializers == null) {
+ syntheticInitializers = new ArrayList<>(1);
+ }
+ // "var arguments = :arguments"
+ syntheticInitializers.add(createSyntheticInitializer(createImplicitIdentifier(ARGUMENTS_VAR.symbolName()),
+ ARGUMENTS, newFunctionNode));
+ }
- newStatements.add(selfInit);
- newStatements.addAll(body.getStatements());
+ if(syntheticInitializers != null) {
+ final List<Statement> stmts = body.getStatements();
+ final List<Statement> newStatements = new ArrayList<>(stmts.size() + syntheticInitializers.size());
+ newStatements.addAll(syntheticInitializers);
+ newStatements.addAll(stmts);
newFunctionNode = newFunctionNode.setBody(lc, body.setStatements(lc, newStatements));
}
@@ -533,6 +535,28 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
return newFunctionNode;
}
+ /**
+ * Creates a synthetic initializer for a variable (a var statement that doesn't occur in the source code). Typically
+ * used to create assignmnent of {@code :callee} to the function name symbol in self-referential function
+ * expressions as well as for assignment of {@code :arguments} to {@code arguments}.
+ *
+ * @param name the ident node identifying the variable to initialize
+ * @param initConstant the compiler constant it is initialized to
+ * @param fn the function node the assignment is for
+ * @return a var node with the appropriate assignment
+ */
+ private VarNode createSyntheticInitializer(final IdentNode name, final CompilerConstants initConstant, final FunctionNode fn) {
+ final IdentNode init = compilerConstant(initConstant);
+ assert init.getSymbol() != null && init.getSymbol().hasSlot();
+
+ VarNode synthVar = new VarNode(fn.getLineNumber(), fn.getToken(), fn.getFinish(), name, init);
+
+ final Symbol nameSymbol = fn.getBody().getExistingSymbol(name.getName());
+ assert nameSymbol != null;
+
+ return synthVar.setName((IdentNode)name.setSymbol(lc, nameSymbol));
+ }
+
@Override
public Node leaveCONVERT(final UnaryNode unaryNode) {
assert false : "There should be no convert operators in IR during Attribution";
@@ -886,10 +910,9 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
@Override
public Node leaveDECINC(final UnaryNode unaryNode) {
// @see assignOffset
- final UnaryNode newUnaryNode = unaryNode.setRHS(ensureAssignmentSlots(unaryNode.rhs()));
final Type type = arithType();
- newType(newUnaryNode.rhs().getSymbol(), type);
- return end(ensureSymbol(type, newUnaryNode));
+ newType(unaryNode.rhs().getSymbol(), type);
+ return end(ensureSymbol(type, unaryNode));
}
@Override
@@ -975,15 +998,18 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
}
private IdentNode compilerConstant(CompilerConstants cc) {
- final FunctionNode functionNode = lc.getCurrentFunction();
- return (IdentNode)
- new IdentNode(
- functionNode.getToken(),
- functionNode.getFinish(),
- cc.symbolName()).
- setSymbol(
- lc,
- functionNode.compilerConstant(cc));
+ return (IdentNode)createImplicitIdentifier(cc.symbolName()).setSymbol(lc, lc.getCurrentFunction().compilerConstant(cc));
+ }
+
+ /**
+ * Creates an ident node for an implicit identifier within the function (one not declared in the script source
+ * code). These identifiers are defined with function's token and finish.
+ * @param name the name of the identifier
+ * @return an ident node representing the implicit identifier.
+ */
+ private IdentNode createImplicitIdentifier(final String name) {
+ final FunctionNode fn = lc.getCurrentFunction();
+ return new IdentNode(fn.getToken(), fn.getFinish(), name);
}
@Override
@@ -1575,39 +1601,6 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
}
/**
- * In an assignment, recursively make sure that there are slots for
- * everything that has to be laid out as temporary storage, which is the
- * case if we are assign-op:ing a BaseNode subclass. This has to be
- * recursive to handle things like multi dimensional arrays as lhs
- *
- * see NASHORN-258
- *
- * @param assignmentDest the destination node of the assignment, e.g. lhs for binary nodes
- */
- private Expression ensureAssignmentSlots(final Expression assignmentDest) {
- final LexicalContext attrLexicalContext = lc;
- return (Expression)assignmentDest.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
- @Override
- public Node leaveIndexNode(final IndexNode indexNode) {
- assert indexNode.getSymbol().isTemp();
- final Expression index = indexNode.getIndex();
- //only temps can be set as needing slots. the others will self resolve
- //it is illegal to take a scope var and force it to be a slot, that breaks
- Symbol indexSymbol = index.getSymbol();
- if (indexSymbol.isTemp() && !indexSymbol.isConstant() && !indexSymbol.hasSlot()) {
- if(indexSymbol.isShared()) {
- indexSymbol = temporarySymbols.createUnshared(indexSymbol);
- }
- indexSymbol.setNeedsSlot(true);
- attrLexicalContext.getCurrentBlock().putSymbol(attrLexicalContext, indexSymbol);
- return indexNode.setIndex(index.setSymbol(attrLexicalContext, indexSymbol));
- }
- return indexNode;
- }
- });
- }
-
- /**
* Return the type that arithmetic ops should use. Until we have implemented better type
* analysis (range based) or overflow checks that are fast enough for int arithmetic,
* this is the number type
@@ -1704,7 +1697,7 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
newType(lhs.getSymbol(), destType); //may not narrow if dest is already wider than destType
// ensureSymbol(destType, binaryNode); //for OP= nodes, the node can carry a narrower types than its lhs rhs. This is perfectly fine
- return end(ensureSymbol(destType, ensureAssignmentSlots(binaryNode)));
+ return end(ensureSymbol(destType, binaryNode));
}
private Expression ensureSymbol(final Type type, final Expression expr) {