The parser should generate AST nodes the var declarations with no initializers
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 Aug 2014 19:11:41 +0000 (19:11 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 Aug 2014 19:11:41 +0000 (19:11 +0000)
https://bugs.webkit.org/show_bug.cgi?id=135545

Patch by Saam Barati <sbarati@apple.com> on 2014-08-18
Reviewed by Geoffrey Garen.

Currently, JSC's parser ignores variable declarations
that have no assignment initializer value because all
variables are implicitly assigned to undefined. But,
type profiling needs an AST node to be generated for these
empty variable declarations because it needs to be able to
profile their text locations and to see that their type
is undefined.

* bytecompiler/NodesCodegen.cpp:
(JSC::EmptyVarExpression::emitBytecode):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createVarStatement):
(JSC::ASTBuilder::createEmptyVarExpression):
* parser/NodeConstructors.h:
(JSC::EmptyVarExpression::EmptyVarExpression):
* parser/Nodes.h:
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseVarDeclarationList):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createEmptyVarExpression):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@172717 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/parser/ASTBuilder.h
Source/JavaScriptCore/parser/NodeConstructors.h
Source/JavaScriptCore/parser/Nodes.h
Source/JavaScriptCore/parser/Parser.cpp
Source/JavaScriptCore/parser/SyntaxChecker.h

index dac145f..1141932 100644 (file)
@@ -1,3 +1,31 @@
+2014-08-18  Saam Barati  <sbarati@apple.com>
+
+        The parser should generate AST nodes the var declarations with no initializers
+        https://bugs.webkit.org/show_bug.cgi?id=135545
+
+        Reviewed by Geoffrey Garen.
+
+        Currently, JSC's parser ignores variable declarations
+        that have no assignment initializer value because all 
+        variables are implicitly assigned to undefined. But, 
+        type profiling needs an AST node to be generated for these 
+        empty variable declarations because it needs to be able to 
+        profile their text locations and to see that their type 
+        is undefined.
+
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::EmptyVarExpression::emitBytecode):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createVarStatement):
+        (JSC::ASTBuilder::createEmptyVarExpression):
+        * parser/NodeConstructors.h:
+        (JSC::EmptyVarExpression::EmptyVarExpression):
+        * parser/Nodes.h:
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseVarDeclarationList):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createEmptyVarExpression):
+
 2014-08-18  Diego Pino Garcia  <dpino@igalia.com>
 
         Completed iterator can be revived by adding more than one new entry to the target object
index a8736d2..6acfc01 100644 (file)
@@ -1782,6 +1782,27 @@ void VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
     generator.emitNode(m_expr);
 }
 
+// ------------------------------ EmptyVarExpression ----------------------------
+
+RegisterID* EmptyVarExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+{
+    if (!generator.isProfilingTypesWithHighFidelity())
+        return nullptr;
+
+    if (Local local = generator.local(m_ident))
+        generator.emitProfileTypesWithHighFidelity(local.get(), ProfileTypesBytecodeHasGlobalID, nullptr);
+    else {
+        RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
+        RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound);
+        generator.emitProfileTypesWithHighFidelity(value.get(), ProfileTypesBytecodeGetFromScope, &m_ident);
+    }
+
+    generator.emitHighFidelityTypeProfilingExpressionInfo(position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
+
+    // It's safe to return null here because this node will always be a child node of VarStatementNode which ignores our return value.
+    return nullptr;
+}
+
 // ------------------------------ IfElseNode ---------------------------------------
 
 static inline StatementNode* singleStatement(StatementNode* statementNode)
index 6e099ba..ac8f5b1 100644 (file)
@@ -416,14 +416,16 @@ public:
     StatementNode* createVarStatement(const JSTokenLocation& location, ExpressionNode* expr, int start, int end)
     {
         StatementNode* result;
-        if (!expr)
-            result = new (m_vm) EmptyStatementNode(location);
-        else
-            result = new (m_vm) VarStatementNode(location, expr);
+        result = new (m_vm) VarStatementNode(location, expr);
         result->setLoc(start, end, location.startOffset, location.lineStartOffset);
         return result;
     }
 
