8055911: Don't use String.intern for IdentNode
authorattila
Tue, 26 Aug 2014 11:31:31 +0200
changeset 26243 438aba09d465
parent 26242 f6707443717b
child 26244 4f3e221fd4ad
8055911: Don't use String.intern for IdentNode Reviewed-by: lagergren, sundar
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java	Tue Aug 26 13:26:15 2014 +0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java	Tue Aug 26 11:31:31 2014 +0200
@@ -71,7 +71,7 @@
      */
     public IdentNode(final long token, final int finish, final String name) {
         super(token, finish);
-        this.name = name.intern();
+        this.name = name;
         this.type = null;
         this.flags = 0;
         this.programPoint = INVALID_PROGRAM_POINT;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java	Tue Aug 26 13:26:15 2014 +0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/AbstractParser.java	Tue Aug 26 11:31:31 2014 +0200
@@ -31,6 +31,8 @@
 import static jdk.nashorn.internal.parser.TokenType.EOL;
 import static jdk.nashorn.internal.parser.TokenType.IDENT;
 
+import java.util.HashMap;
+import java.util.Map;
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.parser.Lexer.LexerToken;
@@ -91,6 +93,8 @@
     /** What should line numbers be counted from? */
     protected final int lineOffset;
 
+    private final Map<String, String> canonicalNames = new HashMap<>();
+
     /**
      * Construct a parser.
      *
@@ -409,7 +413,7 @@
             next();
 
             // Create IDENT node.
-            return new IdentNode(identToken, finish, ident).setIsFutureStrictName();
+            return createIdentNode(identToken, finish, ident).setIsFutureStrictName();
         }
 
         // Get IDENT.
@@ -418,7 +422,22 @@
             return null;
         }
         // Create IDENT node.
-        return new IdentNode(identToken, finish, ident);
+        return createIdentNode(identToken, finish, ident);
+    }
+
+    /**
+     * Creates a new {@link IdentNode} as if invoked with a {@link IdentNode#IdentNode(long, int, String)
+     * constructor} but making sure that the {@code name} is deduplicated within this parse job.
+     * @param identToken the token for the new {@code IdentNode}
+     * @param identFinish the finish for the new {@code IdentNode}
+     * @param name the name for the new {@code IdentNode}. It will be de-duplicated.
+     * @return a newly constructed {@code IdentNode} with the specified token, finish, and name; the name will
+     * be deduplicated.
+     */
+    protected IdentNode createIdentNode(final long identToken, final int identFinish, final String name) {
+        final String existingName = canonicalNames.putIfAbsent(name, name);
+        final String canonicalName = existingName != null ? existingName : name;
+        return new IdentNode(identToken, identFinish, canonicalName);
     }
 
     /**
@@ -453,7 +472,7 @@
             final String ident = (String)getValue(identToken);
             next();
             // Create IDENT node.
-            return new IdentNode(identToken, finish, ident);
+            return createIdentNode(identToken, finish, ident);
         } else {
             expect(IDENT);
             return null;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Tue Aug 26 13:26:15 2014 +0400
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Tue Aug 26 11:31:31 2014 +0200
@@ -222,7 +222,7 @@
      * @param name the name for the first parsed function.
      */
     public void setFunctionName(final String name) {
-        defaultNames.push(new IdentNode(0, 0, name));
+        defaultNames.push(createIdentNode(0, 0, name));
     }
 
     /**
@@ -2243,7 +2243,7 @@
                 }
             }
 
-            propertyName =  new IdentNode(propertyToken, finish, ident).setIsPropertyName();
+            propertyName =  createIdentNode(propertyToken, finish, ident).setIsPropertyName();
         } else {
             propertyName = propertyName();
         }
@@ -2261,7 +2261,7 @@
     private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
         final PropertyKey getIdent = propertyName();
         final String getterName = getIdent.getPropertyName();
-        final IdentNode getNameNode = new IdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
+        final IdentNode getNameNode = createIdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
         expect(LPAREN);
         expect(RPAREN);
         final FunctionNode functionNode = functionBody(getSetToken, getNameNode, new ArrayList<IdentNode>(), FunctionNode.Kind.GETTER, functionLine);
@@ -2272,7 +2272,7 @@
     private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
         final PropertyKey setIdent = propertyName();
         final String setterName = setIdent.getPropertyName();
-        final IdentNode setNameNode = new IdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
+        final IdentNode setNameNode = createIdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
         expect(LPAREN);
         // be sloppy and allow missing setter parameter even though
         // spec does not permit it!