Cleaned up the JavaScript grammar a bit.
1. Changed BlockNode to always hold a child vector (which may be empty),
eliminating a few NULL-check branches in the common execution case.
2. Changed the Block production to correctly report its starting and
ending line numbers to the debugger. (It used to report its ending line
as its starting line.) Also, removed duplicate line-reporting code
inside the BlockNode constructor.
3. Moved curly braces up from FunctionBody production into parent
productions. (I had to move the line number reporting code, too, since
it depends on the location of the curly braces.) This matches the ECMA
spec more closely, and makes some future changes I plan easier.
4. Fixed statementList* convenience functions to deal appropriately with
empty Vectors.
SunSpider reports a small and statistically insignificant speedup.
* kjs/grammar.y:
* kjs/nodes.cpp:
(KJS::statementListPushFIFO):
(KJS::statementListGetDeclarations):
(KJS::statementListInitializeDeclarationStack):
(KJS::statementListInitializeVariableAccessStack):
(KJS::BlockNode::BlockNode):
(KJS::BlockNode::optimizeVariableAccess):
(KJS::BlockNode::getDeclarations):
(KJS::BlockNode::execute):
(KJS::FunctionBodyNode::initializeDeclarationStacks):
(KJS::FunctionBodyNode::optimizeVariableAccess):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@27799
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2007-11-14 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Eric Seidel.
+
+ Cleaned up the JavaScript grammar a bit.
+
+ 1. Changed BlockNode to always hold a child vector (which may be empty),
+ eliminating a few NULL-check branches in the common execution case.
+
+ 2. Changed the Block production to correctly report its starting and
+ ending line numbers to the debugger. (It used to report its ending line
+ as its starting line.) Also, removed duplicate line-reporting code
+ inside the BlockNode constructor.
+
+ 3. Moved curly braces up from FunctionBody production into parent
+ productions. (I had to move the line number reporting code, too, since
+ it depends on the location of the curly braces.) This matches the ECMA
+ spec more closely, and makes some future changes I plan easier.
+
+ 4. Fixed statementList* convenience functions to deal appropriately with
+ empty Vectors.
+
+ SunSpider reports a small and statistically insignificant speedup.
+
+ * kjs/grammar.y:
+ * kjs/nodes.cpp:
+ (KJS::statementListPushFIFO):
+ (KJS::statementListGetDeclarations):
+ (KJS::statementListInitializeDeclarationStack):
+ (KJS::statementListInitializeVariableAccessStack):
+ (KJS::BlockNode::BlockNode):
+ (KJS::BlockNode::optimizeVariableAccess):
+ (KJS::BlockNode::getDeclarations):
+ (KJS::BlockNode::execute):
+ (KJS::FunctionBodyNode::initializeDeclarationStacks):
+ (KJS::FunctionBodyNode::optimizeVariableAccess):
+
2007-11-13 Anders Carlsson <andersca@apple.com>
Add RefCounted.h (And remove Shared.h)
IDENT ':' AssignmentExpr { $$ = new PropertyNode(*$1, $3, PropertyNode::Constant); }
| STRING ':' AssignmentExpr { $$ = new PropertyNode(Identifier(*$1), $3, PropertyNode::Constant); }
| NUMBER ':' AssignmentExpr { $$ = new PropertyNode(Identifier(UString::from($1)), $3, PropertyNode::Constant); }
- | IDENT IDENT '(' ')' FunctionBody { $$ = makeGetterOrSetterPropertyNode(*$1, *$2, 0, $5); if (!$$) YYABORT; }
- | IDENT IDENT '(' FormalParameterList ')' FunctionBody
- { $$ = makeGetterOrSetterPropertyNode(*$1, *$2, $4.head, $6); if (!$$) YYABORT; }
+ | IDENT IDENT '(' ')' '{' FunctionBody '}' { $$ = makeGetterOrSetterPropertyNode(*$1, *$2, 0, $6); DBG($6, @5, @7); if (!$$) YYABORT; }
+ | IDENT IDENT '(' FormalParameterList ')' '{' FunctionBody '}'
+ { $$ = makeGetterOrSetterPropertyNode(*$1, *$2, $4.head, $7); DBG($7, @6, @8); if (!$$) YYABORT; }
;
PropertyList:
;
Block:
- '{' '}' { $$ = new BlockNode(0); DBG($$, @2, @2); }
- | '{' SourceElements '}' { $$ = new BlockNode($2); DBG($$, @3, @3); }
+ '{' '}' { $$ = new BlockNode(new SourceElements); DBG($$, @1, @2); }
+ | '{' SourceElements '}' { $$ = new BlockNode($2); DBG($$, @1, @3); }
;
VariableStatement:
;
FunctionDeclaration:
- FUNCTION IDENT '(' ')' FunctionBody { $$ = new FuncDeclNode(*$2, $5); }
- | FUNCTION IDENT '(' FormalParameterList ')' FunctionBody
- { $$ = new FuncDeclNode(*$2, $4.head, $6); }
+ FUNCTION IDENT '(' ')' '{' FunctionBody '}' { $$ = new FuncDeclNode(*$2, $6); DBG($6, @5, @7); }
+ | FUNCTION IDENT '(' FormalParameterList ')' '{' FunctionBody '}'
+ { $$ = new FuncDeclNode(*$2, $4.head, $7); DBG($7, @6, @8); }
;
FunctionExpr:
- FUNCTION '(' ')' FunctionBody { $$ = new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $4); }
- | FUNCTION '(' FormalParameterList ')' FunctionBody
- { $$ = new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $5, $3.head); }
- | FUNCTION IDENT '(' ')' FunctionBody { $$ = new FuncExprNode(*$2, $5); }
- | FUNCTION IDENT '(' FormalParameterList ')' FunctionBody
- { $$ = new FuncExprNode(*$2, $6, $4.head); }
+ FUNCTION '(' ')' '{' FunctionBody '}' { $$ = new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $5); DBG($5, @4, @6); }
+ | FUNCTION '(' FormalParameterList ')' '{' FunctionBody '}' { $$ = new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $6, $3.head); DBG($6, @5, @7); }
+ | FUNCTION IDENT '(' ')' '{' FunctionBody '}' { $$ = new FuncExprNode(*$2, $6); DBG($6, @5, @7); }
+ | FUNCTION IDENT '(' FormalParameterList ')' '{' FunctionBody '}' { $$ = new FuncExprNode(*$2, $7, $4.head); DBG($7, @6, @8); }
;
FormalParameterList:
;
FunctionBody:
- '{' '}' /* not in spec */ { $$ = new FunctionBodyNode(0); DBG($$, @1, @2); }
- | '{' SourceElements '}' { $$ = new FunctionBodyNode($2); DBG($$, @1, @3); }
+ /* not in spec */ { $$ = new FunctionBodyNode(new SourceElements); }
+ | SourceElements { $$ = new FunctionBodyNode($1); }
;
Program:
- /* not in spec */ { Parser::accept(new ProgramNode(0)); }
+ /* not in spec */ { Parser::accept(new ProgramNode(new SourceElements)); }
| SourceElements { Parser::accept(new ProgramNode($1)); }
;
SourceElements:
- SourceElement { $$ = new Vector<RefPtr<StatementNode> >();
- $$->append($1); }
+ SourceElement { $$ = new SourceElements; $$->append($1); }
| SourceElements SourceElement { $$->append($2); }
;
static inline void statementListPushFIFO(SourceElements& statements, DeclarationStacks::NodeStack& stack)
{
- for (SourceElements::iterator ptr = statements.end() - 1; ptr >= statements.begin(); --ptr)
- stack.append((*ptr).get());
+ SourceElements::iterator it = statements.end();
+ SourceElements::iterator begin = statements.begin();
+ while (it != begin) {
+ --it;
+ stack.append((*it).get());
+ }
}
static inline void statementListGetDeclarations(SourceElements& statements, DeclarationStacks& stacks)
{
- for (SourceElements::iterator ptr = statements.end() - 1; ptr >= statements.begin(); --ptr)
- if ((*ptr)->mayHaveDeclarations())
- stacks.nodeStack.append((*ptr).get());
+ SourceElements::iterator it = statements.end();
+ SourceElements::iterator begin = statements.begin();
+ while (it != begin) {
+ --it;
+ if ((*it)->mayHaveDeclarations())
+ stacks.nodeStack.append((*it).get());
+ }
}
-static inline Node* statementListInitializeDeclarationStacks(SourceElements& statements, DeclarationStacks::NodeStack& stack)
+static inline Node* statementListInitializeDeclarationStack(SourceElements& statements, DeclarationStacks::NodeStack& stack)
{
- for (SourceElements::iterator ptr = statements.end() - 1; ptr >= statements.begin(); --ptr)
- if ((*ptr)->mayHaveDeclarations())
- stack.append((*ptr).get());
+ ASSERT(!stack.size()); // Otherwise, the removeLast() call might remove someone else's node.
+
+ SourceElements::iterator it = statements.end();
+ SourceElements::iterator begin = statements.begin();
+
+ while (it != begin) {
+ --it;
+ if ((*it)->mayHaveDeclarations())
+ stack.append((*it).get());
+ }
+
if (!stack.size())
return 0;
+
Node* n = stack.last();
stack.removeLast();
return n;
static inline Node* statementListInitializeVariableAccessStack(SourceElements& statements, DeclarationStacks::NodeStack& stack)
{
- for (SourceElements::iterator ptr = statements.end() - 1; ptr != statements.begin(); --ptr)
- stack.append((*ptr).get());
- return statements[0].get();
+ if (!statements.size())
+ return 0;
+
+ SourceElements::iterator it = statements.end();
+ SourceElements::iterator begin = statements.begin();
+ SourceElements::iterator beginPlusOne = begin + 1;
+
+ while (it != beginPlusOne) {
+ --it;
+ stack.append((*it).get());
+ }
+
+ return (*begin).get();
}
static inline Completion statementListExecute(SourceElements& statements, ExecState* exec)
// ------------------------------ BlockNode ------------------------------------
-void BlockNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
-{
- if (m_children)
- statementListPushFIFO(*m_children, nodeStack);
-}
-
BlockNode::BlockNode(SourceElements* children)
{
- if (children) {
+ ASSERT(children);
m_mayHaveDeclarations = true;
m_children.set(children);
- setLoc(children->at(0)->firstLine(), children->at(children->size() - 1)->lastLine());
- }
+}
+
+void BlockNode::optimizeVariableAccess(FunctionBodyNode*, DeclarationStacks::NodeStack& nodeStack)
+{
+ statementListPushFIFO(*m_children, nodeStack);
}
void BlockNode::getDeclarations(DeclarationStacks& stacks)
{
- ASSERT(m_children);
statementListGetDeclarations(*m_children, stacks);
}
// ECMA 12.1
Completion BlockNode::execute(ExecState *exec)
{
- if (!m_children)
- return Completion(Normal);
-
- return statementListExecute(*m_children, exec);
+ return statementListExecute(*m_children, exec);
}
// ------------------------------ EmptyStatementNode ---------------------------
void FunctionBodyNode::initializeDeclarationStacks(ExecState* exec)
{
- if (!m_children)
- return;
-
DeclarationStacks::NodeStack nodeStack;
DeclarationStacks stacks(exec, nodeStack, m_varStack, m_functionStack);
- Node* node = statementListInitializeDeclarationStacks(*m_children, nodeStack);
+ Node* node = statementListInitializeDeclarationStack(*m_children, nodeStack);
if (!node)
return;
void FunctionBodyNode::optimizeVariableAccess()
{
- if (!m_children)
- return;
-
DeclarationStacks::NodeStack nodeStack;
Node* node = statementListInitializeVariableAccessStack(*m_children, nodeStack);
if (!node)