+    ExpressionNode* createEmptyVarExpression(const JSTokenLocation& location, const Identifier& identifier)
+    {
+        return new (m_vm) EmptyVarExpression(location, identifier);
+    }
+
     StatementNode* createReturnStatement(const JSTokenLocation& location, ExpressionNode* expression, const JSTextPosition& start, const JSTextPosition& end)
     {
         ReturnNode* result = new (m_vm) ReturnNode(location, expression);
index 2083aa4..25d5bf7 100644 (file)
@@ -655,6 +655,12 @@ inline ResolveNode::ResolveNode(const JSTokenLocation& location, const Identifie
         , m_expr(expr)
     {
     }
+
+    inline EmptyVarExpression::EmptyVarExpression(const JSTokenLocation& location, const Identifier& ident)
+        : ExpressionNode(location)
+        , m_ident(ident)
+    {
+    }
     
     inline IfElseNode::IfElseNode(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock)
         : StatementNode(location)
index 06a27ed..b7be272 100644 (file)
@@ -1212,6 +1212,17 @@ namespace JSC {
         ExpressionNode* m_expr;
     };
 
+    class EmptyVarExpression : public ExpressionNode {
+    public:
+        EmptyVarExpression(const JSTokenLocation&, const Identifier&);
+
+    private:
+        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+
+        const Identifier& m_ident;
+    };
+
+
     class IfElseNode : public StatementNode {
     public:
         IfElseNode(const JSTokenLocation&, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock);
index 1773946..14adbd9 100644 (file)
@@ -458,6 +458,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarati
         bool hasInitializer = false;
         if (match(IDENT)) {
             JSTextPosition varStart = tokenStartPosition();
+            JSTokenLocation varStartLocation(tokenLocation());
             identStart = varStart;
             const Identifier* name = m_token.m_data.ident;
             lastIdent = name;
@@ -475,7 +476,8 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarati
                 failIfFalse(initializer, "Expected expression as the intializer for the variable '", name->impl(), "'");
                 
                 node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEndPosition());
-            }
+            } else
+                node = context.createEmptyVarExpression(varStartLocation, *name);
         } else {
             lastIdent = 0;
             auto pattern = parseDeconstructionPattern(context, DeconstructToVariables);
@@ -490,12 +492,10 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarati
             }
         }
         
-        if (hasInitializer) {
-            if (!varDecls)
-                varDecls = node;
-            else
-                varDecls = context.combineCommaNodes(location, varDecls, node);
-        }
+        if (!varDecls)
+            varDecls = node;
+        else
+            varDecls = context.combineCommaNodes(location, varDecls, node);
     } while (match(COMMA));
     if (lastIdent)
         lastPattern = createBindingPattern(context, DeconstructToVariables, *lastIdent, 0);
index 8912d8b..dd49e83 100644 (file)
@@ -158,6 +158,7 @@ public:
     ExpressionType createNewExpr(const JSTokenLocation&, ExpressionType, int, int) { return NewExpr; }
     ExpressionType createConditionalExpr(const JSTokenLocation&, ExpressionType, ExpressionType, ExpressionType) { return ConditionalExpr; }
     ExpressionType createAssignResolve(const JSTokenLocation&, const Identifier&, ExpressionType, int, int, int) { return AssignmentExpr; }
+    ExpressionType createEmptyVarExpression(const JSTokenLocation&, const Identifier&) { return AssignmentExpr; }
     ExpressionType createFunctionExpr(const JSTokenLocation&, const Identifier*, int, int, int, int, int, int, int) { return FunctionExpr; }
     int createFunctionBody(const JSTokenLocation&, const JSTokenLocation&, int, int, bool) { return FunctionBodyResult; }
     void setFunctionNameStart(int, int) { }