diff options
author | Feng Qian <fqian@google.com> | 2009-06-17 12:12:20 -0700 |
---|---|---|
committer | Feng Qian <fqian@google.com> | 2009-06-17 12:12:20 -0700 |
commit | 5f1ab04193ad0130ca8204aadaceae083aca9881 (patch) | |
tree | 5a92cd389e2cfe7fb67197ce14b38469462379f8 /JavaScriptCore/parser | |
parent | 194315e5a908cc8ed67d597010544803eef1ac59 (diff) | |
download | external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.zip external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.gz external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.bz2 |
Get WebKit r44544.
Diffstat (limited to 'JavaScriptCore/parser')
-rw-r--r-- | JavaScriptCore/parser/Grammar.y | 447 | ||||
-rw-r--r-- | JavaScriptCore/parser/Lexer.cpp | 1490 | ||||
-rw-r--r-- | JavaScriptCore/parser/Lexer.h | 147 | ||||
-rw-r--r-- | JavaScriptCore/parser/NodeConstructors.h | 911 | ||||
-rw-r--r-- | JavaScriptCore/parser/NodeInfo.h | 4 | ||||
-rw-r--r-- | JavaScriptCore/parser/Nodes.cpp | 1517 | ||||
-rw-r--r-- | JavaScriptCore/parser/Nodes.h | 1956 | ||||
-rw-r--r-- | JavaScriptCore/parser/Parser.cpp | 24 | ||||
-rw-r--r-- | JavaScriptCore/parser/Parser.h | 35 | ||||
-rw-r--r-- | JavaScriptCore/parser/ParserArena.cpp | 60 | ||||
-rw-r--r-- | JavaScriptCore/parser/ParserArena.h | 64 | ||||
-rw-r--r-- | JavaScriptCore/parser/ResultType.h | 7 | ||||
-rw-r--r-- | JavaScriptCore/parser/SourceProvider.h | 10 |
13 files changed, 3259 insertions, 3413 deletions
diff --git a/JavaScriptCore/parser/Grammar.y b/JavaScriptCore/parser/Grammar.y index ae787f6..52dddde 100644 --- a/JavaScriptCore/parser/Grammar.y +++ b/JavaScriptCore/parser/Grammar.y @@ -29,7 +29,7 @@ #include <stdlib.h> #include "JSValue.h" #include "JSObject.h" -#include "Nodes.h" +#include "NodeConstructors.h" #include "Lexer.h" #include "JSString.h" #include "JSGlobalData.h" @@ -99,24 +99,24 @@ static ExpressionNode* combineVarInitializers(void*, ExpressionNode* list, Assig #define YYPARSE_PARAM globalPtr #define YYLEX_PARAM globalPtr -template <typename T> NodeDeclarationInfo<T> createNodeDeclarationInfo(T node, ParserRefCountedData<DeclarationStacks::VarStack>* varDecls, - ParserRefCountedData<DeclarationStacks::FunctionStack>* funcDecls, +template <typename T> NodeDeclarationInfo<T> createNodeDeclarationInfo(T node, ParserArenaData<DeclarationStacks::VarStack>* varDecls, + ParserArenaData<DeclarationStacks::FunctionStack>* funcDecls, CodeFeatures info, int numConstants) { ASSERT((info & ~AllFeatures) == 0); - NodeDeclarationInfo<T> result = {node, varDecls, funcDecls, info, numConstants}; + NodeDeclarationInfo<T> result = { node, varDecls, funcDecls, info, numConstants }; return result; } template <typename T> NodeInfo<T> createNodeInfo(T node, CodeFeatures info, int numConstants) { ASSERT((info & ~AllFeatures) == 0); - NodeInfo<T> result = {node, info, numConstants}; + NodeInfo<T> result = { node, info, numConstants }; return result; } -template <typename T> T mergeDeclarationLists(T decls1, T decls2) +template <typename T> inline T mergeDeclarationLists(T decls1, T decls2) { // decls1 or both are null if (!decls1) @@ -128,28 +128,28 @@ template <typename T> T mergeDeclarationLists(T decls1, T decls2) // Both are non-null decls1->data.append(decls2->data); - // We manually release the declaration lists to avoid accumulating many many - // unused heap allocated vectors - decls2->ref(); - decls2->deref(); + // Manually release as much as possible from the now-defunct declaration lists + // to avoid accumulating so many unused heap allocated vectors. + decls2->data.clear(); + return decls1; } -static void appendToVarDeclarationList(void* globalPtr, ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, const Identifier& ident, unsigned attrs) +static void appendToVarDeclarationList(void* globalPtr, ParserArenaData<DeclarationStacks::VarStack>*& varDecls, const Identifier& ident, unsigned attrs) { if (!varDecls) - varDecls = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA); + varDecls = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>; varDecls->data.append(make_pair(ident, attrs)); } -static inline void appendToVarDeclarationList(void* globalPtr, ParserRefCountedData<DeclarationStacks::VarStack>*& varDecls, ConstDeclNode* decl) +static inline void appendToVarDeclarationList(void* globalPtr, ParserArenaData<DeclarationStacks::VarStack>*& varDecls, ConstDeclNode* decl) { unsigned attrs = DeclarationStacks::IsConstant; - if (decl->m_init) + if (decl->hasInitializer()) attrs |= DeclarationStacks::HasInitializer; - appendToVarDeclarationList(globalPtr, varDecls, decl->m_ident, attrs); + appendToVarDeclarationList(globalPtr, varDecls, decl->ident(), attrs); } %} @@ -218,7 +218,7 @@ static inline void appendToVarDeclarationList(void* globalPtr, ParserRefCountedD %token ANDEQUAL MODEQUAL /* &= and %= */ %token XOREQUAL OREQUAL /* ^= and |= */ %token <intValue> OPENBRACE /* { (with char offset) */ -%token <intValue> CLOSEBRACE /* { (with char offset) */ +%token <intValue> CLOSEBRACE /* } (with char offset) */ /* terminal types */ %token <doubleValue> NUMBER @@ -264,7 +264,7 @@ static inline void appendToVarDeclarationList(void* globalPtr, ParserRefCountedD %type <expressionNode> Initializer InitializerNoIn %type <statementNode> FunctionDeclaration %type <funcExprNode> FunctionExpr -%type <functionBodyNode> FunctionBody +%type <functionBodyNode> FunctionBody %type <sourceElements> SourceElements %type <parameterList> FormalParameterList %type <op> AssignmentOperator @@ -287,16 +287,16 @@ static inline void appendToVarDeclarationList(void* globalPtr, ParserRefCountedD // In the mean time, make sure to make any changes to the grammar in both versions. Literal: - NULLTOKEN { $$ = createNodeInfo<ExpressionNode*>(new NullNode(GLOBAL_DATA), 0, 1); } - | TRUETOKEN { $$ = createNodeInfo<ExpressionNode*>(new BooleanNode(GLOBAL_DATA, true), 0, 1); } - | FALSETOKEN { $$ = createNodeInfo<ExpressionNode*>(new BooleanNode(GLOBAL_DATA, false), 0, 1); } + NULLTOKEN { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NullNode(GLOBAL_DATA), 0, 1); } + | TRUETOKEN { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BooleanNode(GLOBAL_DATA, true), 0, 1); } + | FALSETOKEN { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BooleanNode(GLOBAL_DATA, false), 0, 1); } | NUMBER { $$ = createNodeInfo<ExpressionNode*>(makeNumberNode(GLOBAL_DATA, $1), 0, 1); } - | STRING { $$ = createNodeInfo<ExpressionNode*>(new StringNode(GLOBAL_DATA, *$1), 0, 1); } + | STRING { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StringNode(GLOBAL_DATA, *$1), 0, 1); } | '/' /* regexp */ { Lexer& l = *LEXER; if (!l.scanRegExp()) YYABORT; - RegExpNode* node = new RegExpNode(GLOBAL_DATA, l.pattern(), l.flags()); + RegExpNode* node = new (GLOBAL_DATA) RegExpNode(GLOBAL_DATA, l.pattern(), l.flags()); int size = l.pattern().size() + 2; // + 2 for the two /'s SET_EXCEPTION_LOCATION(node, @1.first_column, @1.first_column + size, @1.first_column + size); $$ = createNodeInfo<ExpressionNode*>(node, 0, 0); @@ -305,7 +305,7 @@ Literal: Lexer& l = *LEXER; if (!l.scanRegExp()) YYABORT; - RegExpNode* node = new RegExpNode(GLOBAL_DATA, "=" + l.pattern(), l.flags()); + RegExpNode* node = new (GLOBAL_DATA) RegExpNode(GLOBAL_DATA, "=" + l.pattern(), l.flags()); int size = l.pattern().size() + 2; // + 2 for the two /'s SET_EXCEPTION_LOCATION(node, @1.first_column, @1.first_column + size, @1.first_column + size); $$ = createNodeInfo<ExpressionNode*>(node, 0, 0); @@ -313,9 +313,9 @@ Literal: ; Property: - IDENT ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); } - | STRING ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); } - | NUMBER ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new PropertyNode(GLOBAL_DATA, Identifier(GLOBAL_DATA, UString::from($1)), $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); } + IDENT ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); } + | STRING ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); } + | NUMBER ':' AssignmentExpr { $$ = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, Identifier(GLOBAL_DATA, UString::from($1)), $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); } | IDENT IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(globalPtr, *$1, *$2, 0, $6, LEXER->sourceCode($5, $7, @5.first_line)), ClosureFeature, 0); DBG($6, @5, @7); if (!$$.m_node) YYABORT; } | IDENT IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE { @@ -329,46 +329,46 @@ Property: ; PropertyList: - Property { $$.m_node.head = new PropertyListNode(GLOBAL_DATA, $1.m_node); + Property { $$.m_node.head = new (GLOBAL_DATA) PropertyListNode(GLOBAL_DATA, $1.m_node); $$.m_node.tail = $$.m_node.head; $$.m_features = $1.m_features; $$.m_numConstants = $1.m_numConstants; } | PropertyList ',' Property { $$.m_node.head = $1.m_node.head; - $$.m_node.tail = new PropertyListNode(GLOBAL_DATA, $3.m_node, $1.m_node.tail); + $$.m_node.tail = new (GLOBAL_DATA) PropertyListNode(GLOBAL_DATA, $3.m_node, $1.m_node.tail); $$.m_features = $1.m_features | $3.m_features; $$.m_numConstants = $1.m_numConstants + $3.m_numConstants; } ; PrimaryExpr: PrimaryExprNoBrace - | OPENBRACE CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new ObjectLiteralNode(GLOBAL_DATA), 0, 0); } - | OPENBRACE PropertyList CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new ObjectLiteralNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); } + | OPENBRACE CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ObjectLiteralNode(GLOBAL_DATA), 0, 0); } + | OPENBRACE PropertyList CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ObjectLiteralNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); } /* allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 */ - | OPENBRACE PropertyList ',' CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new ObjectLiteralNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); } + | OPENBRACE PropertyList ',' CLOSEBRACE { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ObjectLiteralNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); } ; PrimaryExprNoBrace: - THISTOKEN { $$ = createNodeInfo<ExpressionNode*>(new ThisNode(GLOBAL_DATA), ThisFeature, 0); } + THISTOKEN { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ThisNode(GLOBAL_DATA), ThisFeature, 0); } | Literal | ArrayLiteral - | IDENT { $$ = createNodeInfo<ExpressionNode*>(new ResolveNode(GLOBAL_DATA, *$1, @1.first_column), (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0, 0); } + | IDENT { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ResolveNode(GLOBAL_DATA, *$1, @1.first_column), (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0, 0); } | '(' Expr ')' { $$ = $2; } ; ArrayLiteral: - '[' ElisionOpt ']' { $$ = createNodeInfo<ExpressionNode*>(new ArrayNode(GLOBAL_DATA, $2), 0, $2 ? 1 : 0); } - | '[' ElementList ']' { $$ = createNodeInfo<ExpressionNode*>(new ArrayNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); } - | '[' ElementList ',' ElisionOpt ']' { $$ = createNodeInfo<ExpressionNode*>(new ArrayNode(GLOBAL_DATA, $4, $2.m_node.head), $2.m_features, $4 ? $2.m_numConstants + 1 : $2.m_numConstants); } + '[' ElisionOpt ']' { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ArrayNode(GLOBAL_DATA, $2), 0, $2 ? 1 : 0); } + | '[' ElementList ']' { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ArrayNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); } + | '[' ElementList ',' ElisionOpt ']' { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ArrayNode(GLOBAL_DATA, $4, $2.m_node.head), $2.m_features, $4 ? $2.m_numConstants + 1 : $2.m_numConstants); } ; ElementList: - ElisionOpt AssignmentExpr { $$.m_node.head = new ElementNode(GLOBAL_DATA, $1, $2.m_node); + ElisionOpt AssignmentExpr { $$.m_node.head = new (GLOBAL_DATA) ElementNode(GLOBAL_DATA, $1, $2.m_node); $$.m_node.tail = $$.m_node.head; $$.m_features = $2.m_features; $$.m_numConstants = $2.m_numConstants; } | ElementList ',' ElisionOpt AssignmentExpr { $$.m_node.head = $1.m_node.head; - $$.m_node.tail = new ElementNode(GLOBAL_DATA, $1.m_node.tail, $3, $4.m_node); + $$.m_node.tail = new (GLOBAL_DATA) ElementNode(GLOBAL_DATA, $1.m_node.tail, $3, $4.m_node); $$.m_features = $1.m_features | $4.m_features; $$.m_numConstants = $1.m_numConstants + $4.m_numConstants; } ; @@ -386,15 +386,15 @@ Elision: MemberExpr: PrimaryExpr | FunctionExpr { $$ = createNodeInfo<ExpressionNode*>($1.m_node, $1.m_features, $1.m_numConstants); } - | MemberExpr '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); + | MemberExpr '[' Expr ']' { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | MemberExpr '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3); + | MemberExpr '.' IDENT { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3); SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants); } - | NEW MemberExpr Arguments { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node); + | NEW MemberExpr Arguments { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node); SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @3.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features | $3.m_features, $2.m_numConstants + $3.m_numConstants); } @@ -402,15 +402,15 @@ MemberExpr: MemberExprNoBF: PrimaryExprNoBrace - | MemberExprNoBF '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); + | MemberExprNoBF '[' Expr ']' { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | MemberExprNoBF '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3); + | MemberExprNoBF '.' IDENT { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3); SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants); } - | NEW MemberExpr Arguments { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node); + | NEW MemberExpr Arguments { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node); SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @3.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features | $3.m_features, $2.m_numConstants + $3.m_numConstants); } @@ -418,7 +418,7 @@ MemberExprNoBF: NewExpr: MemberExpr - | NEW NewExpr { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node); + | NEW NewExpr { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node); SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features, $2.m_numConstants); } @@ -426,7 +426,7 @@ NewExpr: NewExprNoBF: MemberExprNoBF - | NEW NewExpr { NewExprNode* node = new NewExprNode(GLOBAL_DATA, $2.m_node); + | NEW NewExpr { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node); SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features, $2.m_numConstants); } @@ -435,11 +435,11 @@ NewExprNoBF: CallExpr: MemberExpr Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); } | CallExpr Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); } - | CallExpr '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); + | CallExpr '[' Expr ']' { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | CallExpr '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3); + | CallExpr '.' IDENT { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3); SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants); } ; @@ -447,28 +447,28 @@ CallExpr: CallExprNoBF: MemberExprNoBF Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); } | CallExprNoBF Arguments { $$ = makeFunctionCallNode(globalPtr, $1, $2, @1.first_column, @1.last_column, @2.last_column); } - | CallExprNoBF '[' Expr ']' { BracketAccessorNode* node = new BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); + | CallExprNoBF '[' Expr ']' { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @4.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | CallExprNoBF '.' IDENT { DotAccessorNode* node = new DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3); + | CallExprNoBF '.' IDENT { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3); SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @3.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants); } ; Arguments: - '(' ')' { $$ = createNodeInfo<ArgumentsNode*>(new ArgumentsNode(GLOBAL_DATA), 0, 0); } - | '(' ArgumentList ')' { $$ = createNodeInfo<ArgumentsNode*>(new ArgumentsNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); } + '(' ')' { $$ = createNodeInfo<ArgumentsNode*>(new (GLOBAL_DATA) ArgumentsNode(GLOBAL_DATA), 0, 0); } + | '(' ArgumentList ')' { $$ = createNodeInfo<ArgumentsNode*>(new (GLOBAL_DATA) ArgumentsNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); } ; ArgumentList: - AssignmentExpr { $$.m_node.head = new ArgumentListNode(GLOBAL_DATA, $1.m_node); + AssignmentExpr { $$.m_node.head = new (GLOBAL_DATA) ArgumentListNode(GLOBAL_DATA, $1.m_node); $$.m_node.tail = $$.m_node.head; $$.m_features = $1.m_features; $$.m_numConstants = $1.m_numConstants; } | ArgumentList ',' AssignmentExpr { $$.m_node.head = $1.m_node.head; - $$.m_node.tail = new ArgumentListNode(GLOBAL_DATA, $1.m_node.tail, $3.m_node); + $$.m_node.tail = new (GLOBAL_DATA) ArgumentListNode(GLOBAL_DATA, $1.m_node.tail, $3.m_node); $$.m_features = $1.m_features | $3.m_features; $$.m_numConstants = $1.m_numConstants + $3.m_numConstants; } ; @@ -497,16 +497,16 @@ PostfixExprNoBF: UnaryExprCommon: DELETETOKEN UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeDeleteNode(GLOBAL_DATA, $2.m_node, @1.first_column, @2.last_column, @2.last_column), $2.m_features, $2.m_numConstants); } - | VOIDTOKEN UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new VoidNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants + 1); } + | VOIDTOKEN UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) VoidNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants + 1); } | TYPEOF UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeTypeOfNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); } | PLUSPLUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpPlusPlus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); } | AUTOPLUSPLUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpPlusPlus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); } | MINUSMINUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpMinusMinus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); } | AUTOMINUSMINUS UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpMinusMinus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); } - | '+' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new UnaryPlusNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); } + | '+' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) UnaryPlusNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); } | '-' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeNegateNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); } | '~' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeBitwiseNotNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); } - | '!' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalNotNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); } + | '!' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalNotNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); } UnaryExpr: PostfixExpr @@ -522,7 +522,7 @@ MultiplicativeExpr: UnaryExpr | MultiplicativeExpr '*' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeMultNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } | MultiplicativeExpr '/' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeDivNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | MultiplicativeExpr '%' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new ModNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | MultiplicativeExpr '%' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ModNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; MultiplicativeExprNoBF: @@ -532,7 +532,7 @@ MultiplicativeExprNoBF: | MultiplicativeExprNoBF '/' UnaryExpr { $$ = createNodeInfo<ExpressionNode*>(makeDivNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } | MultiplicativeExprNoBF '%' UnaryExpr - { $$ = createNodeInfo<ExpressionNode*>(new ModNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ModNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; AdditiveExpr: @@ -553,188 +553,188 @@ ShiftExpr: AdditiveExpr | ShiftExpr LSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeLeftShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } | ShiftExpr RSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | ShiftExpr URSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(new UnsignedRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | ShiftExpr URSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) UnsignedRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; ShiftExprNoBF: AdditiveExprNoBF | ShiftExprNoBF LSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeLeftShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } | ShiftExprNoBF RSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(makeRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | ShiftExprNoBF URSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(new UnsignedRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | ShiftExprNoBF URSHIFT AdditiveExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) UnsignedRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; RelationalExpr: ShiftExpr - | RelationalExpr '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | RelationalExpr '>' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | RelationalExpr LE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | RelationalExpr GE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | RelationalExpr INSTANCEOF ShiftExpr { InstanceOfNode* node = new InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); + | RelationalExpr '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | RelationalExpr '>' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | RelationalExpr LE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | RelationalExpr GE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | RelationalExpr INSTANCEOF ShiftExpr { InstanceOfNode* node = new (GLOBAL_DATA) InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | RelationalExpr INTOKEN ShiftExpr { InNode* node = new InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); + | RelationalExpr INTOKEN ShiftExpr { InNode* node = new (GLOBAL_DATA) InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; RelationalExprNoIn: ShiftExpr - | RelationalExprNoIn '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | RelationalExprNoIn '>' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | RelationalExprNoIn LE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | RelationalExprNoIn GE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | RelationalExprNoIn '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | RelationalExprNoIn '>' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | RelationalExprNoIn LE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | RelationalExprNoIn GE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } | RelationalExprNoIn INSTANCEOF ShiftExpr - { InstanceOfNode* node = new InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); + { InstanceOfNode* node = new (GLOBAL_DATA) InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; RelationalExprNoBF: ShiftExprNoBF - | RelationalExprNoBF '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | RelationalExprNoBF '>' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | RelationalExprNoBF LE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | RelationalExprNoBF GE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | RelationalExprNoBF '<' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | RelationalExprNoBF '>' ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | RelationalExprNoBF LE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | RelationalExprNoBF GE ShiftExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } | RelationalExprNoBF INSTANCEOF ShiftExpr - { InstanceOfNode* node = new InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); + { InstanceOfNode* node = new (GLOBAL_DATA) InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } | RelationalExprNoBF INTOKEN ShiftExpr - { InNode* node = new InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); + { InNode* node = new (GLOBAL_DATA) InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature); SET_EXCEPTION_LOCATION(node, @1.first_column, @3.first_column, @3.last_column); $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; EqualityExpr: RelationalExpr - | EqualityExpr EQEQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | EqualityExpr NE RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | EqualityExpr STREQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | EqualityExpr STRNEQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | EqualityExpr EQEQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | EqualityExpr NE RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | EqualityExpr STREQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | EqualityExpr STRNEQ RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; EqualityExprNoIn: RelationalExprNoIn | EqualityExprNoIn EQEQ RelationalExprNoIn - { $$ = createNodeInfo<ExpressionNode*>(new EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } | EqualityExprNoIn NE RelationalExprNoIn - { $$ = createNodeInfo<ExpressionNode*>(new NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } | EqualityExprNoIn STREQ RelationalExprNoIn - { $$ = createNodeInfo<ExpressionNode*>(new StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } | EqualityExprNoIn STRNEQ RelationalExprNoIn - { $$ = createNodeInfo<ExpressionNode*>(new NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; EqualityExprNoBF: RelationalExprNoBF | EqualityExprNoBF EQEQ RelationalExpr - { $$ = createNodeInfo<ExpressionNode*>(new EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } - | EqualityExprNoBF NE RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | EqualityExprNoBF NE RelationalExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } | EqualityExprNoBF STREQ RelationalExpr - { $$ = createNodeInfo<ExpressionNode*>(new StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } | EqualityExprNoBF STRNEQ RelationalExpr - { $$ = createNodeInfo<ExpressionNode*>(new NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; BitwiseANDExpr: EqualityExpr - | BitwiseANDExpr '&' EqualityExpr { $$ = createNodeInfo<ExpressionNode*>(new BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | BitwiseANDExpr '&' EqualityExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; BitwiseANDExprNoIn: EqualityExprNoIn | BitwiseANDExprNoIn '&' EqualityExprNoIn - { $$ = createNodeInfo<ExpressionNode*>(new BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; BitwiseANDExprNoBF: EqualityExprNoBF - | BitwiseANDExprNoBF '&' EqualityExpr { $$ = createNodeInfo<ExpressionNode*>(new BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | BitwiseANDExprNoBF '&' EqualityExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; BitwiseXORExpr: BitwiseANDExpr - | BitwiseXORExpr '^' BitwiseANDExpr { $$ = createNodeInfo<ExpressionNode*>(new BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | BitwiseXORExpr '^' BitwiseANDExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; BitwiseXORExprNoIn: BitwiseANDExprNoIn | BitwiseXORExprNoIn '^' BitwiseANDExprNoIn - { $$ = createNodeInfo<ExpressionNode*>(new BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; BitwiseXORExprNoBF: BitwiseANDExprNoBF | BitwiseXORExprNoBF '^' BitwiseANDExpr - { $$ = createNodeInfo<ExpressionNode*>(new BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; BitwiseORExpr: BitwiseXORExpr - | BitwiseORExpr '|' BitwiseXORExpr { $$ = createNodeInfo<ExpressionNode*>(new BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | BitwiseORExpr '|' BitwiseXORExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; BitwiseORExprNoIn: BitwiseXORExprNoIn | BitwiseORExprNoIn '|' BitwiseXORExprNoIn - { $$ = createNodeInfo<ExpressionNode*>(new BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; BitwiseORExprNoBF: BitwiseXORExprNoBF | BitwiseORExprNoBF '|' BitwiseXORExpr - { $$ = createNodeInfo<ExpressionNode*>(new BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; LogicalANDExpr: BitwiseORExpr - | LogicalANDExpr AND BitwiseORExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | LogicalANDExpr AND BitwiseORExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; LogicalANDExprNoIn: BitwiseORExprNoIn | LogicalANDExprNoIn AND BitwiseORExprNoIn - { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; LogicalANDExprNoBF: BitwiseORExprNoBF | LogicalANDExprNoBF AND BitwiseORExpr - { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; LogicalORExpr: LogicalANDExpr - | LogicalORExpr OR LogicalANDExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | LogicalORExpr OR LogicalANDExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; LogicalORExprNoIn: LogicalANDExprNoIn | LogicalORExprNoIn OR LogicalANDExprNoIn - { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; LogicalORExprNoBF: LogicalANDExprNoBF - | LogicalORExprNoBF OR LogicalANDExpr { $$ = createNodeInfo<ExpressionNode*>(new LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | LogicalORExprNoBF OR LogicalANDExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; ConditionalExpr: LogicalORExpr | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr - { $$ = createNodeInfo<ExpressionNode*>(new ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); } ; ConditionalExprNoIn: LogicalORExprNoIn | LogicalORExprNoIn '?' AssignmentExprNoIn ':' AssignmentExprNoIn - { $$ = createNodeInfo<ExpressionNode*>(new ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); } ; ConditionalExprNoBF: LogicalORExprNoBF | LogicalORExprNoBF '?' AssignmentExpr ':' AssignmentExpr - { $$ = createNodeInfo<ExpressionNode*>(new ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); } + { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); } ; AssignmentExpr: @@ -778,17 +778,17 @@ AssignmentOperator: Expr: AssignmentExpr - | Expr ',' AssignmentExpr { $$ = createNodeInfo<ExpressionNode*>(new CommaNode(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | Expr ',' AssignmentExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) CommaNode(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; ExprNoIn: AssignmentExprNoIn - | ExprNoIn ',' AssignmentExprNoIn { $$ = createNodeInfo<ExpressionNode*>(new CommaNode(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | ExprNoIn ',' AssignmentExprNoIn { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) CommaNode(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; ExprNoBF: AssignmentExprNoBF - | ExprNoBF ',' AssignmentExpr { $$ = createNodeInfo<ExpressionNode*>(new CommaNode(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } + | ExprNoBF ',' AssignmentExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) CommaNode(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); } ; Statement: @@ -812,9 +812,9 @@ Statement: ; Block: - OPENBRACE CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new BlockNode(GLOBAL_DATA, 0), 0, 0, 0, 0); + OPENBRACE CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BlockNode(GLOBAL_DATA, 0), 0, 0, 0, 0); DBG($$.m_node, @1, @2); } - | OPENBRACE SourceElements CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new BlockNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants); + | OPENBRACE SourceElements CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BlockNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @3); } ; @@ -828,16 +828,16 @@ VariableStatement: VariableDeclarationList: IDENT { $$.m_node = 0; - $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA); + $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>; appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, 0); $$.m_funcDeclarations = 0; $$.m_features = (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0; $$.m_numConstants = 0; } - | IDENT Initializer { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature); + | IDENT Initializer { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature); SET_EXCEPTION_LOCATION(node, @1.first_column, @2.first_column + 1, @2.last_column); $$.m_node = node; - $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA); + $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>; appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer); $$.m_funcDeclarations = 0; $$.m_features = ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features; @@ -852,7 +852,7 @@ VariableDeclarationList: $$.m_numConstants = $1.m_numConstants; } | VariableDeclarationList ',' IDENT Initializer - { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature); + { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature); SET_EXCEPTION_LOCATION(node, @3.first_column, @4.first_column + 1, @4.last_column); $$.m_node = combineVarInitializers(GLOBAL_DATA, $1.m_node, node); $$.m_varDeclarations = $1.m_varDeclarations; @@ -865,16 +865,16 @@ VariableDeclarationList: VariableDeclarationListNoIn: IDENT { $$.m_node = 0; - $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA); + $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>; appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, 0); $$.m_funcDeclarations = 0; $$.m_features = (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0; $$.m_numConstants = 0; } - | IDENT InitializerNoIn { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature); + | IDENT InitializerNoIn { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature); SET_EXCEPTION_LOCATION(node, @1.first_column, @2.first_column + 1, @2.last_column); $$.m_node = node; - $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA); + $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>; appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer); $$.m_funcDeclarations = 0; $$.m_features = ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features; @@ -889,7 +889,7 @@ VariableDeclarationListNoIn: $$.m_numConstants = $1.m_numConstants; } | VariableDeclarationListNoIn ',' IDENT InitializerNoIn - { AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature); + { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature); SET_EXCEPTION_LOCATION(node, @3.first_column, @4.first_column + 1, @4.last_column); $$.m_node = combineVarInitializers(GLOBAL_DATA, $1.m_node, node); $$.m_varDeclarations = $1.m_varDeclarations; @@ -901,24 +901,24 @@ VariableDeclarationListNoIn: ; ConstStatement: - CONSTTOKEN ConstDeclarationList ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants); + CONSTTOKEN ConstDeclarationList ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @3); } | CONSTTOKEN ConstDeclarationList error - { $$ = createNodeDeclarationInfo<StatementNode*>(new ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants); + { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; } ; ConstDeclarationList: ConstDeclaration { $$.m_node.head = $1.m_node; $$.m_node.tail = $$.m_node.head; - $$.m_varDeclarations = new ParserRefCountedData<DeclarationStacks::VarStack>(GLOBAL_DATA); + $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>; appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, $1.m_node); $$.m_funcDeclarations = 0; $$.m_features = $1.m_features; $$.m_numConstants = $1.m_numConstants; } | ConstDeclarationList ',' ConstDeclaration - { $$.m_node.head = $1.m_node.head; + { $$.m_node.head = $1.m_node.head; $1.m_node.tail->m_next = $3.m_node; $$.m_node.tail = $3.m_node; $$.m_varDeclarations = $1.m_varDeclarations; @@ -929,8 +929,8 @@ ConstDeclarationList: ; ConstDeclaration: - IDENT { $$ = createNodeInfo<ConstDeclNode*>(new ConstDeclNode(GLOBAL_DATA, *$1, 0), (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0, 0); } - | IDENT Initializer { $$ = createNodeInfo<ConstDeclNode*>(new ConstDeclNode(GLOBAL_DATA, *$1, $2.m_node), ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features, $2.m_numConstants); } + IDENT { $$ = createNodeInfo<ConstDeclNode*>(new (GLOBAL_DATA) ConstDeclNode(GLOBAL_DATA, *$1, 0), (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0, 0); } + | IDENT Initializer { $$ = createNodeInfo<ConstDeclNode*>(new (GLOBAL_DATA) ConstDeclNode(GLOBAL_DATA, *$1, $2.m_node), ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features, $2.m_numConstants); } ; Initializer: @@ -942,43 +942,44 @@ InitializerNoIn: ; EmptyStatement: - ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new EmptyStatementNode(GLOBAL_DATA), 0, 0, 0, 0); } + ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) EmptyStatementNode(GLOBAL_DATA), 0, 0, 0, 0); } ; ExprStatement: - ExprNoBF ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants); + ExprNoBF ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants); DBG($$.m_node, @1, @2); } - | ExprNoBF error { $$ = createNodeDeclarationInfo<StatementNode*>(new ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants); + | ExprNoBF error { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; } ; IfStatement: IF '(' Expr ')' Statement %prec IF_WITHOUT_ELSE - { $$ = createNodeDeclarationInfo<StatementNode*>(new IfNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants); + { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) IfNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants); DBG($$.m_node, @1, @4); } | IF '(' Expr ')' Statement ELSE Statement - { $$ = createNodeDeclarationInfo<StatementNode*>(new IfElseNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node), - mergeDeclarationLists($5.m_varDeclarations, $7.m_varDeclarations), mergeDeclarationLists($5.m_funcDeclarations, $7.m_funcDeclarations), + { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) IfElseNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node), + mergeDeclarationLists($5.m_varDeclarations, $7.m_varDeclarations), + mergeDeclarationLists($5.m_funcDeclarations, $7.m_funcDeclarations), $3.m_features | $5.m_features | $7.m_features, $3.m_numConstants + $5.m_numConstants + $7.m_numConstants); DBG($$.m_node, @1, @4); } ; IterationStatement: - DO Statement WHILE '(' Expr ')' ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants); + DO Statement WHILE '(' Expr ')' ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants); DBG($$.m_node, @1, @3); } - | DO Statement WHILE '(' Expr ')' error { $$ = createNodeDeclarationInfo<StatementNode*>(new DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants); + | DO Statement WHILE '(' Expr ')' error { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants); DBG($$.m_node, @1, @3); } // Always performs automatic semicolon insertion. - | WHILE '(' Expr ')' Statement { $$ = createNodeDeclarationInfo<StatementNode*>(new WhileNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants); + | WHILE '(' Expr ')' Statement { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) WhileNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants); DBG($$.m_node, @1, @4); } | FOR '(' ExprNoInOpt ';' ExprOpt ';' ExprOpt ')' Statement - { $$ = createNodeDeclarationInfo<StatementNode*>(new ForNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node, $9.m_node, false), $9.m_varDeclarations, $9.m_funcDeclarations, + { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ForNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node, $9.m_node, false), $9.m_varDeclarations, $9.m_funcDeclarations, $3.m_features | $5.m_features | $7.m_features | $9.m_features, $3.m_numConstants + $5.m_numConstants + $7.m_numConstants + $9.m_numConstants); DBG($$.m_node, @1, @8); } | FOR '(' VAR VariableDeclarationListNoIn ';' ExprOpt ';' ExprOpt ')' Statement - { $$ = createNodeDeclarationInfo<StatementNode*>(new ForNode(GLOBAL_DATA, $4.m_node, $6.m_node, $8.m_node, $10.m_node, true), + { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ForNode(GLOBAL_DATA, $4.m_node, $6.m_node, $8.m_node, $10.m_node, true), mergeDeclarationLists($4.m_varDeclarations, $10.m_varDeclarations), mergeDeclarationLists($4.m_funcDeclarations, $10.m_funcDeclarations), $4.m_features | $6.m_features | $8.m_features | $10.m_features, @@ -986,7 +987,7 @@ IterationStatement: DBG($$.m_node, @1, @9); } | FOR '(' LeftHandSideExpr INTOKEN Expr ')' Statement { - ForInNode* node = new ForInNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node); + ForInNode* node = new (GLOBAL_DATA) ForInNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node); SET_EXCEPTION_LOCATION(node, @3.first_column, @3.last_column, @5.last_column); $$ = createNodeDeclarationInfo<StatementNode*>(node, $7.m_varDeclarations, $7.m_funcDeclarations, $3.m_features | $5.m_features | $7.m_features, @@ -994,13 +995,13 @@ IterationStatement: DBG($$.m_node, @1, @6); } | FOR '(' VAR IDENT INTOKEN Expr ')' Statement - { ForInNode *forIn = new ForInNode(GLOBAL_DATA, *$4, 0, $6.m_node, $8.m_node, @5.first_column, @5.first_column - @4.first_column, @6.last_column - @5.first_column); + { ForInNode *forIn = new (GLOBAL_DATA) ForInNode(GLOBAL_DATA, *$4, 0, $6.m_node, $8.m_node, @5.first_column, @5.first_column - @4.first_column, @6.last_column - @5.first_column); SET_EXCEPTION_LOCATION(forIn, @4.first_column, @5.first_column + 1, @6.last_column); appendToVarDeclarationList(GLOBAL_DATA, $8.m_varDeclarations, *$4, DeclarationStacks::HasInitializer); $$ = createNodeDeclarationInfo<StatementNode*>(forIn, $8.m_varDeclarations, $8.m_funcDeclarations, ((*$4 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $6.m_features | $8.m_features, $6.m_numConstants + $8.m_numConstants); DBG($$.m_node, @1, @7); } | FOR '(' VAR IDENT InitializerNoIn INTOKEN Expr ')' Statement - { ForInNode *forIn = new ForInNode(GLOBAL_DATA, *$4, $5.m_node, $7.m_node, $9.m_node, @5.first_column, @5.first_column - @4.first_column, @5.last_column - @5.first_column); + { ForInNode *forIn = new (GLOBAL_DATA) ForInNode(GLOBAL_DATA, *$4, $5.m_node, $7.m_node, $9.m_node, @5.first_column, @5.first_column - @4.first_column, @5.last_column - @5.first_column); SET_EXCEPTION_LOCATION(forIn, @4.first_column, @6.first_column + 1, @7.last_column); appendToVarDeclarationList(GLOBAL_DATA, $9.m_varDeclarations, *$4, DeclarationStacks::HasInitializer); $$ = createNodeDeclarationInfo<StatementNode*>(forIn, $9.m_varDeclarations, $9.m_funcDeclarations, @@ -1020,70 +1021,70 @@ ExprNoInOpt: ; ContinueStatement: - CONTINUE ';' { ContinueNode* node = new ContinueNode(GLOBAL_DATA); + CONTINUE ';' { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA); SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column); $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @2); } - | CONTINUE error { ContinueNode* node = new ContinueNode(GLOBAL_DATA); + | CONTINUE error { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA); SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column); $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; } - | CONTINUE IDENT ';' { ContinueNode* node = new ContinueNode(GLOBAL_DATA, *$2); + | CONTINUE IDENT ';' { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA, *$2); SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column); $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @3); } - | CONTINUE IDENT error { ContinueNode* node = new ContinueNode(GLOBAL_DATA, *$2); + | CONTINUE IDENT error { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA, *$2); SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column); $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; } ; BreakStatement: - BREAK ';' { BreakNode* node = new BreakNode(GLOBAL_DATA); + BREAK ';' { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA); SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column); $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @2); } - | BREAK error { BreakNode* node = new BreakNode(GLOBAL_DATA); + | BREAK error { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA); SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column); - $$ = createNodeDeclarationInfo<StatementNode*>(new BreakNode(GLOBAL_DATA), 0, 0, 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; } - | BREAK IDENT ';' { BreakNode* node = new BreakNode(GLOBAL_DATA, *$2); + $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BreakNode(GLOBAL_DATA), 0, 0, 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; } + | BREAK IDENT ';' { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *$2); SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column); $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @3); } - | BREAK IDENT error { BreakNode* node = new BreakNode(GLOBAL_DATA, *$2); + | BREAK IDENT error { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *$2); SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column); - $$ = createNodeDeclarationInfo<StatementNode*>(new BreakNode(GLOBAL_DATA, *$2), 0, 0, 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; } + $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *$2), 0, 0, 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; } ; ReturnStatement: - RETURN ';' { ReturnNode* node = new ReturnNode(GLOBAL_DATA, 0); + RETURN ';' { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, 0); SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column); $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @2); } - | RETURN error { ReturnNode* node = new ReturnNode(GLOBAL_DATA, 0); + | RETURN error { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, 0); SET_EXCEPTION_LOCATION(node, @1.first_column, @1.last_column, @1.last_column); $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; } - | RETURN Expr ';' { ReturnNode* node = new ReturnNode(GLOBAL_DATA, $2.m_node); + | RETURN Expr ';' { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, $2.m_node); SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column); $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @3); } - | RETURN Expr error { ReturnNode* node = new ReturnNode(GLOBAL_DATA, $2.m_node); + | RETURN Expr error { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, $2.m_node); SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column); $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; } ; WithStatement: - WITH '(' Expr ')' Statement { $$ = createNodeDeclarationInfo<StatementNode*>(new WithNode(GLOBAL_DATA, $3.m_node, $5.m_node, @3.last_column, @3.last_column - @3.first_column), + WITH '(' Expr ')' Statement { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) WithNode(GLOBAL_DATA, $3.m_node, $5.m_node, @3.last_column, @3.last_column - @3.first_column), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features | WithFeature, $3.m_numConstants + $5.m_numConstants); DBG($$.m_node, @1, @4); } ; SwitchStatement: - SWITCH '(' Expr ')' CaseBlock { $$ = createNodeDeclarationInfo<StatementNode*>(new SwitchNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, + SWITCH '(' Expr ')' CaseBlock { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) SwitchNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants); DBG($$.m_node, @1, @4); } ; CaseBlock: - OPENBRACE CaseClausesOpt CLOSEBRACE { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new CaseBlockNode(GLOBAL_DATA, $2.m_node.head, 0, 0), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants); } + OPENBRACE CaseClausesOpt CLOSEBRACE { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new (GLOBAL_DATA) CaseBlockNode(GLOBAL_DATA, $2.m_node.head, 0, 0), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants); } | OPENBRACE CaseClausesOpt DefaultClause CaseClausesOpt CLOSEBRACE - { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new CaseBlockNode(GLOBAL_DATA, $2.m_node.head, $3.m_node, $4.m_node.head), + { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new (GLOBAL_DATA) CaseBlockNode(GLOBAL_DATA, $2.m_node.head, $3.m_node, $4.m_node.head), mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $3.m_varDeclarations), $4.m_varDeclarations), mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $3.m_funcDeclarations), $4.m_funcDeclarations), $2.m_features | $3.m_features | $4.m_features, @@ -1096,14 +1097,14 @@ CaseClausesOpt: ; CaseClauses: - CaseClause { $$.m_node.head = new ClauseListNode(GLOBAL_DATA, $1.m_node); + CaseClause { $$.m_node.head = new (GLOBAL_DATA) ClauseListNode(GLOBAL_DATA, $1.m_node); $$.m_node.tail = $$.m_node.head; $$.m_varDeclarations = $1.m_varDeclarations; $$.m_funcDeclarations = $1.m_funcDeclarations; $$.m_features = $1.m_features; $$.m_numConstants = $1.m_numConstants; } | CaseClauses CaseClause { $$.m_node.head = $1.m_node.head; - $$.m_node.tail = new ClauseListNode(GLOBAL_DATA, $1.m_node.tail, $2.m_node); + $$.m_node.tail = new (GLOBAL_DATA) ClauseListNode(GLOBAL_DATA, $1.m_node.tail, $2.m_node); $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations); $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations); $$.m_features = $1.m_features | $2.m_features; @@ -1112,47 +1113,47 @@ CaseClauses: ; CaseClause: - CASE Expr ':' { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, $2.m_node), 0, 0, $2.m_features, $2.m_numConstants); } - | CASE Expr ':' SourceElements { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, $2.m_node, $4.m_node), $4.m_varDeclarations, $4.m_funcDeclarations, $2.m_features | $4.m_features, $2.m_numConstants + $4.m_numConstants); } + CASE Expr ':' { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) CaseClauseNode(GLOBAL_DATA, $2.m_node), 0, 0, $2.m_features, $2.m_numConstants); } + | CASE Expr ':' SourceElements { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) CaseClauseNode(GLOBAL_DATA, $2.m_node, $4.m_node), $4.m_varDeclarations, $4.m_funcDeclarations, $2.m_features | $4.m_features, $2.m_numConstants + $4.m_numConstants); } ; DefaultClause: - DEFAULT ':' { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, 0), 0, 0, 0, 0); } - | DEFAULT ':' SourceElements { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new CaseClauseNode(GLOBAL_DATA, 0, $3.m_node), $3.m_varDeclarations, $3.m_funcDeclarations, $3.m_features, $3.m_numConstants); } + DEFAULT ':' { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) CaseClauseNode(GLOBAL_DATA, 0), 0, 0, 0, 0); } + | DEFAULT ':' SourceElements { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) CaseClauseNode(GLOBAL_DATA, 0, $3.m_node), $3.m_varDeclarations, $3.m_funcDeclarations, $3.m_features, $3.m_numConstants); } ; LabelledStatement: - IDENT ':' Statement { LabelNode* node = new LabelNode(GLOBAL_DATA, *$1, $3.m_node); + IDENT ':' Statement { LabelNode* node = new (GLOBAL_DATA) LabelNode(GLOBAL_DATA, *$1, $3.m_node); SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column); $$ = createNodeDeclarationInfo<StatementNode*>(node, $3.m_varDeclarations, $3.m_funcDeclarations, $3.m_features, $3.m_numConstants); } ; ThrowStatement: - THROW Expr ';' { ThrowNode* node = new ThrowNode(GLOBAL_DATA, $2.m_node); + THROW Expr ';' { ThrowNode* node = new (GLOBAL_DATA) ThrowNode(GLOBAL_DATA, $2.m_node); SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column); $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2); } - | THROW Expr error { ThrowNode* node = new ThrowNode(GLOBAL_DATA, $2.m_node); + | THROW Expr error { ThrowNode* node = new (GLOBAL_DATA) ThrowNode(GLOBAL_DATA, $2.m_node); SET_EXCEPTION_LOCATION(node, @1.first_column, @2.last_column, @2.last_column); $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; } ; TryStatement: - TRY Block FINALLY Block { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, GLOBAL_DATA->propertyNames->nullIdentifier, false, 0, $4.m_node), + TRY Block FINALLY Block { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, $2.m_node, GLOBAL_DATA->propertyNames->nullIdentifier, false, 0, $4.m_node), mergeDeclarationLists($2.m_varDeclarations, $4.m_varDeclarations), mergeDeclarationLists($2.m_funcDeclarations, $4.m_funcDeclarations), $2.m_features | $4.m_features, $2.m_numConstants + $4.m_numConstants); DBG($$.m_node, @1, @2); } - | TRY Block CATCH '(' IDENT ')' Block { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, 0), + | TRY Block CATCH '(' IDENT ')' Block { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, 0), mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations), mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations), $2.m_features | $7.m_features | CatchFeature, $2.m_numConstants + $7.m_numConstants); DBG($$.m_node, @1, @2); } | TRY Block CATCH '(' IDENT ')' Block FINALLY Block - { $$ = createNodeDeclarationInfo<StatementNode*>(new TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, $9.m_node), + { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, $9.m_node), mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations), $9.m_varDeclarations), mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations), $9.m_funcDeclarations), $2.m_features | $7.m_features | $9.m_features | CatchFeature, @@ -1161,17 +1162,17 @@ TryStatement: ; DebuggerStatement: - DEBUGGER ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0); + DEBUGGER ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0); DBG($$.m_node, @1, @2); } - | DEBUGGER error { $$ = createNodeDeclarationInfo<StatementNode*>(new DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0); + | DEBUGGER error { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; } ; FunctionDeclaration: - FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new FuncDeclNode(GLOBAL_DATA, *$2, $6, LEXER->sourceCode($5, $7, @5.first_line)), 0, new ParserRefCountedData<DeclarationStacks::FunctionStack>(GLOBAL_DATA), ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | ClosureFeature, 0); DBG($6, @5, @7); $$.m_funcDeclarations->data.append(static_cast<FuncDeclNode*>($$.m_node)); } + FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new FuncDeclNode(GLOBAL_DATA, *$2, $6, LEXER->sourceCode($5, $7, @5.first_line)), 0, new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::FunctionStack>, ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | ClosureFeature, 0); DBG($6, @5, @7); $$.m_funcDeclarations->data.append(static_cast<FuncDeclNode*>($$.m_node)); } | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE { - $$ = createNodeDeclarationInfo<StatementNode*>(new FuncDeclNode(GLOBAL_DATA, *$2, $7, LEXER->sourceCode($6, $8, @6.first_line), $4.m_node.head), 0, new ParserRefCountedData<DeclarationStacks::FunctionStack>(GLOBAL_DATA), ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features | ClosureFeature, 0); + $$ = createNodeDeclarationInfo<StatementNode*>(new FuncDeclNode(GLOBAL_DATA, *$2, $7, LEXER->sourceCode($6, $8, @6.first_line), $4.m_node.head), 0, new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::FunctionStack>, ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features | ClosureFeature, 0); if ($4.m_features & ArgumentsFeature) $7->setUsesArguments(); DBG($7, @6, @8); @@ -1199,12 +1200,12 @@ FunctionExpr: ; FormalParameterList: - IDENT { $$.m_node.head = new ParameterNode(GLOBAL_DATA, *$1); + IDENT { $$.m_node.head = new (GLOBAL_DATA) ParameterNode(GLOBAL_DATA, *$1); $$.m_features = (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0; $$.m_node.tail = $$.m_node.head; } | FormalParameterList ',' IDENT { $$.m_node.head = $1.m_node.head; $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0); - $$.m_node.tail = new ParameterNode(GLOBAL_DATA, $1.m_node.tail, *$3); } + $$.m_node.tail = new (GLOBAL_DATA) ParameterNode(GLOBAL_DATA, $1.m_node.tail, *$3); } ; FunctionBody: @@ -1213,13 +1214,13 @@ FunctionBody: ; Program: - /* not in spec */ { GLOBAL_DATA->parser->didFinishParsing(new SourceElements(GLOBAL_DATA), 0, 0, NoFeatures, @0.last_line, 0); } + /* not in spec */ { GLOBAL_DATA->parser->didFinishParsing(new (GLOBAL_DATA) SourceElements(GLOBAL_DATA), 0, 0, NoFeatures, @0.last_line, 0); } | SourceElements { GLOBAL_DATA->parser->didFinishParsing($1.m_node, $1.m_varDeclarations, $1.m_funcDeclarations, $1.m_features, @1.last_line, $1.m_numConstants); } ; SourceElements: - Statement { $$.m_node = new SourceElements(GLOBAL_DATA); + Statement { $$.m_node = new (GLOBAL_DATA) SourceElements(GLOBAL_DATA); $$.m_node->append($1.m_node); $$.m_varDeclarations = $1.m_varDeclarations; $$.m_funcDeclarations = $1.m_funcDeclarations; @@ -1828,23 +1829,23 @@ SourceElements_NoNode: static ExpressionNode* makeAssignNode(void* globalPtr, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end) { if (!loc->isLocation()) - return new AssignErrorNode(GLOBAL_DATA, loc, op, expr, divot, divot - start, end - divot); + return new (GLOBAL_DATA) AssignErrorNode(GLOBAL_DATA, loc, op, expr, divot, divot - start, end - divot); if (loc->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(loc); if (op == OpEqual) { - AssignResolveNode* node = new AssignResolveNode(GLOBAL_DATA, resolve->identifier(), expr, exprHasAssignments); + AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, resolve->identifier(), expr, exprHasAssignments); SET_EXCEPTION_LOCATION(node, start, divot, end); return node; } else - return new ReadModifyResolveNode(GLOBAL_DATA, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot); + return new (GLOBAL_DATA) ReadModifyResolveNode(GLOBAL_DATA, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot); } if (loc->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc); if (op == OpEqual) - return new AssignBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot()); + return new (GLOBAL_DATA) AssignBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot()); else { - ReadModifyBracketNode* node = new ReadModifyBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, divot - start, end - divot); + ReadModifyBracketNode* node = new (GLOBAL_DATA) ReadModifyBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, divot - start, end - divot); node->setSubexpressionInfo(bracket->divot(), bracket->endOffset()); return node; } @@ -1852,9 +1853,9 @@ static ExpressionNode* makeAssignNode(void* globalPtr, ExpressionNode* loc, Oper ASSERT(loc->isDotAccessorNode()); DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc); if (op == OpEqual) - return new AssignDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot()); + return new (GLOBAL_DATA) AssignDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot()); - ReadModifyDotNode* node = new ReadModifyDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot); + ReadModifyDotNode* node = new (GLOBAL_DATA) ReadModifyDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot); node->setSubexpressionInfo(dot->divot(), dot->endOffset()); return node; } @@ -1862,21 +1863,21 @@ static ExpressionNode* makeAssignNode(void* globalPtr, ExpressionNode* loc, Oper static ExpressionNode* makePrefixNode(void* globalPtr, ExpressionNode* expr, Operator op, int start, int divot, int end) { if (!expr->isLocation()) - return new PrefixErrorNode(GLOBAL_DATA, expr, op, divot, divot - start, end - divot); + return new (GLOBAL_DATA) PrefixErrorNode(GLOBAL_DATA, expr, op, divot, divot - start, end - divot); if (expr->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(expr); - return new PrefixResolveNode(GLOBAL_DATA, resolve->identifier(), op, divot, divot - start, end - divot); + return new (GLOBAL_DATA) PrefixResolveNode(GLOBAL_DATA, resolve->identifier(), op, divot, divot - start, end - divot); } if (expr->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr); - PrefixBracketNode* node = new PrefixBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot); + PrefixBracketNode* node = new (GLOBAL_DATA) PrefixBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot); node->setSubexpressionInfo(bracket->divot(), bracket->startOffset()); return node; } ASSERT(expr->isDotAccessorNode()); DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr); - PrefixDotNode* node = new PrefixDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, divot, divot - start, end - divot); + PrefixDotNode* node = new (GLOBAL_DATA) PrefixDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, divot, divot - start, end - divot); node->setSubexpressionInfo(dot->divot(), dot->startOffset()); return node; } @@ -1884,22 +1885,22 @@ static ExpressionNode* makePrefixNode(void* globalPtr, ExpressionNode* expr, Ope static ExpressionNode* makePostfixNode(void* globalPtr, ExpressionNode* expr, Operator op, int start, int divot, int end) { if (!expr->isLocation()) - return new PostfixErrorNode(GLOBAL_DATA, expr, op, divot, divot - start, end - divot); + return new (GLOBAL_DATA) PostfixErrorNode(GLOBAL_DATA, expr, op, divot, divot - start, end - divot); if (expr->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(expr); - return new PostfixResolveNode(GLOBAL_DATA, resolve->identifier(), op, divot, divot - start, end - divot); + return new (GLOBAL_DATA) PostfixResolveNode(GLOBAL_DATA, resolve->identifier(), op, divot, divot - start, end - divot); } if (expr->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr); - PostfixBracketNode* node = new PostfixBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot); + PostfixBracketNode* node = new (GLOBAL_DATA) PostfixBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot); node->setSubexpressionInfo(bracket->divot(), bracket->endOffset()); return node; } ASSERT(expr->isDotAccessorNode()); DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr); - PostfixDotNode* node = new PostfixDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, divot, divot - start, end - divot); + PostfixDotNode* node = new (GLOBAL_DATA) PostfixDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), op, divot, divot - start, end - divot); node->setSubexpressionInfo(dot->divot(), dot->endOffset()); return node; } @@ -1909,23 +1910,29 @@ static ExpressionNodeInfo makeFunctionCallNode(void* globalPtr, ExpressionNodeIn CodeFeatures features = func.m_features | args.m_features; int numConstants = func.m_numConstants + args.m_numConstants; if (!func.m_node->isLocation()) - return createNodeInfo<ExpressionNode*>(new FunctionCallValueNode(GLOBAL_DATA, func.m_node, args.m_node, divot, divot - start, end - divot), features, numConstants); + return createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) FunctionCallValueNode(GLOBAL_DATA, func.m_node, args.m_node, divot, divot - start, end - divot), features, numConstants); if (func.m_node->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(func.m_node); const Identifier& identifier = resolve->identifier(); if (identifier == GLOBAL_DATA->propertyNames->eval) - return createNodeInfo<ExpressionNode*>(new EvalFunctionCallNode(GLOBAL_DATA, args.m_node, divot, divot - start, end - divot), EvalFeature | features, numConstants); - return createNodeInfo<ExpressionNode*>(new FunctionCallResolveNode(GLOBAL_DATA, identifier, args.m_node, divot, divot - start, end - divot), features, numConstants); + return createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) EvalFunctionCallNode(GLOBAL_DATA, args.m_node, divot, divot - start, end - divot), EvalFeature | features, numConstants); + return createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) FunctionCallResolveNode(GLOBAL_DATA, identifier, args.m_node, divot, divot - start, end - divot), features, numConstants); } if (func.m_node->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func.m_node); - FunctionCallBracketNode* node = new FunctionCallBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), args.m_node, divot, divot - start, end - divot); + FunctionCallBracketNode* node = new (GLOBAL_DATA) FunctionCallBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), args.m_node, divot, divot - start, end - divot); node->setSubexpressionInfo(bracket->divot(), bracket->endOffset()); return createNodeInfo<ExpressionNode*>(node, features, numConstants); } ASSERT(func.m_node->isDotAccessorNode()); DotAccessorNode* dot = static_cast<DotAccessorNode*>(func.m_node); - FunctionCallDotNode* node = new FunctionCallDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot); + FunctionCallDotNode* node; + if (dot->identifier() == GLOBAL_DATA->propertyNames->call) + node = new (GLOBAL_DATA) CallFunctionCallDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot); + else if (dot->identifier() == GLOBAL_DATA->propertyNames->apply) + node = new (GLOBAL_DATA) ApplyFunctionCallDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot); + else + node = new (GLOBAL_DATA) FunctionCallDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot); node->setSubexpressionInfo(dot->divot(), dot->endOffset()); return createNodeInfo<ExpressionNode*>(node, features, numConstants); } @@ -1934,26 +1941,26 @@ static ExpressionNode* makeTypeOfNode(void* globalPtr, ExpressionNode* expr) { if (expr->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(expr); - return new TypeOfResolveNode(GLOBAL_DATA, resolve->identifier()); + return new (GLOBAL_DATA) TypeOfResolveNode(GLOBAL_DATA, resolve->identifier()); } - return new TypeOfValueNode(GLOBAL_DATA, expr); + return new (GLOBAL_DATA) TypeOfValueNode(GLOBAL_DATA, expr); } static ExpressionNode* makeDeleteNode(void* globalPtr, ExpressionNode* expr, int start, int divot, int end) { if (!expr->isLocation()) - return new DeleteValueNode(GLOBAL_DATA, expr); + return new (GLOBAL_DATA) DeleteValueNode(GLOBAL_DATA, expr); if (expr->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(expr); - return new DeleteResolveNode(GLOBAL_DATA, resolve->identifier(), divot, divot - start, end - divot); + return new (GLOBAL_DATA) DeleteResolveNode(GLOBAL_DATA, resolve->identifier(), divot, divot - start, end - divot); } if (expr->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr); - return new DeleteBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), divot, divot - start, end - divot); + return new (GLOBAL_DATA) DeleteBracketNode(GLOBAL_DATA, bracket->base(), bracket->subscript(), divot, divot - start, end - divot); } ASSERT(expr->isDotAccessorNode()); DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr); - return new DeleteDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), divot, divot - start, end - divot); + return new (GLOBAL_DATA) DeleteDotNode(GLOBAL_DATA, dot->base(), dot->identifier(), divot, divot - start, end - divot); } static PropertyNode* makeGetterOrSetterPropertyNode(void* globalPtr, const Identifier& getOrSet, const Identifier& name, ParameterNode* params, FunctionBodyNode* body, const SourceCode& source) @@ -1965,7 +1972,7 @@ static PropertyNode* makeGetterOrSetterPropertyNode(void* globalPtr, const Ident type = PropertyNode::Setter; else return 0; - return new PropertyNode(GLOBAL_DATA, name, new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, body, source, params), type); + return new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, name, new FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, body, source, params), type); } static ExpressionNode* makeNegateNode(void* globalPtr, ExpressionNode* n) @@ -1979,19 +1986,19 @@ static ExpressionNode* makeNegateNode(void* globalPtr, ExpressionNode* n) } } - return new NegateNode(GLOBAL_DATA, n); + return new (GLOBAL_DATA) NegateNode(GLOBAL_DATA, n); } static NumberNode* makeNumberNode(void* globalPtr, double d) { - return new NumberNode(GLOBAL_DATA, d); + return new (GLOBAL_DATA) NumberNode(GLOBAL_DATA, d); } static ExpressionNode* makeBitwiseNotNode(void* globalPtr, ExpressionNode* expr) { if (expr->isNumber()) return makeNumberNode(globalPtr, ~toInt32(static_cast<NumberNode*>(expr)->value())); - return new BitwiseNotNode(GLOBAL_DATA, expr); + return new (GLOBAL_DATA) BitwiseNotNode(GLOBAL_DATA, expr); } static ExpressionNode* makeMultNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) @@ -2003,12 +2010,12 @@ static ExpressionNode* makeMultNode(void* globalPtr, ExpressionNode* expr1, Expr return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value()); if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1) - return new UnaryPlusNode(GLOBAL_DATA, expr2); + return new (GLOBAL_DATA) UnaryPlusNode(GLOBAL_DATA, expr2); if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1) - return new UnaryPlusNode(GLOBAL_DATA, expr1); + return new (GLOBAL_DATA) UnaryPlusNode(GLOBAL_DATA, expr1); - return new MultNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments); + return new (GLOBAL_DATA) MultNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments); } static ExpressionNode* makeDivNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) @@ -2018,14 +2025,14 @@ static ExpressionNode* makeDivNode(void* globalPtr, ExpressionNode* expr1, Expre if (expr1->isNumber() && expr2->isNumber()) return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() / static_cast<NumberNode*>(expr2)->value()); - return new DivNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments); + return new (GLOBAL_DATA) DivNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments); } static ExpressionNode* makeAddNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() + static_cast<NumberNode*>(expr2)->value()); - return new AddNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments); + return new (GLOBAL_DATA) AddNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments); } static ExpressionNode* makeSubNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) @@ -2035,21 +2042,21 @@ static ExpressionNode* makeSubNode(void* globalPtr, ExpressionNode* expr1, Expre if (expr1->isNumber() && expr2->isNumber()) return makeNumberNode(globalPtr, static_cast<NumberNode*>(expr1)->value() - static_cast<NumberNode*>(expr2)->value()); - return new SubNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments); + return new (GLOBAL_DATA) SubNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments); } static ExpressionNode* makeLeftShiftNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) return makeNumberNode(globalPtr, toInt32(static_cast<NumberNode*>(expr1)->value()) << (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); - return new LeftShiftNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments); + return new (GLOBAL_DATA) LeftShiftNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments); } static ExpressionNode* makeRightShiftNode(void* globalPtr, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) return makeNumberNode(globalPtr, toInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); - return new RightShiftNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments); + return new (GLOBAL_DATA) RightShiftNode(GLOBAL_DATA, expr1, expr2, rightHasAssignments); } /* called by yyparse on error */ @@ -2068,7 +2075,7 @@ static ExpressionNode* combineVarInitializers(void* globalPtr, ExpressionNode* l { if (!list) return init; - return new VarDeclCommaNode(GLOBAL_DATA, list, init); + return new (GLOBAL_DATA) CommaNode(GLOBAL_DATA, list, init); } // We turn variable declarations into either assignments or empty @@ -2077,8 +2084,8 @@ static ExpressionNode* combineVarInitializers(void* globalPtr, ExpressionNode* l static StatementNode* makeVarStatementNode(void* globalPtr, ExpressionNode* expr) { if (!expr) - return new EmptyStatementNode(GLOBAL_DATA); - return new VarStatementNode(GLOBAL_DATA, expr); + return new (GLOBAL_DATA) EmptyStatementNode(GLOBAL_DATA); + return new (GLOBAL_DATA) VarStatementNode(GLOBAL_DATA, expr); } #undef GLOBAL_DATA diff --git a/JavaScriptCore/parser/Lexer.cpp b/JavaScriptCore/parser/Lexer.cpp index 6f65096..8e89c18 100644 --- a/JavaScriptCore/parser/Lexer.cpp +++ b/JavaScriptCore/parser/Lexer.cpp @@ -31,13 +31,12 @@ #include <ctype.h> #include <limits.h> #include <string.h> -#include <wtf/ASCIICType.h> #include <wtf/Assertions.h> using namespace WTF; using namespace Unicode; -// we can't specify the namespace in yacc's C output, so do it here +// We can't specify the namespace in yacc's C output, so do it here instead. using namespace JSC; #ifndef KDE_USE_FINAL @@ -47,7 +46,7 @@ using namespace JSC; #include "Lookup.h" #include "Lexer.lut.h" -// a bridge for yacc from the C world to C++ +// A bridge for yacc from the C world to the C++ world. int jscyylex(void* lvalp, void* llocp, void* globalData) { return static_cast<JSGlobalData*>(globalData)->lexer->lex(lvalp, llocp); @@ -55,29 +54,12 @@ int jscyylex(void* lvalp, void* llocp, void* globalData) namespace JSC { -static bool isDecimalDigit(int); +static const UChar byteOrderMark = 0xFEFF; Lexer::Lexer(JSGlobalData* globalData) - : yylineno(1) - , m_restrKeyword(false) - , m_eatNextIdentifier(false) - , m_stackToken(-1) - , m_lastToken(-1) - , m_position(0) - , m_code(0) - , m_length(0) - , m_isReparsing(false) - , m_atLineStart(true) - , m_current(0) - , m_next1(0) - , m_next2(0) - , m_next3(0) - , m_currentOffset(0) - , m_nextOffset1(0) - , m_nextOffset2(0) - , m_nextOffset3(0) + : m_isReparsing(false) , m_globalData(globalData) - , m_mainTable(JSC::mainTable) + , m_keywordTable(JSC::mainTable) { m_buffer8.reserveInitialCapacity(initialReadBufferCapacity); m_buffer16.reserveInitialCapacity(initialReadBufferCapacity); @@ -85,795 +67,882 @@ Lexer::Lexer(JSGlobalData* globalData) Lexer::~Lexer() { - m_mainTable.deleteTable(); + m_keywordTable.deleteTable(); +} + +inline const UChar* Lexer::currentCharacter() const +{ + return m_code - 4; +} + +inline int Lexer::currentOffset() const +{ + return currentCharacter() - m_codeStart; +} + +ALWAYS_INLINE void Lexer::shift1() +{ + m_current = m_next1; + m_next1 = m_next2; + m_next2 = m_next3; + if (LIKELY(m_code < m_codeEnd)) + m_next3 = m_code[0]; + else + m_next3 = -1; + + ++m_code; +} + +ALWAYS_INLINE void Lexer::shift2() +{ + m_current = m_next2; + m_next1 = m_next3; + if (LIKELY(m_code + 1 < m_codeEnd)) { + m_next2 = m_code[0]; + m_next3 = m_code[1]; + } else { + m_next2 = m_code < m_codeEnd ? m_code[0] : -1; + m_next3 = -1; + } + + m_code += 2; +} + +ALWAYS_INLINE void Lexer::shift3() +{ + m_current = m_next3; + if (LIKELY(m_code + 2 < m_codeEnd)) { + m_next1 = m_code[0]; + m_next2 = m_code[1]; + m_next3 = m_code[2]; + } else { + m_next1 = m_code < m_codeEnd ? m_code[0] : -1; + m_next2 = m_code + 1 < m_codeEnd ? m_code[1] : -1; + m_next3 = -1; + } + + m_code += 3; +} + +ALWAYS_INLINE void Lexer::shift4() +{ + if (LIKELY(m_code + 3 < m_codeEnd)) { + m_current = m_code[0]; + m_next1 = m_code[1]; + m_next2 = m_code[2]; + m_next3 = m_code[3]; + } else { + m_current = m_code < m_codeEnd ? m_code[0] : -1; + m_next1 = m_code + 1 < m_codeEnd ? m_code[1] : -1; + m_next2 = m_code + 2 < m_codeEnd ? m_code[2] : -1; + m_next3 = -1; + } + + m_code += 4; } void Lexer::setCode(const SourceCode& source) { - yylineno = source.firstLine(); - m_restrKeyword = false; + m_lineNumber = source.firstLine(); m_delimited = false; - m_eatNextIdentifier = false; - m_stackToken = -1; m_lastToken = -1; - m_position = source.startOffset(); + const UChar* data = source.provider()->data(); + m_source = &source; - m_code = source.provider()->data(); - m_length = source.endOffset(); - m_skipLF = false; - m_skipCR = false; + m_codeStart = data; + m_code = data + source.startOffset(); + m_codeEnd = data + source.endOffset(); m_error = false; m_atLineStart = true; - // read first characters - shift(4); + // ECMA-262 calls for stripping all Cf characters, but we only strip BOM characters. + // See <https://bugs.webkit.org/show_bug.cgi?id=4931> for details. + if (source.provider()->hasBOMs()) { + for (const UChar* p = m_codeStart; p < m_codeEnd; ++p) { + if (UNLIKELY(*p == byteOrderMark)) { + copyCodeWithoutBOMs(); + break; + } + } + } + + // Read the first characters into the 4-character buffer. + shift4(); + ASSERT(currentOffset() == source.startOffset()); } -void Lexer::shift(unsigned p) +void Lexer::copyCodeWithoutBOMs() { - // ECMA-262 calls for stripping Cf characters here, but we only do this for BOM, - // see <https://bugs.webkit.org/show_bug.cgi?id=4931>. - - while (p--) { - m_current = m_next1; - m_next1 = m_next2; - m_next2 = m_next3; - m_currentOffset = m_nextOffset1; - m_nextOffset1 = m_nextOffset2; - m_nextOffset2 = m_nextOffset3; - do { - if (m_position >= m_length) { - m_nextOffset3 = m_position; - m_position++; - m_next3 = -1; - break; - } - m_nextOffset3 = m_position; - m_next3 = m_code[m_position++]; - } while (m_next3 == 0xFEFF); + // Note: In this case, the character offset data for debugging will be incorrect. + // If it's important to correctly debug code with extraneous BOMs, then the caller + // should strip the BOMs when creating the SourceProvider object and do its own + // mapping of offsets within the stripped text to original text offset. + + m_codeWithoutBOMs.reserveCapacity(m_codeEnd - m_code); + for (const UChar* p = m_code; p < m_codeEnd; ++p) { + UChar c = *p; + if (c != byteOrderMark) + m_codeWithoutBOMs.append(c); + } + ptrdiff_t startDelta = m_codeStart - m_code; + m_code = m_codeWithoutBOMs.data(); + m_codeStart = m_code + startDelta; + m_codeEnd = m_codeWithoutBOMs.data() + m_codeWithoutBOMs.size(); +} + +void Lexer::shiftLineTerminator() +{ + ASSERT(isLineTerminator(m_current)); + + // Allow both CRLF and LFCR. + if (m_current + m_next1 == '\n' + '\r') + shift2(); + else + shift1(); + + ++m_lineNumber; +} + +ALWAYS_INLINE Identifier* Lexer::makeIdentifier(const UChar* characters, size_t length) +{ + m_identifiers.append(Identifier(m_globalData, characters, length)); + return &m_identifiers.last(); +} + +inline bool Lexer::lastTokenWasRestrKeyword() const +{ + return m_lastToken == CONTINUE || m_lastToken == BREAK || m_lastToken == RETURN || m_lastToken == THROW; +} + +static NEVER_INLINE bool isNonASCIIIdentStart(int c) +{ + return category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other); +} + +static inline bool isIdentStart(int c) +{ + return isASCII(c) ? isASCIIAlpha(c) || c == '$' || c == '_' : isNonASCIIIdentStart(c); +} + +static NEVER_INLINE bool isNonASCIIIdentPart(int c) +{ + return category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other + | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector); +} + +static inline bool isIdentPart(int c) +{ + return isASCII(c) ? isASCIIAlphanumeric(c) || c == '$' || c == '_' : isNonASCIIIdentPart(c); +} + +static inline int singleEscape(int c) +{ + switch (c) { + case 'b': + return 0x08; + case 't': + return 0x09; + case 'n': + return 0x0A; + case 'v': + return 0x0B; + case 'f': + return 0x0C; + case 'r': + return 0x0D; + default: + return c; } } -// called on each new line -void Lexer::nextLine() +inline void Lexer::record8(int c) { - yylineno++; - m_atLineStart = true; + ASSERT(c >= 0); + ASSERT(c <= 0xFF); + m_buffer8.append(static_cast<char>(c)); } -void Lexer::setDone(State s) +inline void Lexer::record16(UChar c) { - m_state = s; - m_done = true; + m_buffer16.append(c); +} + +inline void Lexer::record16(int c) +{ + ASSERT(c >= 0); + ASSERT(c <= USHRT_MAX); + record16(UChar(static_cast<unsigned short>(c))); } int Lexer::lex(void* p1, void* p2) { + ASSERT(!m_error); + ASSERT(m_buffer8.isEmpty()); + ASSERT(m_buffer16.isEmpty()); + YYSTYPE* lvalp = static_cast<YYSTYPE*>(p1); YYLTYPE* llocp = static_cast<YYLTYPE*>(p2); int token = 0; - m_state = Start; - unsigned short stringType = 0; // either single or double quotes - m_buffer8.clear(); - m_buffer16.clear(); - m_done = false; m_terminator = false; - m_skipLF = false; - m_skipCR = false; - - // did we push a token on the stack previously ? - // (after an automatic semicolon insertion) - if (m_stackToken >= 0) { - setDone(Other); - token = m_stackToken; - m_stackToken = 0; - } - int startOffset = m_currentOffset; - while (!m_done) { - if (m_skipLF && m_current != '\n') // found \r but not \n afterwards - m_skipLF = false; - if (m_skipCR && m_current != '\r') // found \n but not \r afterwards - m_skipCR = false; - if (m_skipLF || m_skipCR) { // found \r\n or \n\r -> eat the second one - m_skipLF = false; - m_skipCR = false; - shift(1); + +start: + while (isWhiteSpace(m_current)) + shift1(); + + int startOffset = currentOffset(); + + if (m_current == -1) { + if (!m_terminator && !m_delimited && !m_isReparsing) { + // automatic semicolon insertion if program incomplete + token = ';'; + goto doneSemicolon; } - switch (m_state) { - case Start: - startOffset = m_currentOffset; - if (isWhiteSpace()) { - // do nothing - } else if (m_current == '/' && m_next1 == '/') { - shift(1); - m_state = InSingleLineComment; - } else if (m_current == '/' && m_next1 == '*') { - shift(1); - m_state = InMultiLineComment; - } else if (m_current == -1) { - if (!m_terminator && !m_delimited && !m_isReparsing) { - // automatic semicolon insertion if program incomplete - token = ';'; - m_stackToken = 0; - setDone(Other); - } else - setDone(Eof); - } else if (isLineTerminator()) { - nextLine(); - m_terminator = true; - if (m_restrKeyword) { - token = ';'; - setDone(Other); - } - } else if (m_current == '"' || m_current == '\'') { - m_state = InString; - stringType = static_cast<unsigned short>(m_current); - } else if (isIdentStart(m_current)) { - record16(m_current); - m_state = InIdentifierOrKeyword; - } else if (m_current == '\\') - m_state = InIdentifierStartUnicodeEscapeStart; - else if (m_current == '0') { - record8(m_current); - m_state = InNum0; - } else if (isDecimalDigit(m_current)) { - record8(m_current); - m_state = InNum; - } else if (m_current == '.' && isDecimalDigit(m_next1)) { - record8(m_current); - m_state = InDecimal; - // <!-- marks the beginning of a line comment (for www usage) - } else if (m_current == '<' && m_next1 == '!' && m_next2 == '-' && m_next3 == '-') { - shift(3); - m_state = InSingleLineComment; - // same for --> - } else if (m_atLineStart && m_current == '-' && m_next1 == '-' && m_next2 == '>') { - shift(2); - m_state = InSingleLineComment; - } else { - token = matchPunctuator(lvalp->intValue, m_current, m_next1, m_next2, m_next3); - if (token != -1) - setDone(Other); - else - setDone(Bad); + return 0; + } + + m_delimited = false; + switch (m_current) { + case '>': + if (m_next1 == '>' && m_next2 == '>') { + if (m_next3 == '=') { + shift4(); + token = URSHIFTEQUAL; + break; } + shift3(); + token = URSHIFT; break; - case InString: - if (m_current == stringType) { - shift(1); - setDone(String); - } else if (isLineTerminator() || m_current == -1) - setDone(Bad); - else if (m_current == '\\') - m_state = InEscapeSequence; - else - record16(m_current); + } + if (m_next1 == '>') { + if (m_next2 == '=') { + shift3(); + token = RSHIFTEQUAL; + break; + } + shift2(); + token = RSHIFT; break; - // Escape Sequences inside of strings - case InEscapeSequence: - if (isOctalDigit(m_current)) { - if (m_current >= '0' && m_current <= '3' && - isOctalDigit(m_next1) && isOctalDigit(m_next2)) { - record16(convertOctal(m_current, m_next1, m_next2)); - shift(2); - m_state = InString; - } else if (isOctalDigit(m_current) && isOctalDigit(m_next1)) { - record16(convertOctal('0', m_current, m_next1)); - shift(1); - m_state = InString; - } else if (isOctalDigit(m_current)) { - record16(convertOctal('0', '0', m_current)); - m_state = InString; - } else - setDone(Bad); - } else if (m_current == 'x') - m_state = InHexEscape; - else if (m_current == 'u') - m_state = InUnicodeEscape; - else if (isLineTerminator()) { - nextLine(); - m_state = InString; - } else { - record16(singleEscape(static_cast<unsigned short>(m_current))); - m_state = InString; + } + if (m_next1 == '=') { + shift2(); + token = GE; + break; + } + shift1(); + token = '>'; + break; + case '=': + if (m_next1 == '=') { + if (m_next2 == '=') { + shift3(); + token = STREQ; + break; } + shift2(); + token = EQEQ; break; - case InHexEscape: - if (isHexDigit(m_current) && isHexDigit(m_next1)) { - m_state = InString; - record16(convertHex(m_current, m_next1)); - shift(1); - } else if (m_current == stringType) { - record16('x'); - shift(1); - setDone(String); - } else { - record16('x'); - record16(m_current); - m_state = InString; + } + shift1(); + token = '='; + break; + case '!': + if (m_next1 == '=') { + if (m_next2 == '=') { + shift3(); + token = STRNEQ; + break; } + shift2(); + token = NE; break; - case InUnicodeEscape: - if (isHexDigit(m_current) && isHexDigit(m_next1) && isHexDigit(m_next2) && isHexDigit(m_next3)) { - record16(convertUnicode(m_current, m_next1, m_next2, m_next3)); - shift(3); - m_state = InString; - } else if (m_current == stringType) { - record16('u'); - shift(1); - setDone(String); - } else - setDone(Bad); + } + shift1(); + token = '!'; + break; + case '<': + if (m_next1 == '!' && m_next2 == '-' && m_next3 == '-') { + // <!-- marks the beginning of a line comment (for www usage) + shift4(); + goto inSingleLineComment; + } + if (m_next1 == '<') { + if (m_next2 == '=') { + shift3(); + token = LSHIFTEQUAL; + break; + } + shift2(); + token = LSHIFT; break; - case InSingleLineComment: - if (isLineTerminator()) { - nextLine(); - m_terminator = true; - if (m_restrKeyword) { - token = ';'; - setDone(Other); - } else - m_state = Start; - } else if (m_current == -1) - setDone(Eof); + } + if (m_next1 == '=') { + shift2(); + token = LE; break; - case InMultiLineComment: - if (m_current == -1) - setDone(Bad); - else if (isLineTerminator()) - nextLine(); - else if (m_current == '*' && m_next1 == '/') { - m_state = Start; - shift(1); + } + shift1(); + token = '<'; + break; + case '+': + if (m_next1 == '+') { + shift2(); + if (m_terminator) { + token = AUTOPLUSPLUS; + break; } + token = PLUSPLUS; break; - case InIdentifierOrKeyword: - case InIdentifier: - if (isIdentPart(m_current)) - record16(m_current); - else if (m_current == '\\') - m_state = InIdentifierPartUnicodeEscapeStart; - else - setDone(m_state == InIdentifierOrKeyword ? IdentifierOrKeyword : Identifier); + } + if (m_next1 == '=') { + shift2(); + token = PLUSEQUAL; break; - case InNum0: - if (m_current == 'x' || m_current == 'X') { - record8(m_current); - m_state = InHex; - } else if (m_current == '.') { - record8(m_current); - m_state = InDecimal; - } else if (m_current == 'e' || m_current == 'E') { - record8(m_current); - m_state = InExponentIndicator; - } else if (isOctalDigit(m_current)) { - record8(m_current); - m_state = InOctal; - } else if (isDecimalDigit(m_current)) { - record8(m_current); - m_state = InDecimal; - } else - setDone(Number); + } + shift1(); + token = '+'; + break; + case '-': + if (m_next1 == '-') { + if (m_atLineStart && m_next2 == '>') { + shift3(); + goto inSingleLineComment; + } + shift2(); + if (m_terminator) { + token = AUTOMINUSMINUS; + break; + } + token = MINUSMINUS; break; - case InHex: - if (isHexDigit(m_current)) - record8(m_current); - else - setDone(Hex); + } + if (m_next1 == '=') { + shift2(); + token = MINUSEQUAL; break; - case InOctal: - if (isOctalDigit(m_current)) - record8(m_current); - else if (isDecimalDigit(m_current)) { - record8(m_current); - m_state = InDecimal; - } else - setDone(Octal); + } + shift1(); + token = '-'; + break; + case '*': + if (m_next1 == '=') { + shift2(); + token = MULTEQUAL; break; - case InNum: - if (isDecimalDigit(m_current)) - record8(m_current); - else if (m_current == '.') { - record8(m_current); - m_state = InDecimal; - } else if (m_current == 'e' || m_current == 'E') { - record8(m_current); - m_state = InExponentIndicator; - } else - setDone(Number); + } + shift1(); + token = '*'; + break; + case '/': + if (m_next1 == '/') { + shift2(); + goto inSingleLineComment; + } + if (m_next1 == '*') + goto inMultiLineComment; + if (m_next1 == '=') { + shift2(); + token = DIVEQUAL; break; - case InDecimal: - if (isDecimalDigit(m_current)) - record8(m_current); - else if (m_current == 'e' || m_current == 'E') { - record8(m_current); - m_state = InExponentIndicator; - } else - setDone(Number); + } + shift1(); + token = '/'; + break; + case '&': + if (m_next1 == '&') { + shift2(); + token = AND; break; - case InExponentIndicator: - if (m_current == '+' || m_current == '-') - record8(m_current); - else if (isDecimalDigit(m_current)) { - record8(m_current); - m_state = InExponent; - } else - setDone(Bad); + } + if (m_next1 == '=') { + shift2(); + token = ANDEQUAL; break; - case InExponent: - if (isDecimalDigit(m_current)) - record8(m_current); - else - setDone(Number); + } + shift1(); + token = '&'; + break; + case '^': + if (m_next1 == '=') { + shift2(); + token = XOREQUAL; break; - case InIdentifierStartUnicodeEscapeStart: - if (m_current == 'u') - m_state = InIdentifierStartUnicodeEscape; - else - setDone(Bad); + } + shift1(); + token = '^'; + break; + case '%': + if (m_next1 == '=') { + shift2(); + token = MODEQUAL; break; - case InIdentifierPartUnicodeEscapeStart: - if (m_current == 'u') - m_state = InIdentifierPartUnicodeEscape; - else - setDone(Bad); + } + shift1(); + token = '%'; + break; + case '|': + if (m_next1 == '=') { + shift2(); + token = OREQUAL; break; - case InIdentifierStartUnicodeEscape: - if (!isHexDigit(m_current) || !isHexDigit(m_next1) || !isHexDigit(m_next2) || !isHexDigit(m_next3)) { - setDone(Bad); - break; - } - token = convertUnicode(m_current, m_next1, m_next2, m_next3); - shift(3); - if (!isIdentStart(token)) { - setDone(Bad); - break; - } - record16(token); - m_state = InIdentifier; + } + if (m_next1 == '|') { + shift2(); + token = OR; break; - case InIdentifierPartUnicodeEscape: - if (!isHexDigit(m_current) || !isHexDigit(m_next1) || !isHexDigit(m_next2) || !isHexDigit(m_next3)) { - setDone(Bad); - break; - } - token = convertUnicode(m_current, m_next1, m_next2, m_next3); - shift(3); - if (!isIdentPart(token)) { - setDone(Bad); - break; + } + shift1(); + token = '|'; + break; + case '.': + if (isASCIIDigit(m_next1)) { + record8('.'); + shift1(); + goto inNumberAfterDecimalPoint; + } + token = '.'; + shift1(); + break; + case ',': + case '~': + case '?': + case ':': + case '(': + case ')': + case '[': + case ']': + token = m_current; + shift1(); + break; + case ';': + shift1(); + m_delimited = true; + token = ';'; + break; + case '{': + lvalp->intValue = currentOffset(); + shift1(); + token = OPENBRACE; + break; + case '}': + lvalp->intValue = currentOffset(); + shift1(); + m_delimited = true; + token = CLOSEBRACE; + break; + case '\\': + goto startIdentifierWithBackslash; + case '0': + goto startNumberWithZeroDigit; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + goto startNumber; + case '"': + case '\'': + goto startString; + default: + if (isIdentStart(m_current)) + goto startIdentifierOrKeyword; + if (isLineTerminator(m_current)) { + shiftLineTerminator(); + m_atLineStart = true; + m_terminator = true; + if (lastTokenWasRestrKeyword()) { + token = ';'; + goto doneSemicolon; } - record16(token); - m_state = InIdentifier; - break; - default: - ASSERT(!"Unhandled state in switch statement"); - } - - // move on to the next character - if (!m_done) - shift(1); - if (m_state != Start && m_state != InSingleLineComment) - m_atLineStart = false; + goto start; + } + goto returnError; } - // no identifiers allowed directly after numeric literal, e.g. "3in" is bad - if ((m_state == Number || m_state == Octal || m_state == Hex) && isIdentStart(m_current)) - m_state = Bad; + m_atLineStart = false; + goto returnToken; - // terminate string - m_buffer8.append('\0'); - -#ifdef JSC_DEBUG_LEX - fprintf(stderr, "line: %d ", lineNo()); - fprintf(stderr, "yytext (%x): ", m_buffer8[0]); - fprintf(stderr, "%s ", m_buffer8.data()); -#endif +startString: { + int stringQuoteCharacter = m_current; + shift1(); - double dval = 0; - if (m_state == Number) - dval = WTF::strtod(m_buffer8.data(), 0L); - else if (m_state == Hex) { // scan hex numbers - const char* p = m_buffer8.data() + 2; - while (char c = *p++) { - dval *= 16; - dval += convertHex(c); + const UChar* stringStart = currentCharacter(); + while (m_current != stringQuoteCharacter) { + // Fast check for characters that require special handling. + // Catches -1, \n, \r, \, 0x2028, and 0x2029 as efficiently + // as possible, and lets through all common ASCII characters. + if (UNLIKELY(m_current == '\\') || UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) { + m_buffer16.append(stringStart, currentCharacter() - stringStart); + goto inString; + } + shift1(); + } + lvalp->ident = makeIdentifier(stringStart, currentCharacter() - stringStart); + shift1(); + m_atLineStart = false; + m_delimited = false; + token = STRING; + goto returnToken; + +inString: + while (m_current != stringQuoteCharacter) { + if (m_current == '\\') + goto inStringEscapeSequence; + if (UNLIKELY(isLineTerminator(m_current))) + goto returnError; + if (UNLIKELY(m_current == -1)) + goto returnError; + record16(m_current); + shift1(); + } + goto doneString; + +inStringEscapeSequence: + shift1(); + if (m_current == 'x') { + shift1(); + if (isASCIIHexDigit(m_current) && isASCIIHexDigit(m_next1)) { + record16(convertHex(m_current, m_next1)); + shift2(); + goto inString; } + record16('x'); + if (m_current == stringQuoteCharacter) + goto doneString; + goto inString; + } + if (m_current == 'u') { + shift1(); + if (isASCIIHexDigit(m_current) && isASCIIHexDigit(m_next1) && isASCIIHexDigit(m_next2) && isASCIIHexDigit(m_next3)) { + record16(convertUnicode(m_current, m_next1, m_next2, m_next3)); + shift4(); + goto inString; + } + if (m_current == stringQuoteCharacter) { + record16('u'); + goto doneString; + } + goto returnError; + } + if (isASCIIOctalDigit(m_current)) { + if (m_current >= '0' && m_current <= '3' && isASCIIOctalDigit(m_next1) && isASCIIOctalDigit(m_next2)) { + record16((m_current - '0') * 64 + (m_next1 - '0') * 8 + m_next2 - '0'); + shift3(); + goto inString; + } + if (isASCIIOctalDigit(m_next1)) { + record16((m_current - '0') * 8 + m_next1 - '0'); + shift2(); + goto inString; + } + record16(m_current - '0'); + shift1(); + goto inString; + } + if (isLineTerminator(m_current)) { + shiftLineTerminator(); + goto inString; + } + record16(singleEscape(m_current)); + shift1(); + goto inString; +} - if (dval >= mantissaOverflowLowerBound) - dval = parseIntOverflow(m_buffer8.data() + 2, p - (m_buffer8.data() + 3), 16); +startIdentifierWithBackslash: + shift1(); + if (UNLIKELY(m_current != 'u')) + goto returnError; + shift1(); + if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(m_next1) || !isASCIIHexDigit(m_next2) || !isASCIIHexDigit(m_next3))) + goto returnError; + token = convertUnicode(m_current, m_next1, m_next2, m_next3); + if (UNLIKELY(!isIdentStart(token))) + goto returnError; + goto inIdentifierAfterCharacterCheck; + +startIdentifierOrKeyword: { + const UChar* identifierStart = currentCharacter(); + shift1(); + while (isIdentPart(m_current)) + shift1(); + if (LIKELY(m_current != '\\')) { + lvalp->ident = makeIdentifier(identifierStart, currentCharacter() - identifierStart); + goto doneIdentifierOrKeyword; + } + m_buffer16.append(identifierStart, currentCharacter() - identifierStart); +} - m_state = Number; - } else if (m_state == Octal) { // scan octal number - const char* p = m_buffer8.data() + 1; - while (char c = *p++) { - dval *= 8; - dval += c - '0'; + do { + shift1(); + if (UNLIKELY(m_current != 'u')) + goto returnError; + shift1(); + if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(m_next1) || !isASCIIHexDigit(m_next2) || !isASCIIHexDigit(m_next3))) + goto returnError; + token = convertUnicode(m_current, m_next1, m_next2, m_next3); + if (UNLIKELY(!isIdentPart(token))) + goto returnError; +inIdentifierAfterCharacterCheck: + record16(token); + shift4(); + + while (isIdentPart(m_current)) { + record16(m_current); + shift1(); } + } while (UNLIKELY(m_current == '\\')); + goto doneIdentifier; - if (dval >= mantissaOverflowLowerBound) - dval = parseIntOverflow(m_buffer8.data() + 1, p - (m_buffer8.data() + 2), 8); - - m_state = Number; +inSingleLineComment: + while (!isLineTerminator(m_current)) { + if (UNLIKELY(m_current == -1)) + return 0; + shift1(); } - -#ifdef JSC_DEBUG_LEX - switch (m_state) { - case Eof: - printf("(EOF)\n"); - break; - case Other: - printf("(Other)\n"); - break; - case Identifier: - printf("(Identifier)/(Keyword)\n"); - break; - case String: - printf("(String)\n"); - break; - case Number: - printf("(Number)\n"); - break; - default: - printf("(unknown)"); + shiftLineTerminator(); + m_atLineStart = true; + m_terminator = true; + if (lastTokenWasRestrKeyword()) + goto doneSemicolon; + goto start; + +inMultiLineComment: + shift2(); + while (m_current != '*' || m_next1 != '/') { + if (isLineTerminator(m_current)) + shiftLineTerminator(); + else { + shift1(); + if (UNLIKELY(m_current == -1)) + goto returnError; + } } -#endif + shift2(); + m_atLineStart = false; + goto start; + +startNumberWithZeroDigit: + shift1(); + if ((m_current | 0x20) == 'x' && isASCIIHexDigit(m_next1)) { + shift1(); + goto inHex; + } + if (m_current == '.') { + record8('0'); + record8('.'); + shift1(); + goto inNumberAfterDecimalPoint; + } + if ((m_current | 0x20) == 'e') { + record8('0'); + record8('e'); + shift1(); + goto inExponentIndicator; + } + if (isASCIIOctalDigit(m_current)) + goto inOctal; + if (isASCIIDigit(m_current)) + goto startNumber; + lvalp->doubleValue = 0; + goto doneNumeric; + +inNumberAfterDecimalPoint: + while (isASCIIDigit(m_current)) { + record8(m_current); + shift1(); + } + if ((m_current | 0x20) == 'e') { + record8('e'); + shift1(); + goto inExponentIndicator; + } + goto doneNumber; + +inExponentIndicator: + if (m_current == '+' || m_current == '-') { + record8(m_current); + shift1(); + } + if (!isASCIIDigit(m_current)) + goto returnError; + do { + record8(m_current); + shift1(); + } while (isASCIIDigit(m_current)); + goto doneNumber; + +inOctal: { + do { + record8(m_current); + shift1(); + } while (isASCIIOctalDigit(m_current)); + if (isASCIIDigit(m_current)) + goto startNumber; - if (m_state != Identifier) - m_eatNextIdentifier = false; + double dval = 0; - m_restrKeyword = false; - m_delimited = false; - llocp->first_line = yylineno; - llocp->last_line = yylineno; - llocp->first_column = startOffset; - llocp->last_column = m_currentOffset; - switch (m_state) { - case Eof: - token = 0; - break; - case Other: - if (token == '}' || token == ';') - m_delimited = true; - break; - case Identifier: - // Apply anonymous-function hack below (eat the identifier). - if (m_eatNextIdentifier) { - m_eatNextIdentifier = false; - token = lex(lvalp, llocp); - break; - } - lvalp->ident = makeIdentifier(m_buffer16); - token = IDENT; - break; - case IdentifierOrKeyword: { - lvalp->ident = makeIdentifier(m_buffer16); - const HashEntry* entry = m_mainTable.entry(m_globalData, *lvalp->ident); - if (!entry) { - // Lookup for keyword failed, means this is an identifier. - token = IDENT; - break; - } - token = entry->lexerValue(); - // Hack for "f = function somename() { ... }"; too hard to get into the grammar. - m_eatNextIdentifier = token == FUNCTION && m_lastToken == '='; - if (token == CONTINUE || token == BREAK || token == RETURN || token == THROW) - m_restrKeyword = true; - break; - } - case String: - // Atomize constant strings in case they're later used in property lookup. - lvalp->ident = makeIdentifier(m_buffer16); - token = STRING; - break; - case Number: - lvalp->doubleValue = dval; - token = NUMBER; - break; - case Bad: -#ifdef JSC_DEBUG_LEX - fprintf(stderr, "yylex: ERROR.\n"); -#endif - m_error = true; - return -1; - default: - ASSERT(!"unhandled numeration value in switch"); - m_error = true; - return -1; + const char* end = m_buffer8.end(); + for (const char* p = m_buffer8.data(); p < end; ++p) { + dval *= 8; + dval += *p - '0'; } - m_lastToken = token; - return token; -} + if (dval >= mantissaOverflowLowerBound) + dval = parseIntOverflow(m_buffer8.data(), end - m_buffer8.data(), 8); -bool Lexer::isWhiteSpace() const -{ - return isWhiteSpace(m_current); -} + m_buffer8.resize(0); -bool Lexer::isLineTerminator() -{ - bool cr = (m_current == '\r'); - bool lf = (m_current == '\n'); - if (cr) - m_skipLF = true; - else if (lf) - m_skipCR = true; - return cr || lf || m_current == 0x2028 || m_current == 0x2029; + lvalp->doubleValue = dval; + goto doneNumeric; } -bool Lexer::isIdentStart(int c) -{ - return isASCIIAlpha(c) || c == '$' || c == '_' || (!isASCII(c) && (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other))); -} +inHex: { + do { + record8(m_current); + shift1(); + } while (isASCIIHexDigit(m_current)); -bool Lexer::isIdentPart(int c) -{ - return isASCIIAlphanumeric(c) || c == '$' || c == '_' || (!isASCII(c) && (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other - | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector))); -} + double dval = 0; -static bool isDecimalDigit(int c) -{ - return isASCIIDigit(c); -} + const char* end = m_buffer8.end(); + for (const char* p = m_buffer8.data(); p < end; ++p) { + dval *= 16; + dval += toASCIIHexValue(*p); + } + if (dval >= mantissaOverflowLowerBound) + dval = parseIntOverflow(m_buffer8.data(), end - m_buffer8.data(), 16); -bool Lexer::isHexDigit(int c) -{ - return isASCIIHexDigit(c); -} + m_buffer8.resize(0); -bool Lexer::isOctalDigit(int c) -{ - return isASCIIOctalDigit(c); + lvalp->doubleValue = dval; + goto doneNumeric; } -int Lexer::matchPunctuator(int& charPos, int c1, int c2, int c3, int c4) -{ - if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') { - shift(4); - return URSHIFTEQUAL; - } - if (c1 == '=' && c2 == '=' && c3 == '=') { - shift(3); - return STREQ; - } - if (c1 == '!' && c2 == '=' && c3 == '=') { - shift(3); - return STRNEQ; - } - if (c1 == '>' && c2 == '>' && c3 == '>') { - shift(3); - return URSHIFT; - } - if (c1 == '<' && c2 == '<' && c3 == '=') { - shift(3); - return LSHIFTEQUAL; - } - if (c1 == '>' && c2 == '>' && c3 == '=') { - shift(3); - return RSHIFTEQUAL; - } - if (c1 == '<' && c2 == '=') { - shift(2); - return LE; - } - if (c1 == '>' && c2 == '=') { - shift(2); - return GE; - } - if (c1 == '!' && c2 == '=') { - shift(2); - return NE; - } - if (c1 == '+' && c2 == '+') { - shift(2); - if (m_terminator) - return AUTOPLUSPLUS; - return PLUSPLUS; - } - if (c1 == '-' && c2 == '-') { - shift(2); - if (m_terminator) - return AUTOMINUSMINUS; - return MINUSMINUS; - } - if (c1 == '=' && c2 == '=') { - shift(2); - return EQEQ; - } - if (c1 == '+' && c2 == '=') { - shift(2); - return PLUSEQUAL; - } - if (c1 == '-' && c2 == '=') { - shift(2); - return MINUSEQUAL; - } - if (c1 == '*' && c2 == '=') { - shift(2); - return MULTEQUAL; - } - if (c1 == '/' && c2 == '=') { - shift(2); - return DIVEQUAL; - } - if (c1 == '&' && c2 == '=') { - shift(2); - return ANDEQUAL; - } - if (c1 == '^' && c2 == '=') { - shift(2); - return XOREQUAL; - } - if (c1 == '%' && c2 == '=') { - shift(2); - return MODEQUAL; - } - if (c1 == '|' && c2 == '=') { - shift(2); - return OREQUAL; - } - if (c1 == '<' && c2 == '<') { - shift(2); - return LSHIFT; - } - if (c1 == '>' && c2 == '>') { - shift(2); - return RSHIFT; +startNumber: + record8(m_current); + shift1(); + while (isASCIIDigit(m_current)) { + record8(m_current); + shift1(); } - if (c1 == '&' && c2 == '&') { - shift(2); - return AND; + if (m_current == '.') { + record8('.'); + shift1(); + goto inNumberAfterDecimalPoint; } - if (c1 == '|' && c2 == '|') { - shift(2); - return OR; + if ((m_current | 0x20) == 'e') { + record8('e'); + shift1(); + goto inExponentIndicator; } - switch (c1) { - case '=': - case '>': - case '<': - case ',': - case '!': - case '~': - case '?': - case ':': - case '.': - case '+': - case '-': - case '*': - case '/': - case '&': - case '|': - case '^': - case '%': - case '(': - case ')': - case '[': - case ']': - case ';': - shift(1); - return static_cast<int>(c1); - case '{': - charPos = m_currentOffset; - shift(1); - return OPENBRACE; - case '}': - charPos = m_currentOffset; - shift(1); - return CLOSEBRACE; - default: - return -1; - } -} + // Fall through into doneNumber. -unsigned short Lexer::singleEscape(unsigned short c) -{ - switch (c) { - case 'b': - return 0x08; - case 't': - return 0x09; - case 'n': - return 0x0A; - case 'v': - return 0x0B; - case 'f': - return 0x0C; - case 'r': - return 0x0D; - case '"': - return 0x22; - case '\'': - return 0x27; - case '\\': - return 0x5C; - default: - return c; - } -} +doneNumber: + // Null-terminate string for strtod. + m_buffer8.append('\0'); + lvalp->doubleValue = WTF::strtod(m_buffer8.data(), 0); + m_buffer8.resize(0); -unsigned short Lexer::convertOctal(int c1, int c2, int c3) -{ - return static_cast<unsigned short>((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0'); -} + // Fall through into doneNumeric. -unsigned char Lexer::convertHex(int c) -{ - if (c >= '0' && c <= '9') - return static_cast<unsigned char>(c - '0'); - if (c >= 'a' && c <= 'f') - return static_cast<unsigned char>(c - 'a' + 10); - return static_cast<unsigned char>(c - 'A' + 10); -} +doneNumeric: + // No identifiers allowed directly after numeric literal, e.g. "3in" is bad. + if (UNLIKELY(isIdentStart(m_current))) + goto returnError; -unsigned char Lexer::convertHex(int c1, int c2) -{ - return ((convertHex(c1) << 4) + convertHex(c2)); -} + m_atLineStart = false; + m_delimited = false; + token = NUMBER; + goto returnToken; -UChar Lexer::convertUnicode(int c1, int c2, int c3, int c4) -{ - unsigned char highByte = (convertHex(c1) << 4) + convertHex(c2); - unsigned char lowByte = (convertHex(c3) << 4) + convertHex(c4); - return (highByte << 8 | lowByte); -} +doneSemicolon: + token = ';'; + m_delimited = true; + goto returnToken; -void Lexer::record8(int c) -{ - ASSERT(c >= 0); - ASSERT(c <= 0xff); - m_buffer8.append(static_cast<char>(c)); +doneIdentifier: + m_atLineStart = false; + m_delimited = false; + lvalp->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size()); + m_buffer16.resize(0); + token = IDENT; + goto returnToken; + +doneIdentifierOrKeyword: { + m_atLineStart = false; + m_delimited = false; + m_buffer16.resize(0); + const HashEntry* entry = m_keywordTable.entry(m_globalData, *lvalp->ident); + token = entry ? entry->lexerValue() : IDENT; + goto returnToken; } -void Lexer::record16(int c) -{ - ASSERT(c >= 0); - ASSERT(c <= USHRT_MAX); - record16(UChar(static_cast<unsigned short>(c))); +doneString: + // Atomize constant strings in case they're later used in property lookup. + shift1(); + m_atLineStart = false; + m_delimited = false; + lvalp->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size()); + m_buffer16.resize(0); + token = STRING; + + // Fall through into returnToken. + +returnToken: { + int lineNumber = m_lineNumber; + llocp->first_line = lineNumber; + llocp->last_line = lineNumber; + llocp->first_column = startOffset; + llocp->last_column = currentOffset(); + + m_lastToken = token; + return token; } -void Lexer::record16(UChar c) -{ - m_buffer16.append(c); +returnError: + m_error = true; + return -1; } bool Lexer::scanRegExp() { - m_buffer16.clear(); + ASSERT(m_buffer16.isEmpty()); + bool lastWasEscape = false; bool inBrackets = false; - while (1) { - if (isLineTerminator() || m_current == -1) + while (true) { + if (isLineTerminator(m_current) || m_current == -1) return false; - else if (m_current != '/' || lastWasEscape == true || inBrackets == true) { + if (m_current != '/' || lastWasEscape || inBrackets) { // keep track of '[' and ']' if (!lastWasEscape) { - if ( m_current == '[' && !inBrackets ) + if (m_current == '[' && !inBrackets) inBrackets = true; - if ( m_current == ']' && inBrackets ) + if (m_current == ']' && inBrackets) inBrackets = false; } record16(m_current); - lastWasEscape = - !lastWasEscape && (m_current == '\\'); + lastWasEscape = !lastWasEscape && m_current == '\\'; } else { // end of regexp m_pattern = UString(m_buffer16); - m_buffer16.clear(); - shift(1); + m_buffer16.resize(0); + shift1(); break; } - shift(1); + shift1(); } while (isIdentPart(m_current)) { record16(m_current); - shift(1); + shift1(); } m_flags = UString(m_buffer16); + m_buffer16.resize(0); return true; } @@ -881,6 +950,7 @@ bool Lexer::scanRegExp() void Lexer::clear() { m_identifiers.clear(); + m_codeWithoutBOMs.clear(); Vector<char> newBuffer8; newBuffer8.reserveInitialCapacity(initialReadBufferCapacity); @@ -892,8 +962,30 @@ void Lexer::clear() m_isReparsing = false; - m_pattern = 0; - m_flags = 0; + m_pattern = UString(); + m_flags = UString(); +} + +SourceCode Lexer::sourceCode(int openBrace, int closeBrace, int firstLine) +{ + if (m_codeWithoutBOMs.isEmpty()) + return SourceCode(m_source->provider(), openBrace, closeBrace + 1, firstLine); + + const UChar* data = m_source->provider()->data(); + + ASSERT(openBrace < closeBrace); + + int numBOMsBeforeOpenBrace = 0; + int numBOMsBetweenBraces = 0; + + int i; + for (i = m_source->startOffset(); i < openBrace; ++i) + numBOMsBeforeOpenBrace += data[i] == byteOrderMark; + for (; i < closeBrace; ++i) + numBOMsBetweenBraces += data[i] == byteOrderMark; + + return SourceCode(m_source->provider(), openBrace + numBOMsBeforeOpenBrace, + closeBrace + numBOMsBeforeOpenBrace + numBOMsBetweenBraces + 1, firstLine); } } // namespace JSC diff --git a/JavaScriptCore/parser/Lexer.h b/JavaScriptCore/parser/Lexer.h index 63c2da9..9c22a9c 100644 --- a/JavaScriptCore/parser/Lexer.h +++ b/JavaScriptCore/parser/Lexer.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,10 +22,10 @@ #ifndef Lexer_h #define Lexer_h -#include "Identifier.h" #include "Lookup.h" #include "SegmentedVector.h" #include "SourceCode.h" +#include <wtf/ASCIICType.h> #include <wtf/Vector.h> #include <wtf/unicode/Unicode.h> @@ -35,125 +35,71 @@ namespace JSC { class Lexer : Noncopyable { public: + // Character manipulation functions. + static bool isWhiteSpace(int character); + static bool isLineTerminator(int character); + static unsigned char convertHex(int c1, int c2); + static UChar convertUnicode(int c1, int c2, int c3, int c4); + + // Functions to set up parsing. void setCode(const SourceCode&); void setIsReparsing() { m_isReparsing = true; } - int lex(void* lvalp, void* llocp); - - int lineNo() const { return yylineno; } + // Functions for the parser itself. + int lex(void* lvalp, void* llocp); + int lineNumber() const { return m_lineNumber; } bool prevTerminator() const { return m_terminator; } - - enum State { - Start, - IdentifierOrKeyword, - Identifier, - InIdentifierOrKeyword, - InIdentifier, - InIdentifierStartUnicodeEscapeStart, - InIdentifierStartUnicodeEscape, - InIdentifierPartUnicodeEscapeStart, - InIdentifierPartUnicodeEscape, - InSingleLineComment, - InMultiLineComment, - InNum, - InNum0, - InHex, - InOctal, - InDecimal, - InExponentIndicator, - InExponent, - Hex, - Octal, - Number, - String, - Eof, - InString, - InEscapeSequence, - InHexEscape, - InUnicodeEscape, - Other, - Bad - }; - + SourceCode sourceCode(int openBrace, int closeBrace, int firstLine); bool scanRegExp(); const UString& pattern() const { return m_pattern; } const UString& flags() const { return m_flags; } - static unsigned char convertHex(int); - static unsigned char convertHex(int c1, int c2); - static UChar convertUnicode(int c1, int c2, int c3, int c4); - static bool isIdentStart(int); - static bool isIdentPart(int); - static bool isHexDigit(int); - + // Functions for use after parsing. bool sawError() const { return m_error; } - void clear(); - SourceCode sourceCode(int openBrace, int closeBrace, int firstLine) { return SourceCode(m_source->provider(), openBrace, closeBrace + 1, firstLine); } - - static inline bool isWhiteSpace(int ch) - { - return ch == '\t' || ch == 0x0b || ch == 0x0c || WTF::Unicode::isSeparatorSpace(ch); - } - - static inline bool isLineTerminator(int ch) - { - return ch == '\r' || ch == '\n' || ch == 0x2028 || ch == 0x2029; - } private: friend class JSGlobalData; + Lexer(JSGlobalData*); ~Lexer(); - void setDone(State); - void shift(unsigned int p); - void nextLine(); - int lookupKeyword(const char *); - - bool isWhiteSpace() const; - bool isLineTerminator(); - static bool isOctalDigit(int); - - ALWAYS_INLINE int matchPunctuator(int& charPos, int c1, int c2, int c3, int c4); - static unsigned short singleEscape(unsigned short); - static unsigned short convertOctal(int c1, int c2, int c3); + void shift1(); + void shift2(); + void shift3(); + void shift4(); + void shiftLineTerminator(); void record8(int); void record16(int); void record16(UChar); - JSC::Identifier* makeIdentifier(const Vector<UChar>& buffer) - { - m_identifiers.append(JSC::Identifier(m_globalData, buffer.data(), buffer.size())); - return &m_identifiers.last(); - } + void copyCodeWithoutBOMs(); + + int currentOffset() const; + const UChar* currentCharacter() const; + + JSC::Identifier* makeIdentifier(const UChar* buffer, size_t length); + + bool lastTokenWasRestrKeyword() const; static const size_t initialReadBufferCapacity = 32; static const size_t initialIdentifierTableCapacity = 64; - int yylineno; - int yycolumn; + int m_lineNumber; - bool m_done; Vector<char> m_buffer8; Vector<UChar> m_buffer16; bool m_terminator; - bool m_restrKeyword; bool m_delimited; // encountered delimiter like "'" and "}" on last run - bool m_skipLF; - bool m_skipCR; - bool m_eatNextIdentifier; - int m_stackToken; int m_lastToken; - State m_state; - unsigned int m_position; const SourceCode* m_source; const UChar* m_code; - unsigned int m_length; + const UChar* m_codeStart; + const UChar* m_codeEnd; bool m_isReparsing; - int m_atLineStart; + bool m_atLineStart; bool m_error; // current and following unicode characters (int to allow for -1 for end-of-file marker) @@ -162,11 +108,6 @@ namespace JSC { int m_next2; int m_next3; - int m_currentOffset; - int m_nextOffset1; - int m_nextOffset2; - int m_nextOffset3; - SegmentedVector<JSC::Identifier, initialIdentifierTableCapacity> m_identifiers; JSGlobalData* m_globalData; @@ -174,9 +115,31 @@ namespace JSC { UString m_pattern; UString m_flags; - const HashTable m_mainTable; + const HashTable m_keywordTable; + + Vector<UChar> m_codeWithoutBOMs; }; + inline bool Lexer::isWhiteSpace(int ch) + { + return isASCII(ch) ? (ch == ' ' || ch == '\t' || ch == 0xB || ch == 0xC) : WTF::Unicode::isSeparatorSpace(ch); + } + + inline bool Lexer::isLineTerminator(int ch) + { + return ch == '\r' || ch == '\n' || (ch & ~1) == 0x2028; + } + + inline unsigned char Lexer::convertHex(int c1, int c2) + { + return (toASCIIHexValue(c1) << 4) | toASCIIHexValue(c2); + } + + inline UChar Lexer::convertUnicode(int c1, int c2, int c3, int c4) + { + return (convertHex(c1, c2) << 8) | convertHex(c3, c4); + } + } // namespace JSC #endif // Lexer_h diff --git a/JavaScriptCore/parser/NodeConstructors.h b/JavaScriptCore/parser/NodeConstructors.h new file mode 100644 index 0000000..ea1579b --- /dev/null +++ b/JavaScriptCore/parser/NodeConstructors.h @@ -0,0 +1,911 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef NodeConstructors_h +#define NodeConstructors_h + +#include "Nodes.h" +#include "Lexer.h" +#include "Parser.h" + +namespace JSC { + + inline void* ParserArenaDeletable::operator new(size_t size, JSGlobalData* globalData) + { + ParserArenaDeletable* deletable = static_cast<ParserArenaDeletable*>(fastMalloc(size)); + globalData->parser->arena().deleteWithArena(deletable); + return deletable; + } + + inline void* ParserArenaDeletable::operator new(size_t size) + { + return fastMalloc(size); + } + + inline ParserArenaRefCounted::ParserArenaRefCounted(JSGlobalData* globalData) + { + globalData->parser->arena().derefWithArena(adoptRef(this)); + } + + inline Node::Node(JSGlobalData* globalData) + : m_line(globalData->lexer->lineNumber()) + { + } + + inline ExpressionNode::ExpressionNode(JSGlobalData* globalData, ResultType resultType) + : Node(globalData) + , m_resultType(resultType) + { + } + + inline StatementNode::StatementNode(JSGlobalData* globalData) + : Node(globalData) + , m_lastLine(-1) + { + } + + inline NullNode::NullNode(JSGlobalData* globalData) + : ExpressionNode(globalData, ResultType::nullType()) + { + } + + inline BooleanNode::BooleanNode(JSGlobalData* globalData, bool value) + : ExpressionNode(globalData, ResultType::booleanType()) + , m_value(value) + { + } + + inline NumberNode::NumberNode(JSGlobalData* globalData, double v) + : ExpressionNode(globalData, ResultType::numberType()) + , m_double(v) + { + } + + inline StringNode::StringNode(JSGlobalData* globalData, const Identifier& v) + : ExpressionNode(globalData, ResultType::stringType()) + , m_value(v) + { + } + + inline RegExpNode::RegExpNode(JSGlobalData* globalData, const UString& pattern, const UString& flags) + : ExpressionNode(globalData) + , m_pattern(pattern) + , m_flags(flags) + { + } + + inline ThisNode::ThisNode(JSGlobalData* globalData) + : ExpressionNode(globalData) + { + } + + inline ResolveNode::ResolveNode(JSGlobalData* globalData, const Identifier& ident, int startOffset) + : ExpressionNode(globalData) + , m_ident(ident) + , m_startOffset(startOffset) + { + } + + inline ElementNode::ElementNode(JSGlobalData*, int elision, ExpressionNode* node) + : m_next(0) + , m_elision(elision) + , m_node(node) + { + } + + inline ElementNode::ElementNode(JSGlobalData*, ElementNode* l, int elision, ExpressionNode* node) + : m_next(0) + , m_elision(elision) + , m_node(node) + { + l->m_next = this; + } + + inline ArrayNode::ArrayNode(JSGlobalData* globalData, int elision) + : ExpressionNode(globalData) + , m_element(0) + , m_elision(elision) + , m_optional(true) + { + } + + inline ArrayNode::ArrayNode(JSGlobalData* globalData, ElementNode* element) + : ExpressionNode(globalData) + , m_element(element) + , m_elision(0) + , m_optional(false) + { + } + + inline ArrayNode::ArrayNode(JSGlobalData* globalData, int elision, ElementNode* element) + : ExpressionNode(globalData) + , m_element(element) + , m_elision(elision) + , m_optional(true) + { + } + + inline PropertyNode::PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* assign, Type type) + : m_name(name) + , m_assign(assign) + , m_type(type) + { + } + + inline PropertyListNode::PropertyListNode(JSGlobalData* globalData, PropertyNode* node) + : Node(globalData) + , m_node(node) + , m_next(0) + { + } + + inline PropertyListNode::PropertyListNode(JSGlobalData* globalData, PropertyNode* node, PropertyListNode* list) + : Node(globalData) + , m_node(node) + , m_next(0) + { + list->m_next = this; + } + + inline ObjectLiteralNode::ObjectLiteralNode(JSGlobalData* globalData) + : ExpressionNode(globalData) + , m_list(0) + { + } + + inline ObjectLiteralNode::ObjectLiteralNode(JSGlobalData* globalData, PropertyListNode* list) + : ExpressionNode(globalData) + , m_list(list) + { + } + + inline BracketAccessorNode::BracketAccessorNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments) + : ExpressionNode(globalData) + , m_base(base) + , m_subscript(subscript) + , m_subscriptHasAssignments(subscriptHasAssignments) + { + } + + inline DotAccessorNode::DotAccessorNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident) + : ExpressionNode(globalData) + , m_base(base) + , m_ident(ident) + { + } + + inline ArgumentListNode::ArgumentListNode(JSGlobalData* globalData, ExpressionNode* expr) + : Node(globalData) + , m_next(0) + , m_expr(expr) + { + } + + inline ArgumentListNode::ArgumentListNode(JSGlobalData* globalData, ArgumentListNode* listNode, ExpressionNode* expr) + : Node(globalData) + , m_next(0) + , m_expr(expr) + { + listNode->m_next = this; + } + + inline ArgumentsNode::ArgumentsNode(JSGlobalData*) + : m_listNode(0) + { + } + + inline ArgumentsNode::ArgumentsNode(JSGlobalData*, ArgumentListNode* listNode) + : m_listNode(listNode) + { + } + + inline NewExprNode::NewExprNode(JSGlobalData* globalData, ExpressionNode* expr) + : ExpressionNode(globalData) + , m_expr(expr) + , m_args(0) + { + } + + inline NewExprNode::NewExprNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args) + : ExpressionNode(globalData) + , m_expr(expr) + , m_args(args) + { + } + + inline EvalFunctionCallNode::EvalFunctionCallNode(JSGlobalData* globalData, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableExpressionData(divot, startOffset, endOffset) + , m_args(args) + { + } + + inline FunctionCallValueNode::FunctionCallValueNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableExpressionData(divot, startOffset, endOffset) + , m_expr(expr) + , m_args(args) + { + } + + inline FunctionCallResolveNode::FunctionCallResolveNode(JSGlobalData* globalData, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableExpressionData(divot, startOffset, endOffset) + , m_ident(ident) + , m_args(args) + { + } + + inline FunctionCallBracketNode::FunctionCallBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableSubExpressionData(divot, startOffset, endOffset) + , m_base(base) + , m_subscript(subscript) + , m_args(args) + { + } + + inline FunctionCallDotNode::FunctionCallDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableSubExpressionData(divot, startOffset, endOffset) + , m_base(base) + , m_ident(ident) + , m_args(args) + { + } + + inline CallFunctionCallDotNode::CallFunctionCallDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + : FunctionCallDotNode(globalData, base, ident, args, divot, startOffset, endOffset) + { + } + + inline ApplyFunctionCallDotNode::ApplyFunctionCallDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + : FunctionCallDotNode(globalData, base, ident, args, divot, startOffset, endOffset) + { + } + + inline PrePostResolveNode::PrePostResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData, ResultType::numberType()) // could be reusable for pre? + , ThrowableExpressionData(divot, startOffset, endOffset) + , m_ident(ident) + { + } + + inline PostfixResolveNode::PostfixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset) + , m_operator(oper) + { + } + + inline PostfixBracketNode::PostfixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableSubExpressionData(divot, startOffset, endOffset) + , m_base(base) + , m_subscript(subscript) + , m_operator(oper) + { + } + + inline PostfixDotNode::PostfixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableSubExpressionData(divot, startOffset, endOffset) + , m_base(base) + , m_ident(ident) + , m_operator(oper) + { + } + + inline PostfixErrorNode::PostfixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableSubExpressionData(divot, startOffset, endOffset) + , m_expr(expr) + , m_operator(oper) + { + } + + inline DeleteResolveNode::DeleteResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableExpressionData(divot, startOffset, endOffset) + , m_ident(ident) + { + } + + inline DeleteBracketNode::DeleteBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableExpressionData(divot, startOffset, endOffset) + , m_base(base) + , m_subscript(subscript) + { + } + + inline DeleteDotNode::DeleteDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableExpressionData(divot, startOffset, endOffset) + , m_base(base) + , m_ident(ident) + { + } + + inline DeleteValueNode::DeleteValueNode(JSGlobalData* globalData, ExpressionNode* expr) + : ExpressionNode(globalData) + , m_expr(expr) + { + } + + inline VoidNode::VoidNode(JSGlobalData* globalData, ExpressionNode* expr) + : ExpressionNode(globalData) + , m_expr(expr) + { + } + + inline TypeOfResolveNode::TypeOfResolveNode(JSGlobalData* globalData, const Identifier& ident) + : ExpressionNode(globalData, ResultType::stringType()) + , m_ident(ident) + { + } + + inline TypeOfValueNode::TypeOfValueNode(JSGlobalData* globalData, ExpressionNode* expr) + : ExpressionNode(globalData, ResultType::stringType()) + , m_expr(expr) + { + } + + inline PrefixResolveNode::PrefixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset) + , m_operator(oper) + { + } + + inline PrefixBracketNode::PrefixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset) + , m_base(base) + , m_subscript(subscript) + , m_operator(oper) + { + } + + inline PrefixDotNode::PrefixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset) + , m_base(base) + , m_ident(ident) + , m_operator(oper) + { + } + + inline PrefixErrorNode::PrefixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableExpressionData(divot, startOffset, endOffset) + , m_expr(expr) + , m_operator(oper) + { + } + + inline UnaryOpNode::UnaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr, OpcodeID opcodeID) + : ExpressionNode(globalData, type) + , m_expr(expr) + , m_opcodeID(opcodeID) + { + } + + inline UnaryPlusNode::UnaryPlusNode(JSGlobalData* globalData, ExpressionNode* expr) + : UnaryOpNode(globalData, ResultType::numberType(), expr, op_to_jsnumber) + { + } + + inline NegateNode::NegateNode(JSGlobalData* globalData, ExpressionNode* expr) + : UnaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr, op_negate) + { + } + + inline BitwiseNotNode::BitwiseNotNode(JSGlobalData* globalData, ExpressionNode* expr) + : UnaryOpNode(globalData, ResultType::forBitOp(), expr, op_bitnot) + { + } + + inline LogicalNotNode::LogicalNotNode(JSGlobalData* globalData, ExpressionNode* expr) + : UnaryOpNode(globalData, ResultType::booleanType(), expr, op_not) + { + } + + inline BinaryOpNode::BinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments) + : ExpressionNode(globalData) + , m_expr1(expr1) + , m_expr2(expr2) + , m_opcodeID(opcodeID) + , m_rightHasAssignments(rightHasAssignments) + { + } + + inline BinaryOpNode::BinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments) + : ExpressionNode(globalData, type) + , m_expr1(expr1) + , m_expr2(expr2) + , m_opcodeID(opcodeID) + , m_rightHasAssignments(rightHasAssignments) + { + } + + inline ReverseBinaryOpNode::ReverseBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments) + : BinaryOpNode(globalData, expr1, expr2, opcodeID, rightHasAssignments) + { + } + + inline ReverseBinaryOpNode::ReverseBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments) + : BinaryOpNode(globalData, type, expr1, expr2, opcodeID, rightHasAssignments) + { + } + + inline MultNode::MultNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, op_mul, rightHasAssignments) + { + } + + inline DivNode::DivNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, op_div, rightHasAssignments) + { + } + + + inline ModNode::ModNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, op_mod, rightHasAssignments) + { + } + + inline AddNode::AddNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::forAdd(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, op_add, rightHasAssignments) + { + } + + inline SubNode::SubNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, op_sub, rightHasAssignments) + { + } + + inline LeftShiftNode::LeftShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, op_lshift, rightHasAssignments) + { + } + + inline RightShiftNode::RightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, op_rshift, rightHasAssignments) + { + } + + inline UnsignedRightShiftNode::UnsignedRightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, op_urshift, rightHasAssignments) + { + } + + inline LessNode::LessNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_less, rightHasAssignments) + { + } + + inline GreaterNode::GreaterNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_less, rightHasAssignments) + { + } + + inline LessEqNode::LessEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_lesseq, rightHasAssignments) + { + } + + inline GreaterEqNode::GreaterEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_lesseq, rightHasAssignments) + { + } + + inline ThrowableBinaryOpNode::ThrowableBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments) + : BinaryOpNode(globalData, type, expr1, expr2, opcodeID, rightHasAssignments) + { + } + + inline ThrowableBinaryOpNode::ThrowableBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID opcodeID, bool rightHasAssignments) + : BinaryOpNode(globalData, expr1, expr2, opcodeID, rightHasAssignments) + { + } + + inline InstanceOfNode::InstanceOfNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : ThrowableBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_instanceof, rightHasAssignments) + { + } + + inline InNode::InNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : ThrowableBinaryOpNode(globalData, expr1, expr2, op_in, rightHasAssignments) + { + } + + inline EqualNode::EqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_eq, rightHasAssignments) + { + } + + inline NotEqualNode::NotEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_neq, rightHasAssignments) + { + } + + inline StrictEqualNode::StrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_stricteq, rightHasAssignments) + { + } + + inline NotStrictEqualNode::NotStrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, op_nstricteq, rightHasAssignments) + { + } + + inline BitAndNode::BitAndNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, op_bitand, rightHasAssignments) + { + } + + inline BitOrNode::BitOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, op_bitor, rightHasAssignments) + { + } + + inline BitXOrNode::BitXOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) + : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, op_bitxor, rightHasAssignments) + { + } + + inline LogicalOpNode::LogicalOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator oper) + : ExpressionNode(globalData, ResultType::booleanType()) + , m_expr1(expr1) + , m_expr2(expr2) + , m_operator(oper) + { + } + + inline ConditionalNode::ConditionalNode(JSGlobalData* globalData, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2) + : ExpressionNode(globalData) + , m_logical(logical) + , m_expr1(expr1) + , m_expr2(expr2) + { + } + + inline ReadModifyResolveNode::ReadModifyResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableExpressionData(divot, startOffset, endOffset) + , m_ident(ident) + , m_right(right) + , m_operator(oper) + , m_rightHasAssignments(rightHasAssignments) + { + } + + inline AssignResolveNode::AssignResolveNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments) + : ExpressionNode(globalData) + , m_ident(ident) + , m_right(right) + , m_rightHasAssignments(rightHasAssignments) + { + } + + inline ReadModifyBracketNode::ReadModifyBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableSubExpressionData(divot, startOffset, endOffset) + , m_base(base) + , m_subscript(subscript) + , m_right(right) + , m_operator(oper) + , m_subscriptHasAssignments(subscriptHasAssignments) + , m_rightHasAssignments(rightHasAssignments) + { + } + + inline AssignBracketNode::AssignBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableExpressionData(divot, startOffset, endOffset) + , m_base(base) + , m_subscript(subscript) + , m_right(right) + , m_subscriptHasAssignments(subscriptHasAssignments) + , m_rightHasAssignments(rightHasAssignments) + { + } + + inline AssignDotNode::AssignDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableExpressionData(divot, startOffset, endOffset) + , m_base(base) + , m_ident(ident) + , m_right(right) + , m_rightHasAssignments(rightHasAssignments) + { + } + + inline ReadModifyDotNode::ReadModifyDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableSubExpressionData(divot, startOffset, endOffset) + , m_base(base) + , m_ident(ident) + , m_right(right) + , m_operator(oper) + , m_rightHasAssignments(rightHasAssignments) + { + } + + inline AssignErrorNode::AssignErrorNode(JSGlobalData* globalData, ExpressionNode* left, Operator oper, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset) + : ExpressionNode(globalData) + , ThrowableExpressionData(divot, startOffset, endOffset) + , m_left(left) + , m_operator(oper) + , m_right(right) + { + } + + inline CommaNode::CommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2) + : ExpressionNode(globalData) + , m_expr1(expr1) + , m_expr2(expr2) + { + } + + inline ConstStatementNode::ConstStatementNode(JSGlobalData* globalData, ConstDeclNode* next) + : StatementNode(globalData) + , m_next(next) + { + } + + inline SourceElements::SourceElements(JSGlobalData*) + { + } + + inline EmptyStatementNode::EmptyStatementNode(JSGlobalData* globalData) + : StatementNode(globalData) + { + } + + inline DebuggerStatementNode::DebuggerStatementNode(JSGlobalData* globalData) + : StatementNode(globalData) + { + } + + inline ExprStatementNode::ExprStatementNode(JSGlobalData* globalData, ExpressionNode* expr) + : StatementNode(globalData) + , m_expr(expr) + { + } + + inline VarStatementNode::VarStatementNode(JSGlobalData* globalData, ExpressionNode* expr) + : StatementNode(globalData) + , m_expr(expr) + { + } + + inline IfNode::IfNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock) + : StatementNode(globalData) + , m_condition(condition) + , m_ifBlock(ifBlock) + { + } + + inline IfElseNode::IfElseNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock) + : IfNode(globalData, condition, ifBlock) + , m_elseBlock(elseBlock) + { + } + + inline DoWhileNode::DoWhileNode(JSGlobalData* globalData, StatementNode* statement, ExpressionNode* expr) + : StatementNode(globalData) + , m_statement(statement) + , m_expr(expr) + { + } + + inline WhileNode::WhileNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement) + : StatementNode(globalData) + , m_expr(expr) + , m_statement(statement) + { + } + + inline ForNode::ForNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl) + : StatementNode(globalData) + , m_expr1(expr1) + , m_expr2(expr2) + , m_expr3(expr3) + , m_statement(statement) + , m_expr1WasVarDecl(expr1 && expr1WasVarDecl) + { + ASSERT(statement); + } + + inline ContinueNode::ContinueNode(JSGlobalData* globalData) + : StatementNode(globalData) + { + } + + inline ContinueNode::ContinueNode(JSGlobalData* globalData, const Identifier& ident) + : StatementNode(globalData) + , m_ident(ident) + { + } + + inline BreakNode::BreakNode(JSGlobalData* globalData) + : StatementNode(globalData) + { + } + + inline BreakNode::BreakNode(JSGlobalData* globalData, const Identifier& ident) + : StatementNode(globalData) + , m_ident(ident) + { + } + + inline ReturnNode::ReturnNode(JSGlobalData* globalData, ExpressionNode* value) + : StatementNode(globalData) + , m_value(value) + { + } + + inline WithNode::WithNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement, uint32_t divot, uint32_t expressionLength) + : StatementNode(globalData) + , m_expr(expr) + , m_statement(statement) + , m_divot(divot) + , m_expressionLength(expressionLength) + { + } + + inline LabelNode::LabelNode(JSGlobalData* globalData, const Identifier& name, StatementNode* statement) + : StatementNode(globalData) + , m_name(name) + , m_statement(statement) + { + } + + inline ThrowNode::ThrowNode(JSGlobalData* globalData, ExpressionNode* expr) + : StatementNode(globalData) + , m_expr(expr) + { + } + + inline TryNode::TryNode(JSGlobalData* globalData, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock) + : StatementNode(globalData) + , m_tryBlock(tryBlock) + , m_exceptionIdent(exceptionIdent) + , m_catchBlock(catchBlock) + , m_finallyBlock(finallyBlock) + , m_catchHasEval(catchHasEval) + { + } + + inline ParameterNode::ParameterNode(JSGlobalData*, const Identifier& ident) + : m_ident(ident) + , m_next(0) + { + } + + inline ParameterNode::ParameterNode(JSGlobalData*, ParameterNode* l, const Identifier& ident) + : m_ident(ident) + , m_next(0) + { + l->m_next = this; + } + + inline FuncExprNode::FuncExprNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter) + : ExpressionNode(globalData) + , ParserArenaRefCounted(globalData) + , m_ident(ident) + , m_body(body) + { + m_body->finishParsing(source, parameter); + } + + inline FuncDeclNode::FuncDeclNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter) + : StatementNode(globalData) + , ParserArenaRefCounted(globalData) + , m_ident(ident) + , m_body(body) + { + m_body->finishParsing(source, parameter); + } + + inline CaseClauseNode::CaseClauseNode(JSGlobalData*, ExpressionNode* expr) + : m_expr(expr) + { + } + + inline CaseClauseNode::CaseClauseNode(JSGlobalData*, ExpressionNode* expr, SourceElements* children) + : m_expr(expr) + { + if (children) + children->releaseContentsIntoVector(m_children); + } + + inline ClauseListNode::ClauseListNode(JSGlobalData*, CaseClauseNode* clause) + : m_clause(clause) + , m_next(0) + { + } + + inline ClauseListNode::ClauseListNode(JSGlobalData*, ClauseListNode* clauseList, CaseClauseNode* clause) + : m_clause(clause) + , m_next(0) + { + clauseList->m_next = this; + } + + inline CaseBlockNode::CaseBlockNode(JSGlobalData*, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2) + : m_list1(list1) + , m_defaultClause(defaultClause) + , m_list2(list2) + { + } + + inline SwitchNode::SwitchNode(JSGlobalData* globalData, ExpressionNode* expr, CaseBlockNode* block) + : StatementNode(globalData) + , m_expr(expr) + , m_block(block) + { + } + + inline ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init) + : ExpressionNode(globalData) + , m_ident(ident) + , m_next(0) + , m_init(init) + { + } + + inline BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children) + : StatementNode(globalData) + { + if (children) + children->releaseContentsIntoVector(m_children); + } + + inline ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement) + : StatementNode(globalData) + , m_init(0) + , m_lexpr(l) + , m_expr(expr) + , m_statement(statement) + , m_identIsVarDecl(false) + { + } + + inline ForInNode::ForInNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset) + : StatementNode(globalData) + , m_ident(ident) + , m_init(0) + , m_lexpr(new (globalData) ResolveNode(globalData, ident, divot - startOffset)) + , m_expr(expr) + , m_statement(statement) + , m_identIsVarDecl(true) + { + if (in) { + AssignResolveNode* node = new (globalData) AssignResolveNode(globalData, ident, in, true); + node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot); + m_init = node; + } + // for( var foo = bar in baz ) + } + +} // namespace JSC + +#endif // NodeConstructors_h diff --git a/JavaScriptCore/parser/NodeInfo.h b/JavaScriptCore/parser/NodeInfo.h index a518b23..7f4deff 100644 --- a/JavaScriptCore/parser/NodeInfo.h +++ b/JavaScriptCore/parser/NodeInfo.h @@ -43,8 +43,8 @@ namespace JSC { template <typename T> struct NodeDeclarationInfo { T m_node; - ParserRefCountedData<DeclarationStacks::VarStack>* m_varDeclarations; - ParserRefCountedData<DeclarationStacks::FunctionStack>* m_funcDeclarations; + ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; + ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; CodeFeatures m_features; int m_numConstants; }; diff --git a/JavaScriptCore/parser/Nodes.cpp b/JavaScriptCore/parser/Nodes.cpp index f7fa739..38e842a 100644 --- a/JavaScriptCore/parser/Nodes.cpp +++ b/JavaScriptCore/parser/Nodes.cpp @@ -25,24 +25,23 @@ #include "config.h" #include "Nodes.h" +#include "NodeConstructors.h" #include "BytecodeGenerator.h" #include "CallFrame.h" +#include "Debugger.h" +#include "JIT.h" +#include "JSFunction.h" #include "JSGlobalObject.h" #include "JSStaticScopeObject.h" #include "LabelScope.h" +#include "Lexer.h" +#include "Operations.h" #include "Parser.h" #include "PropertyNameArray.h" #include "RegExpObject.h" #include "SamplingTool.h" -#include "Debugger.h" -#include "Lexer.h" -#include "Operations.h" -#include <math.h> #include <wtf/Assertions.h> -#include <wtf/HashCountedSet.h> -#include <wtf/HashSet.h> -#include <wtf/MathExtras.h> #include <wtf/RefCountedLeakCounter.h> #include <wtf/Threading.h> @@ -50,173 +49,7 @@ using namespace WTF; namespace JSC { -static void substitute(UString& string, const UString& substring) JSC_FAST_CALL; - -// ------------------------------ NodeReleaser -------------------------------- - -class NodeReleaser : Noncopyable { -public: - // Call this function inside the destructor of a class derived from Node. - // This will traverse the tree below this node, destroying all of those nodes, - // but without relying on recursion. - static void releaseAllNodes(ParserRefCounted* root); - - // Call this on each node in a the releaseNodes virtual function. - // It gives the node to the NodeReleaser, which will then release the - // node later at the end of the releaseAllNodes process. - template <typename T> void release(RefPtr<T>& node) { if (node) adopt(node.release()); } - void release(RefPtr<FunctionBodyNode>& node) { if (node) adoptFunctionBodyNode(node); } - -private: - NodeReleaser() { } - ~NodeReleaser() { } - - void adopt(PassRefPtr<ParserRefCounted>); - void adoptFunctionBodyNode(RefPtr<FunctionBodyNode>&); - - typedef Vector<RefPtr<ParserRefCounted> > NodeReleaseVector; - OwnPtr<NodeReleaseVector> m_vector; -}; - -void NodeReleaser::releaseAllNodes(ParserRefCounted* root) -{ - ASSERT(root); - NodeReleaser releaser; - root->releaseNodes(releaser); - if (!releaser.m_vector) - return; - // Note: The call to release.m_vector->size() is intentionally inside - // the loop, since calls to releaseNodes are expected to increase the size. - for (size_t i = 0; i < releaser.m_vector->size(); ++i) { - ParserRefCounted* node = (*releaser.m_vector)[i].get(); - if (node->hasOneRef()) - node->releaseNodes(releaser); - } -} - -void NodeReleaser::adopt(PassRefPtr<ParserRefCounted> node) -{ - ASSERT(node); - if (!node->hasOneRef()) - return; - if (!m_vector) - m_vector.set(new NodeReleaseVector); - m_vector->append(node); -} - -void NodeReleaser::adoptFunctionBodyNode(RefPtr<FunctionBodyNode>& functionBodyNode) -{ - // This sidesteps a problem where if you assign a PassRefPtr<FunctionBodyNode> - // to a PassRefPtr<Node> we leave the two reference counts (FunctionBodyNode - // and ParserRefCounted) unbalanced. It would be nice to fix this problem in - // a cleaner way -- perhaps we could remove the FunctionBodyNode reference - // count at some point. - RefPtr<Node> node = functionBodyNode; - functionBodyNode = 0; - adopt(node.release()); -} - -// ------------------------------ ParserRefCounted ----------------------------------------- - -#ifndef NDEBUG -static RefCountedLeakCounter parserRefCountedCounter("JSC::Node"); -#endif - -ParserRefCounted::ParserRefCounted(JSGlobalData* globalData) - : m_globalData(globalData) -{ -#ifndef NDEBUG - parserRefCountedCounter.increment(); -#endif - if (!m_globalData->newParserObjects) - m_globalData->newParserObjects = new HashSet<ParserRefCounted*>; - m_globalData->newParserObjects->add(this); - ASSERT(m_globalData->newParserObjects->contains(this)); -} - -ParserRefCounted::~ParserRefCounted() -{ -#ifndef NDEBUG - parserRefCountedCounter.decrement(); -#endif -} - -void ParserRefCounted::releaseNodes(NodeReleaser&) -{ -} - -void ParserRefCounted::ref() -{ - // bumping from 0 to 1 is just removing from the new nodes set - if (m_globalData->newParserObjects) { - HashSet<ParserRefCounted*>::iterator it = m_globalData->newParserObjects->find(this); - if (it != m_globalData->newParserObjects->end()) { - m_globalData->newParserObjects->remove(it); - ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this)); - return; - } - } - - ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this)); - - if (!m_globalData->parserObjectExtraRefCounts) - m_globalData->parserObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>; - m_globalData->parserObjectExtraRefCounts->add(this); -} - -void ParserRefCounted::deref() -{ - ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this)); - - if (!m_globalData->parserObjectExtraRefCounts) { - delete this; - return; - } - - HashCountedSet<ParserRefCounted*>::iterator it = m_globalData->parserObjectExtraRefCounts->find(this); - if (it == m_globalData->parserObjectExtraRefCounts->end()) - delete this; - else - m_globalData->parserObjectExtraRefCounts->remove(it); -} - -bool ParserRefCounted::hasOneRef() -{ - if (m_globalData->newParserObjects && m_globalData->newParserObjects->contains(this)) { - ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this)); - return false; - } - - ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this)); - - if (!m_globalData->parserObjectExtraRefCounts) - return true; - - return !m_globalData->parserObjectExtraRefCounts->contains(this); -} - -void ParserRefCounted::deleteNewObjects(JSGlobalData* globalData) -{ - if (!globalData->newParserObjects) - return; - -#ifndef NDEBUG - HashSet<ParserRefCounted*>::iterator end = globalData->newParserObjects->end(); - for (HashSet<ParserRefCounted*>::iterator it = globalData->newParserObjects->begin(); it != end; ++it) - ASSERT(!globalData->parserObjectExtraRefCounts || !globalData->parserObjectExtraRefCounts->contains(*it)); -#endif - deleteAllValues(*globalData->newParserObjects); - delete globalData->newParserObjects; - globalData->newParserObjects = 0; -} - -// ------------------------------ Node -------------------------------- - -Node::Node(JSGlobalData* globalData) - : ParserRefCounted(globalData) -{ - m_line = globalData->lexer->lineNo(); -} +static void substitute(UString& string, const UString& substring); // ------------------------------ ThrowableExpressionData -------------------------------- @@ -247,14 +80,8 @@ RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator generator.emitThrow(exception); return exception; } - -// ------------------------------ StatementNode -------------------------------- -StatementNode::StatementNode(JSGlobalData* globalData) - : Node(globalData) - , m_lastLine(-1) -{ -} +// ------------------------------ StatementNode -------------------------------- void StatementNode::setLoc(int firstLine, int lastLine) { @@ -264,11 +91,10 @@ void StatementNode::setLoc(int firstLine, int lastLine) // ------------------------------ SourceElements -------------------------------- -void SourceElements::append(PassRefPtr<StatementNode> statement) +void SourceElements::append(StatementNode* statement) { if (statement->isEmptyStatement()) return; - m_statements.append(statement); } @@ -348,47 +174,24 @@ RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* return generator.emitResolve(generator.finalDestination(dst), m_ident); } -// ------------------------------ ElementNode ------------------------------------ - -ElementNode::~ElementNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ElementNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_next); - releaser.release(m_node); -} - // ------------------------------ ArrayNode ------------------------------------ -ArrayNode::~ArrayNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ArrayNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_element); -} - RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { // FIXME: Should we put all of this code into emitNewArray? unsigned length = 0; ElementNode* firstPutElement; - for (firstPutElement = m_element.get(); firstPutElement; firstPutElement = firstPutElement->next()) { + for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) { if (firstPutElement->elision()) break; ++length; } if (!firstPutElement && !m_elision) - return generator.emitNewArray(generator.finalDestination(dst), m_element.get()); + return generator.emitNewArray(generator.finalDestination(dst), m_element); - RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element.get()); + RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element); for (ElementNode* n = firstPutElement; n; n = n->next()) { RegisterID* value = generator.emitNode(n->value()); @@ -404,30 +207,35 @@ RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds return generator.moveToDestinationIfNeeded(dst, array.get()); } -// ------------------------------ PropertyNode ---------------------------- - -PropertyNode::~PropertyNode() +bool ArrayNode::isSimpleArray() const { - NodeReleaser::releaseAllNodes(this); + if (m_elision || m_optional) + return false; + for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) { + if (ptr->elision()) + return false; + } + return true; } -void PropertyNode::releaseNodes(NodeReleaser& releaser) +ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData) const { - releaser.release(m_assign); + ASSERT(!m_elision && !m_optional); + ElementNode* ptr = m_element; + if (!ptr) + return 0; + ArgumentListNode* head = new (globalData) ArgumentListNode(globalData, ptr->value()); + ArgumentListNode* tail = head; + ptr = ptr->next(); + for (; ptr; ptr = ptr->next()) { + ASSERT(!ptr->elision()); + tail = new (globalData) ArgumentListNode(globalData, tail, ptr->value()); + } + return head; } // ------------------------------ ObjectLiteralNode ---------------------------- -ObjectLiteralNode::~ObjectLiteralNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ObjectLiteralNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_list); -} - RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (!m_list) { @@ -435,30 +243,19 @@ RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, Regist return 0; return generator.emitNewObject(generator.finalDestination(dst)); } - return generator.emitNode(dst, m_list.get()); + return generator.emitNode(dst, m_list); } // ------------------------------ PropertyListNode ----------------------------- -PropertyListNode::~PropertyListNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PropertyListNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_node); - releaser.release(m_next); -} - RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> newObj = generator.tempDestination(dst); generator.emitNewObject(newObj.get()); - for (PropertyListNode* p = this; p; p = p->m_next.get()) { - RegisterID* value = generator.emitNode(p->m_node->m_assign.get()); + for (PropertyListNode* p = this; p; p = p->m_next) { + RegisterID* value = generator.emitNode(p->m_node->m_assign); switch (p->m_node->m_type) { case PropertyNode::Constant: { @@ -483,152 +280,66 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe // ------------------------------ BracketAccessorNode -------------------------------- -BracketAccessorNode::~BracketAccessorNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void BracketAccessorNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); -} - RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript->isPure(generator)); - RegisterID* property = generator.emitNode(m_subscript.get()); + RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator)); + RegisterID* property = generator.emitNode(m_subscript); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property); } // ------------------------------ DotAccessorNode -------------------------------- -DotAccessorNode::~DotAccessorNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void DotAccessorNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); -} - RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RegisterID* base = generator.emitNode(m_base.get()); + RegisterID* base = generator.emitNode(m_base); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitGetById(generator.finalDestination(dst), base, m_ident); } // ------------------------------ ArgumentListNode ----------------------------- -ArgumentListNode::~ArgumentListNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ArgumentListNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_next); - releaser.release(m_expr); -} - RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { ASSERT(m_expr); - return generator.emitNode(dst, m_expr.get()); -} - -// ------------------------------ ArgumentsNode ----------------------------- - -ArgumentsNode::~ArgumentsNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ArgumentsNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_listNode); + return generator.emitNode(dst, m_expr); } // ------------------------------ NewExprNode ---------------------------------- -NewExprNode::~NewExprNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void NewExprNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); - releaser.release(m_args); -} - RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> func = generator.emitNode(m_expr.get()); - return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args.get(), divot(), startOffset(), endOffset()); + RefPtr<RegisterID> func = generator.emitNode(m_expr); + return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args, divot(), startOffset(), endOffset()); } // ------------------------------ EvalFunctionCallNode ---------------------------------- -EvalFunctionCallNode::~EvalFunctionCallNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void EvalFunctionCallNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_args); -} - RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> func = generator.tempDestination(dst); RefPtr<RegisterID> thisRegister = generator.newTemporary(); generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0); generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval); - return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); + return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); } // ------------------------------ FunctionCallValueNode ---------------------------------- -FunctionCallValueNode::~FunctionCallValueNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void FunctionCallValueNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); - releaser.release(m_args); -} - RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> func = generator.emitNode(m_expr.get()); + RefPtr<RegisterID> func = generator.emitNode(m_expr); RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); - return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); + return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); } // ------------------------------ FunctionCallResolveNode ---------------------------------- -FunctionCallResolveNode::~FunctionCallResolveNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void FunctionCallResolveNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_args); -} - RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) { RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); - return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); + return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); } int index = 0; @@ -637,7 +348,7 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) { RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); - return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); + return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); } RefPtr<RegisterID> func = generator.newTemporary(); @@ -645,53 +356,134 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, int identifierStart = divot() - startOffset(); generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0); generator.emitResolveFunction(thisRegister.get(), func.get(), m_ident); - return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); + return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); } // ------------------------------ FunctionCallBracketNode ---------------------------------- -FunctionCallBracketNode::~FunctionCallBracketNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void FunctionCallBracketNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); - releaser.release(m_args); -} - RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNode(m_base.get()); - RegisterID* property = generator.emitNode(m_subscript.get()); + RefPtr<RegisterID> base = generator.emitNode(m_base); + RegisterID* property = generator.emitNode(m_subscript); generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property); RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); - return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); + return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); } // ------------------------------ FunctionCallDotNode ---------------------------------- -FunctionCallDotNode::~FunctionCallDotNode() +RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - NodeReleaser::releaseAllNodes(this); + RefPtr<RegisterID> base = generator.emitNode(m_base); + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); + generator.emitMethodCheck(); + RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); + RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); + return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); } -void FunctionCallDotNode::releaseNodes(NodeReleaser& releaser) +RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<Label> realCall = generator.newLabel(); + RefPtr<Label> end = generator.newLabel(); + RefPtr<RegisterID> base = generator.emitNode(m_base); + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); + RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); + RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get()); + generator.emitJumpIfNotFunctionCall(function.get(), realCall.get()); + { + RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); + RefPtr<RegisterID> thisRegister = generator.newTemporary(); + ArgumentListNode* oldList = m_args->m_listNode; + if (m_args->m_listNode && m_args->m_listNode->m_expr) { + generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr); + m_args->m_listNode = m_args->m_listNode->m_next; + } else + generator.emitLoad(thisRegister.get(), jsNull()); + + generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + generator.emitJump(end.get()); + m_args->m_listNode = oldList; + } + generator.emitLabel(realCall.get()); + { + RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); + generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + } + generator.emitLabel(end.get()); + return finalDestination.get(); +} + +static bool areTrivialApplyArguments(ArgumentsNode* args) { - releaser.release(m_base); - releaser.release(m_args); + return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next + || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray()); } -RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNode(m_base.get()); + // A few simple cases can be trivially handled as ordinary function calls. + // function.apply(), function.apply(arg) -> identical to function.call + // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation + bool mayBeCall = areTrivialApplyArguments(m_args); + + RefPtr<Label> realCall = generator.newLabel(); + RefPtr<Label> end = generator.newLabel(); + RefPtr<RegisterID> base = generator.emitNode(m_base); generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); - RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); - return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); + RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get()); + generator.emitJumpIfNotFunctionApply(function.get(), realCall.get()); + { + if (mayBeCall) { + RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); + RefPtr<RegisterID> thisRegister = generator.newTemporary(); + ArgumentListNode* oldList = m_args->m_listNode; + if (m_args->m_listNode && m_args->m_listNode->m_expr) { + generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr); + m_args->m_listNode = m_args->m_listNode->m_next; + if (m_args->m_listNode) { + ASSERT(m_args->m_listNode->m_expr->isSimpleArray()); + ASSERT(!m_args->m_listNode->m_next); + m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_expr)->toArgumentList(generator.globalData()); + } + } else + generator.emitLoad(thisRegister.get(), jsNull()); + generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + m_args->m_listNode = oldList; + } else { + ASSERT(m_args->m_listNode && m_args->m_listNode->m_next); + RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get()); + RefPtr<RegisterID> argsCountRegister = generator.newTemporary(); + RefPtr<RegisterID> thisRegister = generator.newTemporary(); + RefPtr<RegisterID> argsRegister = generator.newTemporary(); + generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr); + ArgumentListNode* args = m_args->m_listNode->m_next; + bool isArgumentsApply = false; + if (args->m_expr->isResolveNode()) { + ResolveNode* resolveNode = static_cast<ResolveNode*>(args->m_expr); + isArgumentsApply = generator.willResolveToArguments(resolveNode->identifier()); + if (isArgumentsApply) + generator.emitMove(argsRegister.get(), generator.uncheckedRegisterForArguments()); + } + if (!isArgumentsApply) + generator.emitNode(argsRegister.get(), args->m_expr); + while ((args = args->m_next)) + generator.emitNode(args->m_expr); + + generator.emitLoadVarargs(argsCountRegister.get(), argsRegister.get()); + generator.emitCallVarargs(finalDestination.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset()); + } + generator.emitJump(end.get()); + } + generator.emitLabel(realCall.get()); + { + RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); + generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + } + generator.emitLabel(end.get()); + return finalDestination.get(); } // ------------------------------ PostfixResolveNode ---------------------------------- @@ -752,21 +544,10 @@ RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, Regis // ------------------------------ PostfixBracketNode ---------------------------------- -PostfixBracketNode::~PostfixBracketNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PostfixBracketNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); -} - RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNode(m_base.get()); - RefPtr<RegisterID> property = generator.emitNode(m_subscript.get()); + RefPtr<RegisterID> base = generator.emitNode(m_base); + RefPtr<RegisterID> property = generator.emitNode(m_subscript); generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get()); @@ -787,19 +568,9 @@ RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, Regis // ------------------------------ PostfixDotNode ---------------------------------- -PostfixDotNode::~PostfixDotNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PostfixDotNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); -} - RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNode(m_base.get()); + RefPtr<RegisterID> base = generator.emitNode(m_base); generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident); @@ -820,16 +591,6 @@ RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterI // ------------------------------ PostfixErrorNode ----------------------------------- -PostfixErrorNode::~PostfixErrorNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PostfixErrorNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Postfix ++ operator applied to value that is not a reference." : "Postfix -- operator applied to value that is not a reference."); @@ -849,21 +610,10 @@ RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, Regist // ------------------------------ DeleteBracketNode ----------------------------------- -DeleteBracketNode::~DeleteBracketNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void DeleteBracketNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); -} - RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> r0 = generator.emitNode(m_base.get()); - RegisterID* r1 = generator.emitNode(m_subscript.get()); + RefPtr<RegisterID> r0 = generator.emitNode(m_base); + RegisterID* r1 = generator.emitNode(m_subscript); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1); @@ -871,19 +621,9 @@ RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, Regist // ------------------------------ DeleteDotNode ----------------------------------- -DeleteDotNode::~DeleteDotNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void DeleteDotNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); -} - RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RegisterID* r0 = generator.emitNode(m_base.get()); + RegisterID* r0 = generator.emitNode(m_base); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident); @@ -891,19 +631,9 @@ RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID // ------------------------------ DeleteValueNode ----------------------------------- -DeleteValueNode::~DeleteValueNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void DeleteValueNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitNode(generator.ignoredResult(), m_expr.get()); + generator.emitNode(generator.ignoredResult(), m_expr); // delete on a non-location expression ignores the value and returns true return generator.emitUnexpectedLoad(generator.finalDestination(dst), true); @@ -911,23 +641,13 @@ RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, Register // ------------------------------ VoidNode ------------------------------------- -VoidNode::~VoidNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void VoidNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (dst == generator.ignoredResult()) { - generator.emitNode(generator.ignoredResult(), m_expr.get()); + generator.emitNode(generator.ignoredResult(), m_expr); return 0; } - RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get()); + RefPtr<RegisterID> r0 = generator.emitNode(m_expr); return generator.emitLoad(dst, jsUndefined()); } @@ -950,23 +670,13 @@ RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, Regist // ------------------------------ TypeOfValueNode ----------------------------------- -TypeOfValueNode::~TypeOfValueNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void TypeOfValueNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (dst == generator.ignoredResult()) { - generator.emitNode(generator.ignoredResult(), m_expr.get()); + generator.emitNode(generator.ignoredResult(), m_expr); return 0; } - RefPtr<RegisterID> src = generator.emitNode(m_expr.get()); + RefPtr<RegisterID> src = generator.emitNode(m_expr); return generator.emitTypeOf(generator.finalDestination(dst), src.get()); } @@ -1006,21 +716,10 @@ RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, Regist // ------------------------------ PrefixBracketNode ---------------------------------- -PrefixBracketNode::~PrefixBracketNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PrefixBracketNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); -} - RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNode(m_base.get()); - RefPtr<RegisterID> property = generator.emitNode(m_subscript.get()); + RefPtr<RegisterID> base = generator.emitNode(m_base); + RefPtr<RegisterID> property = generator.emitNode(m_subscript); RefPtr<RegisterID> propDst = generator.tempDestination(dst); generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); @@ -1036,19 +735,9 @@ RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, Regist // ------------------------------ PrefixDotNode ---------------------------------- -PrefixDotNode::~PrefixDotNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PrefixDotNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); -} - RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNode(m_base.get()); + RefPtr<RegisterID> base = generator.emitNode(m_base); RefPtr<RegisterID> propDst = generator.tempDestination(dst); generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); @@ -1064,16 +753,6 @@ RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID // ------------------------------ PrefixErrorNode ----------------------------------- -PrefixErrorNode::~PrefixErrorNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void PrefixErrorNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Prefix ++ operator applied to value that is not a reference." : "Prefix -- operator applied to value that is not a reference."); @@ -1081,48 +760,149 @@ RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, Register // ------------------------------ Unary Operation Nodes ----------------------------------- -UnaryOpNode::~UnaryOpNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void UnaryOpNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RegisterID* src = generator.emitNode(m_expr.get()); + RegisterID* src = generator.emitNode(m_expr); return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src); } // ------------------------------ Binary Operation Nodes ----------------------------------- -BinaryOpNode::~BinaryOpNode() -{ - NodeReleaser::releaseAllNodes(this); -} +// BinaryOpNode::emitStrcat: +// +// This node generates an op_strcat operation. This opcode can handle concatenation of three or +// more values, where we can determine a set of separate op_add operations would be operating on +// string values. +// +// This function expects to be operating on a graph of AST nodes looking something like this: +// +// (a)... (b) +// \ / +// (+) (c) +// \ / +// [d] ((+)) +// \ / +// [+=] +// +// The assignment operation is optional, if it exists the register holding the value on the +// lefthand side of the assignment should be passing as the optional 'lhs' argument. +// +// The method should be called on the node at the root of the tree of regular binary add +// operations (marked in the diagram with a double set of parentheses). This node must +// be performing a string concatenation (determined by statically detecting that at least +// one child must be a string). +// +// Since the minimum number of values being concatenated together is expected to be 3, if +// a lhs to a concatenating assignment is not provided then the root add should have at +// least one left child that is also an add that can be determined to be operating on strings. +// +RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe) +{ + ASSERT(isAdd()); + ASSERT(resultDescriptor().definitelyIsString()); + + // Create a list of expressions for all the adds in the tree of nodes we can convert into + // a string concatenation. The rightmost node (c) is added first. The rightmost node is + // added first, and the leftmost child is never added, so the vector produced for the + // example above will be [ c, b ]. + Vector<ExpressionNode*, 16> reverseExpressionList; + reverseExpressionList.append(m_expr2); + + // Examine the left child of the add. So long as this is a string add, add its right-child + // to the list, and keep processing along the left fork. + ExpressionNode* leftMostAddChild = m_expr1; + while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) { + reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2); + leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1; + } -void BinaryOpNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr1); - releaser.release(m_expr2); + Vector<RefPtr<RegisterID>, 16> temporaryRegisters; + + // If there is an assignment, allocate a temporary to hold the lhs after conversion. + // We could possibly avoid this (the lhs is converted last anyway, we could let the + // op_strcat node handle its conversion if required). + if (lhs) + temporaryRegisters.append(generator.newTemporary()); + + // Emit code for the leftmost node ((a) in the example). + temporaryRegisters.append(generator.newTemporary()); + RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get(); + generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild); + + // Note on ordering of conversions: + // + // We maintain the same ordering of conversions as we would see if the concatenations + // was performed as a sequence of adds (otherwise this optimization could change + // behaviour should an object have been provided a valueOf or toString method). + // + // Considering the above example, the sequnce of execution is: + // * evaluate operand (a) + // * evaluate operand (b) + // * convert (a) to primitive <- (this would be triggered by the first add) + // * convert (b) to primitive <- (ditto) + // * evaluate operand (c) + // * convert (c) to primitive <- (this would be triggered by the second add) + // And optionally, if there is an assignment: + // * convert (d) to primitive <- (this would be triggered by the assigning addition) + // + // As such we do not plant an op to convert the leftmost child now. Instead, use + // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion + // once the second node has been generated. However, if the leftmost child is an + // immediate we can trivially determine that no conversion will be required. + // If this is the case + if (leftMostAddChild->isString()) + leftMostAddChildTempRegister = 0; + + while (reverseExpressionList.size()) { + ExpressionNode* node = reverseExpressionList.last(); + reverseExpressionList.removeLast(); + + // Emit the code for the current node. + temporaryRegisters.append(generator.newTemporary()); + generator.emitNode(temporaryRegisters.last().get(), node); + + // On the first iteration of this loop, when we first reach this point we have just + // generated the second node, which means it is time to convert the leftmost operand. + if (leftMostAddChildTempRegister) { + generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister); + leftMostAddChildTempRegister = 0; // Only do this once. + } + // Plant a conversion for this node, if necessary. + if (!node->isString()) + generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get()); + } + ASSERT(temporaryRegisters.size() >= 3); + + // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated. + // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now. + if (emitExpressionInfoForMe) + generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset()); + + // If there is an assignment convert the lhs now. This will also copy lhs to + // the temporary register we allocated for it. + if (lhs) + generator.emitToPrimitive(temporaryRegisters[0].get(), lhs); + + return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size()); } RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { OpcodeID opcodeID = this->opcodeID(); + + if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) + return emitStrcat(generator, dst); + if (opcodeID == op_neq) { if (m_expr1->isNull() || m_expr2->isNull()) { RefPtr<RegisterID> src = generator.tempDestination(dst); - generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2.get() : m_expr1.get()); + generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1); return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get()); } } - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2.get()); + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RegisterID* src2 = generator.emitNode(m_expr2); return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); } @@ -1130,41 +910,41 @@ RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds { if (m_expr1->isNull() || m_expr2->isNull()) { RefPtr<RegisterID> src = generator.tempDestination(dst); - generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2.get() : m_expr1.get()); + generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1); return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get()); } - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2.get()); + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RegisterID* src2 = generator.emitNode(m_expr2); return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2); } RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2.get()); + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RegisterID* src2 = generator.emitNode(m_expr2); return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2); } RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2.get()); + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RegisterID* src2 = generator.emitNode(m_expr2); return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor())); } RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2.get()); + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RegisterID* src2 = generator.emitNode(m_expr2); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); } RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); - RefPtr<RegisterID> src2 = generator.emitNode(m_expr2.get()); + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RefPtr<RegisterID> src2 = generator.emitNode(m_expr2); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitGetByIdExceptionInfo(op_instanceof); @@ -1176,28 +956,17 @@ RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterI // ------------------------------ LogicalOpNode ---------------------------- -LogicalOpNode::~LogicalOpNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void LogicalOpNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr1); - releaser.release(m_expr2); -} - RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> temp = generator.tempDestination(dst); RefPtr<Label> target = generator.newLabel(); - generator.emitNode(temp.get(), m_expr1.get()); + generator.emitNode(temp.get(), m_expr1); if (m_operator == OpLogicalAnd) generator.emitJumpIfFalse(temp.get(), target.get()); else generator.emitJumpIfTrue(temp.get(), target.get()); - generator.emitNode(temp.get(), m_expr2.get()); + generator.emitNode(temp.get(), m_expr2); generator.emitLabel(target.get()); return generator.moveToDestinationIfNeeded(dst, temp.get()); @@ -1205,32 +974,20 @@ RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID // ------------------------------ ConditionalNode ------------------------------ -ConditionalNode::~ConditionalNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ConditionalNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_logical); - releaser.release(m_expr1); - releaser.release(m_expr2); -} - RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> newDst = generator.finalDestination(dst); RefPtr<Label> beforeElse = generator.newLabel(); RefPtr<Label> afterElse = generator.newLabel(); - RegisterID* cond = generator.emitNode(m_logical.get()); + RegisterID* cond = generator.emitNode(m_logical); generator.emitJumpIfFalse(cond, beforeElse.get()); - generator.emitNode(newDst.get(), m_expr1.get()); + generator.emitNode(newDst.get(), m_expr1); generator.emitJump(afterElse.get()); generator.emitLabel(beforeElse.get()); - generator.emitNode(newDst.get(), m_expr2.get()); + generator.emitNode(newDst.get(), m_expr2); generator.emitLabel(afterElse.get()); @@ -1239,18 +996,8 @@ RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, Register // ------------------------------ ReadModifyResolveNode ----------------------------------- -ReadModifyResolveNode::~ReadModifyResolveNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ReadModifyResolveNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_right); -} - // FIXME: should this be moved to be a method on BytecodeGenerator? -static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper, OperandTypes types) +static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0) { OpcodeID opcodeID; switch (oper) { @@ -1261,6 +1008,8 @@ static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& gen opcodeID = op_div; break; case OpPlusEq: + if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString()) + return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe); opcodeID = op_add; break; case OpMinusEq: @@ -1291,7 +1040,14 @@ static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& gen ASSERT_NOT_REACHED(); return dst; } - + + RegisterID* src2 = generator.emitNode(m_right); + + // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated. + // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now. + if (emitExpressionInfoForMe) + generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset()); + return generator.emitBinaryOp(opcodeID, dst, src1, src2, types); } @@ -1299,21 +1055,18 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re { if (RegisterID* local = generator.registerFor(m_ident)) { if (generator.isLocalConstant(m_ident)) { - RegisterID* src2 = generator.emitNode(m_right.get()); - return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); + return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); } if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) { RefPtr<RegisterID> result = generator.newTemporary(); generator.emitMove(result.get(), local); - RegisterID* src2 = generator.emitNode(m_right.get()); - emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); + emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); generator.emitMove(local, result.get()); return generator.moveToDestinationIfNeeded(dst, result.get()); } - RegisterID* src2 = generator.emitNode(m_right.get()); - RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); + RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); return generator.moveToDestinationIfNeeded(dst, result); } @@ -1322,8 +1075,7 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re JSObject* globalObject = 0; if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject); - RegisterID* src2 = generator.emitNode(m_right.get()); - RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); + RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); generator.emitPutScopedVar(depth, index, result, globalObject); return result; } @@ -1331,31 +1083,19 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re RefPtr<RegisterID> src1 = generator.tempDestination(dst); generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0); RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident); - RegisterID* src2 = generator.emitNode(m_right.get()); - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); + RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this); return generator.emitPutById(base.get(), m_ident, result); } // ------------------------------ AssignResolveNode ----------------------------------- -AssignResolveNode::~AssignResolveNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void AssignResolveNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_right); -} - RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (RegisterID* local = generator.registerFor(m_ident)) { if (generator.isLocalConstant(m_ident)) - return generator.emitNode(dst, m_right.get()); + return generator.emitNode(dst, m_right); - RegisterID* result = generator.emitNode(local, m_right.get()); + RegisterID* result = generator.emitNode(local, m_right); return generator.moveToDestinationIfNeeded(dst, result); } @@ -1365,7 +1105,7 @@ RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, Regist if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { if (dst == generator.ignoredResult()) dst = 0; - RegisterID* value = generator.emitNode(dst, m_right.get()); + RegisterID* value = generator.emitNode(dst, m_right); generator.emitPutScopedVar(depth, index, value, globalObject); return value; } @@ -1373,29 +1113,18 @@ RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, Regist RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident); if (dst == generator.ignoredResult()) dst = 0; - RegisterID* value = generator.emitNode(dst, m_right.get()); + RegisterID* value = generator.emitNode(dst, m_right); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitPutById(base.get(), m_ident, value); } // ------------------------------ AssignDotNode ----------------------------------- -AssignDotNode::~AssignDotNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void AssignDotNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_right); -} - RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator)); + RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator)); RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); - RegisterID* result = generator.emitNode(value.get(), m_right.get()); + RegisterID* result = generator.emitNode(value.get(), m_right); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutById(base.get(), m_ident, result); return generator.moveToDestinationIfNeeded(dst, result); @@ -1403,25 +1132,13 @@ RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID // ------------------------------ ReadModifyDotNode ----------------------------------- -ReadModifyDotNode::~ReadModifyDotNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ReadModifyDotNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_right); -} - RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator)); + RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator)); generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); - RegisterID* change = generator.emitNode(m_right.get()); - RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); + RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); return generator.emitPutById(base.get(), m_ident, updatedValue); @@ -1429,17 +1146,6 @@ RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, Regist // ------------------------------ AssignErrorNode ----------------------------------- -AssignErrorNode::~AssignErrorNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void AssignErrorNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_left); - releaser.release(m_right); -} - RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference."); @@ -1447,24 +1153,12 @@ RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, Register // ------------------------------ AssignBracketNode ----------------------------------- -AssignBracketNode::~AssignBracketNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void AssignBracketNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); - releaser.release(m_right); -} - RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); - RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator)); + RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); + RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator)); RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); - RegisterID* result = generator.emitNode(value.get(), m_right.get()); + RegisterID* result = generator.emitNode(value.get(), m_right); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutByVal(base.get(), property.get(), result); @@ -1473,27 +1167,14 @@ RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, Regist // ------------------------------ ReadModifyBracketNode ----------------------------------- -ReadModifyBracketNode::~ReadModifyBracketNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ReadModifyBracketNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_base); - releaser.release(m_subscript); - releaser.release(m_right); -} - RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); - RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator)); + RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); + RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator)); generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get()); - RegisterID* change = generator.emitNode(m_right.get()); - RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); + RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutByVal(base.get(), property.get(), updatedValue); @@ -1503,63 +1184,34 @@ RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, Re // ------------------------------ CommaNode ------------------------------------ -CommaNode::~CommaNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void CommaNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr1); - releaser.release(m_expr2); -} - RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - generator.emitNode(generator.ignoredResult(), m_expr1.get()); - return generator.emitNode(dst, m_expr2.get()); + generator.emitNode(generator.ignoredResult(), m_expr1); + return generator.emitNode(dst, m_expr2); } // ------------------------------ ConstDeclNode ------------------------------------ -ConstDeclNode::~ConstDeclNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ConstDeclNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_next); - releaser.release(m_init); -} - -ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init) - : ExpressionNode(globalData) - , m_ident(ident) - , m_init(init) -{ -} - RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator) { if (RegisterID* local = generator.constRegisterFor(m_ident)) { if (!m_init) return local; - return generator.emitNode(local, m_init.get()); + return generator.emitNode(local, m_init); } // FIXME: While this code should only be hit in eval code, it will potentially // assign to the wrong base if m_ident exists in an intervening dynamic scope. RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident); - RegisterID* value = m_init ? generator.emitNode(m_init.get()) : generator.emitLoad(0, jsUndefined()); + RegisterID* value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined()); return generator.emitPutById(base.get(), m_ident, value); } RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { RegisterID* result = 0; - for (ConstDeclNode* n = this; n; n = n->m_next.get()) + for (ConstDeclNode* n = this; n; n = n->m_next) result = n->emitCodeSingle(generator); return result; @@ -1567,58 +1219,27 @@ RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID // ------------------------------ ConstStatementNode ----------------------------- -ConstStatementNode::~ConstStatementNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ConstStatementNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_next); -} - RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); - return generator.emitNode(m_next.get()); + return generator.emitNode(m_next); } // ------------------------------ Helper functions for handling Vectors of StatementNode ------------------------------- -static inline RegisterID* statementListEmitCode(const StatementVector& statements, BytecodeGenerator& generator, RegisterID* dst) -{ - StatementVector::const_iterator end = statements.end(); - for (StatementVector::const_iterator it = statements.begin(); it != end; ++it) { - StatementNode* n = it->get(); - generator.emitNode(dst, n); - } - return 0; -} - -// ------------------------------ BlockNode ------------------------------------ - -BlockNode::~BlockNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void BlockNode::releaseNodes(NodeReleaser& releaser) +static inline void statementListEmitCode(const StatementVector& statements, BytecodeGenerator& generator, RegisterID* dst) { - size_t size = m_children.size(); + size_t size = statements.size(); for (size_t i = 0; i < size; ++i) - releaser.release(m_children[i]); + generator.emitNode(dst, statements[i]); } -BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children) - : StatementNode(globalData) -{ - if (children) - children->releaseContentsIntoVector(m_children); -} +// ------------------------------ BlockNode ------------------------------------ RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - return statementListEmitCode(m_children, generator, dst); + statementListEmitCode(m_children, generator, dst); + return 0; } // ------------------------------ EmptyStatementNode --------------------------- @@ -1643,51 +1264,30 @@ RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, Regist { ASSERT(m_expr); generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); - return generator.emitNode(dst, m_expr.get()); + return generator.emitNode(dst, m_expr); } // ------------------------------ VarStatementNode ---------------------------- -VarStatementNode::~VarStatementNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void VarStatementNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { ASSERT(m_expr); generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); - return generator.emitNode(m_expr.get()); + return generator.emitNode(m_expr); } // ------------------------------ IfNode --------------------------------------- -IfNode::~IfNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void IfNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_condition); - releaser.release(m_ifBlock); -} - RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); RefPtr<Label> afterThen = generator.newLabel(); - RegisterID* cond = generator.emitNode(m_condition.get()); + RegisterID* cond = generator.emitNode(m_condition); generator.emitJumpIfFalse(cond, afterThen.get()); - generator.emitNode(dst, m_ifBlock.get()); + generator.emitNode(dst, m_ifBlock); generator.emitLabel(afterThen.get()); // FIXME: This should return the last statement executed so that it can be returned as a Completion. @@ -1696,17 +1296,6 @@ RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) // ------------------------------ IfElseNode --------------------------------------- -IfElseNode::~IfElseNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void IfElseNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_elseBlock); - IfNode::releaseNodes(releaser); -} - RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); @@ -1714,15 +1303,15 @@ RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d RefPtr<Label> beforeElse = generator.newLabel(); RefPtr<Label> afterElse = generator.newLabel(); - RegisterID* cond = generator.emitNode(m_condition.get()); + RegisterID* cond = generator.emitNode(m_condition); generator.emitJumpIfFalse(cond, beforeElse.get()); - generator.emitNode(dst, m_ifBlock.get()); + generator.emitNode(dst, m_ifBlock); generator.emitJump(afterElse.get()); generator.emitLabel(beforeElse.get()); - generator.emitNode(dst, m_elseBlock.get()); + generator.emitNode(dst, m_elseBlock); generator.emitLabel(afterElse.get()); @@ -1732,17 +1321,6 @@ RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d // ------------------------------ DoWhileNode ---------------------------------- -DoWhileNode::~DoWhileNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void DoWhileNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_statement); - releaser.release(m_expr); -} - RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); @@ -1752,11 +1330,11 @@ RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); - RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get()); + RefPtr<RegisterID> result = generator.emitNode(dst, m_statement); generator.emitLabel(scope->continueTarget()); generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); - RegisterID* cond = generator.emitNode(m_expr.get()); + RegisterID* cond = generator.emitNode(m_expr); generator.emitJumpIfTrue(cond, topOfLoop.get()); generator.emitLabel(scope->breakTarget()); @@ -1765,17 +1343,6 @@ RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* // ------------------------------ WhileNode ------------------------------------ -WhileNode::~WhileNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void WhileNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); - releaser.release(m_statement); -} - RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); @@ -1785,11 +1352,11 @@ RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RefPtr<Label> topOfLoop = generator.newLabel(); generator.emitLabel(topOfLoop.get()); - generator.emitNode(dst, m_statement.get()); + generator.emitNode(dst, m_statement); generator.emitLabel(scope->continueTarget()); generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); - RegisterID* cond = generator.emitNode(m_expr.get()); + RegisterID* cond = generator.emitNode(m_expr); generator.emitJumpIfTrue(cond, topOfLoop.get()); generator.emitLabel(scope->breakTarget()); @@ -1800,19 +1367,6 @@ RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds // ------------------------------ ForNode -------------------------------------- -ForNode::~ForNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ForNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr1); - releaser.release(m_expr2); - releaser.release(m_expr3); - releaser.release(m_statement); -} - RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (dst == generator.ignoredResult()) @@ -1823,7 +1377,7 @@ RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); if (m_expr1) - generator.emitNode(generator.ignoredResult(), m_expr1.get()); + generator.emitNode(generator.ignoredResult(), m_expr1); RefPtr<Label> condition = generator.newLabel(); generator.emitJump(condition.get()); @@ -1831,16 +1385,16 @@ RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) RefPtr<Label> topOfLoop = generator.newLabel(); generator.emitLabel(topOfLoop.get()); - RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get()); + RefPtr<RegisterID> result = generator.emitNode(dst, m_statement); generator.emitLabel(scope->continueTarget()); generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); if (m_expr3) - generator.emitNode(generator.ignoredResult(), m_expr3.get()); + generator.emitNode(generator.ignoredResult(), m_expr3); generator.emitLabel(condition.get()); if (m_expr2) { - RegisterID* cond = generator.emitNode(m_expr2.get()); + RegisterID* cond = generator.emitNode(m_expr2); generator.emitJumpIfTrue(cond, topOfLoop.get()); } else generator.emitJump(topOfLoop.get()); @@ -1851,45 +1405,6 @@ RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) // ------------------------------ ForInNode ------------------------------------ -ForInNode::~ForInNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ForInNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_init); - releaser.release(m_lexpr); - releaser.release(m_expr); - releaser.release(m_statement); -} - -ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement) - : StatementNode(globalData) - , m_init(0L) - , m_lexpr(l) - , m_expr(expr) - , m_statement(statement) - , m_identIsVarDecl(false) -{ -} - -ForInNode::ForInNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset) - : StatementNode(globalData) - , m_ident(ident) - , m_lexpr(new ResolveNode(globalData, ident, divot - startOffset)) - , m_expr(expr) - , m_statement(statement) - , m_identIsVarDecl(true) -{ - if (in) { - AssignResolveNode* node = new AssignResolveNode(globalData, ident, in, true); - node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot); - m_init = node; - } - // for( var foo = bar in baz ) -} - RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); @@ -1902,8 +1417,8 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); if (m_init) - generator.emitNode(generator.ignoredResult(), m_init.get()); - RegisterID* forInBase = generator.emitNode(m_expr.get()); + generator.emitNode(generator.ignoredResult(), m_init); + RegisterID* forInBase = generator.emitNode(m_expr); RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase); generator.emitJump(scope->continueTarget()); @@ -1912,7 +1427,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RegisterID* propertyName; if (m_lexpr->isResolveNode()) { - const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier(); + const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier(); propertyName = generator.registerFor(ident); if (!propertyName) { propertyName = generator.newTemporary(); @@ -1923,7 +1438,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds generator.emitPutById(base, ident, propertyName); } } else if (m_lexpr->isDotAccessorNode()) { - DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get()); + DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr); const Identifier& ident = assignNode->identifier(); propertyName = generator.newTemporary(); RefPtr<RegisterID> protect = propertyName; @@ -1933,7 +1448,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds generator.emitPutById(base, ident, propertyName); } else { ASSERT(m_lexpr->isBracketAccessorNode()); - BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr.get()); + BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr); propertyName = generator.newTemporary(); RefPtr<RegisterID> protect = propertyName; RefPtr<RegisterID> base = generator.emitNode(assignNode->base()); @@ -1943,7 +1458,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds generator.emitPutByVal(base.get(), subscript, propertyName); } - generator.emitNode(dst, m_statement.get()); + generator.emitNode(dst, m_statement); generator.emitLabel(scope->continueTarget()); generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get()); @@ -1990,16 +1505,6 @@ RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds // ------------------------------ ReturnNode ----------------------------------- -ReturnNode::~ReturnNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ReturnNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_value); -} - RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); @@ -2008,7 +1513,7 @@ RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d if (dst == generator.ignoredResult()) dst = 0; - RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(dst, jsUndefined()); + RegisterID* r0 = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined()); RefPtr<RegisterID> returnRegister; if (generator.scopeDepth()) { RefPtr<Label> l0 = generator.newLabel(); @@ -2025,69 +1530,21 @@ RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d // ------------------------------ WithNode ------------------------------------- -WithNode::~WithNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void WithNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); - releaser.release(m_statement); -} - RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); RefPtr<RegisterID> scope = generator.newTemporary(); - generator.emitNode(scope.get(), m_expr.get()); // scope must be protected until popped + generator.emitNode(scope.get(), m_expr); // scope must be protected until popped generator.emitExpressionInfo(m_divot, m_expressionLength, 0); generator.emitPushScope(scope.get()); - RegisterID* result = generator.emitNode(dst, m_statement.get()); + RegisterID* result = generator.emitNode(dst, m_statement); generator.emitPopScope(); return result; } -// ------------------------------ CaseClauseNode -------------------------------- - -CaseClauseNode::~CaseClauseNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void CaseClauseNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - -// ------------------------------ ClauseListNode -------------------------------- - -ClauseListNode::~ClauseListNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ClauseListNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_clause); - releaser.release(m_next); -} - // ------------------------------ CaseBlockNode -------------------------------- -CaseBlockNode::~CaseBlockNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void CaseBlockNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_list1); - releaser.release(m_defaultClause); - releaser.release(m_list2); -} - enum SwitchKind { SwitchUnset = 0, SwitchNumber = 1, @@ -2102,7 +1559,7 @@ static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector.append(clauseExpression); if (clauseExpression->isNumber()) { double value = static_cast<NumberNode*>(clauseExpression)->value(); - JSValuePtr jsValue = JSValuePtr::makeInt32Fast(static_cast<int32_t>(value)); + JSValue jsValue = JSValue::makeInt32Fast(static_cast<int32_t>(value)); if ((typeForTable & ~SwitchNumber) || !jsValue || (jsValue.getInt32Fast() != value)) { typeForTable = SwitchNeither; break; @@ -2142,8 +1599,8 @@ SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, SwitchKind typeForTable = SwitchUnset; bool singleCharacterSwitch = true; - processClauseList(m_list1.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); - processClauseList(m_list2.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); + processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); + processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); if (typeForTable == SwitchUnset || typeForTable == SwitchNeither) return SwitchInfo::SwitchNone; @@ -2183,7 +1640,7 @@ RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, Re generator.beginSwitch(switchExpression, switchType); } else { // Setup jumps - for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) { + for (ClauseListNode* list = m_list1; list; list = list->getNext()) { RefPtr<RegisterID> clauseVal = generator.newTemporary(); generator.emitNode(clauseVal.get(), list->getClause()->expr()); generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes()); @@ -2191,7 +1648,7 @@ RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, Re generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get()); } - for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) { + for (ClauseListNode* list = m_list2; list; list = list->getNext()) { RefPtr<RegisterID> clauseVal = generator.newTemporary(); generator.emitNode(clauseVal.get(), list->getClause()->expr()); generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes()); @@ -2205,19 +1662,19 @@ RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, Re RegisterID* result = 0; size_t i = 0; - for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) { + for (ClauseListNode* list = m_list1; list; list = list->getNext()) { generator.emitLabel(labelVector[i++].get()); - result = statementListEmitCode(list->getClause()->children(), generator, dst); + statementListEmitCode(list->getClause()->children(), generator, dst); } if (m_defaultClause) { generator.emitLabel(defaultLabel.get()); - result = statementListEmitCode(m_defaultClause->children(), generator, dst); + statementListEmitCode(m_defaultClause->children(), generator, dst); } - for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) { + for (ClauseListNode* list = m_list2; list; list = list->getNext()) { generator.emitLabel(labelVector[i++].get()); - result = statementListEmitCode(list->getClause()->children(), generator, dst); + statementListEmitCode(list->getClause()->children(), generator, dst); } if (!m_defaultClause) generator.emitLabel(defaultLabel.get()); @@ -2232,24 +1689,13 @@ RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, Re // ------------------------------ SwitchNode ----------------------------------- -SwitchNode::~SwitchNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void SwitchNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); - releaser.release(m_block); -} - RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch); - RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get()); + RefPtr<RegisterID> r0 = generator.emitNode(m_expr); RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst); generator.emitLabel(scope->breakTarget()); @@ -2258,16 +1704,6 @@ RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d // ------------------------------ LabelNode ------------------------------------ -LabelNode::~LabelNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void LabelNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_statement); -} - RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); @@ -2276,7 +1712,7 @@ RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name); RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name); - RegisterID* r0 = generator.emitNode(dst, m_statement.get()); + RegisterID* r0 = generator.emitNode(dst, m_statement); generator.emitLabel(scope->breakTarget()); return r0; @@ -2284,23 +1720,13 @@ RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds // ------------------------------ ThrowNode ------------------------------------ -ThrowNode::~ThrowNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ThrowNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_expr); -} - RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); if (dst == generator.ignoredResult()) dst = 0; - RefPtr<RegisterID> expr = generator.emitNode(m_expr.get()); + RefPtr<RegisterID> expr = generator.emitNode(m_expr); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitThrow(expr.get()); return 0; @@ -2308,18 +1734,6 @@ RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds // ------------------------------ TryNode -------------------------------------- -TryNode::~TryNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void TryNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_tryBlock); - releaser.release(m_catchBlock); - releaser.release(m_finallyBlock); -} - RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); @@ -2334,7 +1748,7 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get()); } generator.emitLabel(tryStartLabel.get()); - generator.emitNode(dst, m_tryBlock.get()); + generator.emitNode(dst, m_tryBlock); generator.emitLabel(tryEndLabel.get()); if (m_catchBlock) { @@ -2348,7 +1762,7 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) generator.emitPushScope(exceptionRegister.get()); } else generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get()); - generator.emitNode(dst, m_catchBlock.get()); + generator.emitNode(dst, m_catchBlock); generator.emitPopScope(); generator.emitLabel(handlerEndLabel.get()); } @@ -2377,7 +1791,7 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) // emit the finally block itself generator.emitLabel(finallyStart.get()); - generator.emitNode(dst, m_finallyBlock.get()); + generator.emitNode(dst, m_finallyBlock); generator.emitSubroutineReturn(finallyReturnAddr.get()); generator.emitLabel(finallyEndLabel.get()); @@ -2386,27 +1800,16 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) return dst; } -// ------------------------------ ParameterNode ----------------------------- - -ParameterNode::~ParameterNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ParameterNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_next); -} - // -----------------------------ScopeNodeData --------------------------- -ScopeNodeData::ScopeNodeData(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, int numConstants) +ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, int numConstants) : m_numConstants(numConstants) { + m_arena.swap(arena); if (varStack) - m_varStack = *varStack; + m_varStack.swap(*varStack); if (funcStack) - m_functionStack = *funcStack; + m_functionStack.swap(*funcStack); if (children) children->releaseContentsIntoVector(m_children); } @@ -2426,48 +1829,44 @@ void ScopeNodeData::mark() ScopeNode::ScopeNode(JSGlobalData* globalData) : StatementNode(globalData) + , ParserArenaRefCounted(globalData) , m_features(NoFeatures) { -#if ENABLE(OPCODE_SAMPLING) - globalData->interpreter->sampler()->notifyOfScope(this); +#if ENABLE(CODEBLOCK_SAMPLING) + if (SamplingTool* sampler = globalData->interpreter->sampler()) + sampler->notifyOfScope(this); #endif } ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants) : StatementNode(globalData) - , m_data(new ScopeNodeData(children, varStack, funcStack, numConstants)) + , ParserArenaRefCounted(globalData) + , m_data(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, numConstants)) , m_features(features) , m_source(source) { -#if ENABLE(OPCODE_SAMPLING) - globalData->interpreter->sampler()->notifyOfScope(this); +#if ENABLE(CODEBLOCK_SAMPLING) + if (SamplingTool* sampler = globalData->interpreter->sampler()) + sampler->notifyOfScope(this); #endif } -ScopeNode::~ScopeNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void ScopeNode::releaseNodes(NodeReleaser& releaser) -{ - if (!m_data) - return; - size_t size = m_data->m_children.size(); - for (size_t i = 0; i < size; ++i) - releaser.release(m_data->m_children[i]); -} - // ------------------------------ ProgramNode ----------------------------- -ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) +inline ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants) { } -ProgramNode* ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) +PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) { - return new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants); + RefPtr<ProgramNode> node = new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants); + + ASSERT(node->data()->m_arena.last() == node); + node->data()->m_arena.removeLast(); + ASSERT(!node->data()->m_arena.contains(node.get())); + + return node.release(); } RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) @@ -2496,16 +1895,33 @@ void ProgramNode::generateBytecode(ScopeChainNode* scopeChainNode) destroyData(); } +#if ENABLE(JIT) +void ProgramNode::generateJITCode(ScopeChainNode* scopeChainNode) +{ + bytecode(scopeChainNode); + ASSERT(m_code); + ASSERT(!m_jitCode); + JIT::compile(scopeChainNode->globalData, m_code.get()); + ASSERT(m_jitCode); +} +#endif + // ------------------------------ EvalNode ----------------------------- -EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) +inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants) { } -EvalNode* EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) +PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) { - return new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants); + RefPtr<EvalNode> node = new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants); + + ASSERT(node->data()->m_arena.last() == node); + node->data()->m_arena.removeLast(); + ASSERT(!node->data()->m_arena.contains(node.get())); + + return node.release(); } RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) @@ -2558,27 +1974,35 @@ void EvalNode::mark() data()->mark(); } +#if ENABLE(JIT) +void EvalNode::generateJITCode(ScopeChainNode* scopeChainNode) +{ + bytecode(scopeChainNode); + ASSERT(m_code); + ASSERT(!m_jitCode); + JIT::compile(scopeChainNode->globalData, m_code.get()); + ASSERT(m_jitCode); +} +#endif + // ------------------------------ FunctionBodyNode ----------------------------- -FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData) +inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData) : ScopeNode(globalData) , m_parameters(0) , m_parameterCount(0) - , m_refCount(0) { } -FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants) +inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants) : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants) , m_parameters(0) , m_parameterCount(0) - , m_refCount(0) { } FunctionBodyNode::~FunctionBodyNode() { - ASSERT(!m_refCount); for (size_t i = 0; i < m_parameterCount; ++i) m_parameters[i].~Identifier(); fastFree(m_parameters); @@ -2608,14 +2032,30 @@ void FunctionBodyNode::mark() m_code->mark(); } +#if ENABLE(JIT) +PassRefPtr<FunctionBodyNode> FunctionBodyNode::createNativeThunk(JSGlobalData* globalData) +{ + RefPtr<FunctionBodyNode> body = new FunctionBodyNode(globalData); + globalData->parser->arena().reset(); + body->m_jitCode = JITCode(JITCode::HostFunction(globalData->jitStubs.ctiNativeCallThunk())); + return body.release(); +} +#endif + FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData) { return new FunctionBodyNode(globalData); } -FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants) +PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants) { - return new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants); + RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants); + + ASSERT(node->data()->m_arena.last() == node); + node->data()->m_arena.removeLast(); + ASSERT(!node->data()->m_arena.contains(node.get())); + + return node.release(); } void FunctionBodyNode::generateBytecode(ScopeChainNode* scopeChainNode) @@ -2637,6 +2077,17 @@ void FunctionBodyNode::generateBytecode(ScopeChainNode* scopeChainNode) destroyData(); } +#if ENABLE(JIT) +void FunctionBodyNode::generateJITCode(ScopeChainNode* scopeChainNode) +{ + bytecode(scopeChainNode); + ASSERT(m_code); + ASSERT(!m_jitCode); + JIT::compile(scopeChainNode->globalData, m_code.get()); + ASSERT(m_jitCode); +} +#endif + CodeBlock& FunctionBodyNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom) { ASSERT(!m_code); @@ -2658,7 +2109,7 @@ RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, Registe generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine()); statementListEmitCode(children(), generator, generator.ignoredResult()); if (children().size() && children().last()->isBlock()) { - BlockNode* blockNode = static_cast<BlockNode*>(children().last().get()); + BlockNode* blockNode = static_cast<BlockNode*>(children().last()); if (blockNode->children().size() && blockNode->children().last()->isReturnNode()) return 0; } @@ -2690,17 +2141,6 @@ Identifier* FunctionBodyNode::copyParameters() // ------------------------------ FuncDeclNode --------------------------------- -FuncDeclNode::~FuncDeclNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void FuncDeclNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_parameter); - releaser.release(m_body); -} - JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain) { return new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain); @@ -2715,17 +2155,6 @@ RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* // ------------------------------ FuncExprNode --------------------------------- -FuncExprNode::~FuncExprNode() -{ - NodeReleaser::releaseAllNodes(this); -} - -void FuncExprNode::releaseNodes(NodeReleaser& releaser) -{ - releaser.release(m_parameter); - releaser.release(m_body); -} - RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { return generator.emitNewFunctionExpression(generator.finalDestination(dst), this); diff --git a/JavaScriptCore/parser/Nodes.h b/JavaScriptCore/parser/Nodes.h index f209133..ec4fdb4 100644 --- a/JavaScriptCore/parser/Nodes.h +++ b/JavaScriptCore/parser/Nodes.h @@ -23,34 +23,30 @@ * */ -#ifndef NODES_H_ -#define NODES_H_ +#ifndef Nodes_h +#define Nodes_h #include "Error.h" +#include "JITCode.h" #include "Opcode.h" +#include "ParserArena.h" #include "ResultType.h" #include "SourceCode.h" #include "SymbolTable.h" #include <wtf/MathExtras.h> #include <wtf/OwnPtr.h> -#include <wtf/Vector.h> - -#if PLATFORM(X86) && COMPILER(GCC) -#define JSC_FAST_CALL __attribute__((regparm(3))) -#else -#define JSC_FAST_CALL -#endif namespace JSC { + class ArgumentListNode; class CodeBlock; class BytecodeGenerator; class FuncDeclNode; class EvalCodeBlock; class JSFunction; - class NodeReleaser; class ProgramCodeBlock; class PropertyListNode; + class ReadModifyResolveNode; class RegisterID; class ScopeChainNode; @@ -91,7 +87,7 @@ namespace JSC { namespace DeclarationStacks { enum VarAttrs { IsConstant = 1, HasInitializer = 2 }; typedef Vector<std::pair<Identifier, unsigned> > VarStack; - typedef Vector<RefPtr<FuncDeclNode> > FunctionStack; + typedef Vector<FuncDeclNode*> FunctionStack; } struct SwitchInfo { @@ -100,30 +96,37 @@ namespace JSC { SwitchType switchType; }; - class ParserRefCounted : Noncopyable { + class ParserArenaDeletable { protected: - ParserRefCounted(JSGlobalData*) JSC_FAST_CALL; + ParserArenaDeletable() { } public: - virtual ~ParserRefCounted(); + virtual ~ParserArenaDeletable() { } - // Nonrecursive destruction. - virtual void releaseNodes(NodeReleaser&); + // Objects created with this version of new are deleted when the arena is deleted. + void* operator new(size_t, JSGlobalData*); - void ref() JSC_FAST_CALL; - void deref() JSC_FAST_CALL; - bool hasOneRef() JSC_FAST_CALL; + // Objects created with this version of new are not deleted when the arena is deleted. + // Other arrangements must be made. + void* operator new(size_t); + }; - static void deleteNewObjects(JSGlobalData*) JSC_FAST_CALL; + class ParserArenaRefCounted : public RefCounted<ParserArenaRefCounted> { + protected: + ParserArenaRefCounted(JSGlobalData*); - private: - JSGlobalData* m_globalData; + public: + virtual ~ParserArenaRefCounted() + { + ASSERT(deletionHasBegun()); + } }; - class Node : public ParserRefCounted { - public: - Node(JSGlobalData*) JSC_FAST_CALL; + class Node : public ParserArenaDeletable { + protected: + Node(JSGlobalData*); + public: /* Return value: The register holding the production's value. dst: An optional parameter specifying the most efficient @@ -146,7 +149,7 @@ namespace JSC { because the assignment node, "x =", passes r[x] as dst to the number node, "1". */ - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL = 0; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) = 0; int lineNo() const { return m_line; } @@ -166,45 +169,44 @@ namespace JSC { class ExpressionNode : public Node { public: - ExpressionNode(JSGlobalData* globalData, ResultType resultDesc = ResultType::unknownType()) JSC_FAST_CALL - : Node(globalData) - , m_resultDesc(resultDesc) - { - } + ExpressionNode(JSGlobalData*, ResultType = ResultType::unknownType()); - virtual bool isNumber() const JSC_FAST_CALL { return false; } - virtual bool isString() const JSC_FAST_CALL { return false; } - virtual bool isNull() const JSC_FAST_CALL { return false; } - virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return false; } - virtual bool isLocation() const JSC_FAST_CALL { return false; } - virtual bool isResolveNode() const JSC_FAST_CALL { return false; } - virtual bool isBracketAccessorNode() const JSC_FAST_CALL { return false; } - virtual bool isDotAccessorNode() const JSC_FAST_CALL { return false; } - virtual bool isFuncExprNode() const JSC_FAST_CALL { return false; } + virtual bool isNumber() const { return false; } + virtual bool isString() const { return false; } + virtual bool isNull() const { return false; } + virtual bool isPure(BytecodeGenerator&) const { return false; } + virtual bool isLocation() const { return false; } + virtual bool isResolveNode() const { return false; } + virtual bool isBracketAccessorNode() const { return false; } + virtual bool isDotAccessorNode() const { return false; } + virtual bool isFuncExprNode() const { return false; } + virtual bool isSimpleArray() const { return false; } + virtual bool isAdd() const { return false; } virtual ExpressionNode* stripUnaryPlus() { return this; } - ResultType resultDescriptor() const JSC_FAST_CALL { return m_resultDesc; } + ResultType resultDescriptor() const { return m_resultType; } // This needs to be in public in order to compile using GCC 3.x typedef enum { EvalOperator, FunctionCall } CallerType; private: - ResultType m_resultDesc; + ResultType m_resultType; }; class StatementNode : public Node { public: - StatementNode(JSGlobalData*) JSC_FAST_CALL; - void setLoc(int line0, int line1) JSC_FAST_CALL; - int firstLine() const JSC_FAST_CALL { return lineNo(); } - int lastLine() const JSC_FAST_CALL { return m_lastLine; } + StatementNode(JSGlobalData*); - virtual bool isEmptyStatement() const JSC_FAST_CALL { return false; } - virtual bool isReturnNode() const JSC_FAST_CALL { return false; } - virtual bool isExprStatement() const JSC_FAST_CALL { return false; } + void setLoc(int line0, int line1); + int firstLine() const { return lineNo(); } + int lastLine() const { return m_lastLine; } - virtual bool isBlock() const JSC_FAST_CALL { return false; } + virtual bool isEmptyStatement() const { return false; } + virtual bool isReturnNode() const { return false; } + virtual bool isExprStatement() const { return false; } + + virtual bool isBlock() const { return false; } private: int m_lastLine; @@ -212,66 +214,54 @@ namespace JSC { class NullNode : public ExpressionNode { public: - NullNode(JSGlobalData* globalData) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::nullType()) - { - } + NullNode(JSGlobalData*); - virtual bool isNull() const JSC_FAST_CALL { return true; } + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual bool isNull() const { return true; } }; class BooleanNode : public ExpressionNode { public: - BooleanNode(JSGlobalData* globalData, bool value) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::booleanType()) - , m_value(value) - { - } + BooleanNode(JSGlobalData*, bool value); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; } + virtual bool isPure(BytecodeGenerator&) const { return true; } - private: bool m_value; }; class NumberNode : public ExpressionNode { public: - NumberNode(JSGlobalData* globalData, double v) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::numberType()) - , m_double(v) - { - } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + NumberNode(JSGlobalData*, double v); - virtual bool isNumber() const JSC_FAST_CALL { return true; } - virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; } - double value() const JSC_FAST_CALL { return m_double; } - void setValue(double d) JSC_FAST_CALL { m_double = d; } + double value() const { return m_double; } + void setValue(double d) { m_double = d; } private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isNumber() const { return true; } + virtual bool isPure(BytecodeGenerator&) const { return true; } + double m_double; }; class StringNode : public ExpressionNode { public: - StringNode(JSGlobalData* globalData, const Identifier& v) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::stringType()) - , m_value(v) - { - } + StringNode(JSGlobalData*, const Identifier& v); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - virtual bool isString() const JSC_FAST_CALL { return true; } const Identifier& value() { return m_value; } - virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL { return true; } + virtual bool isPure(BytecodeGenerator&) const { return true; } private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isString() const { return true; } + Identifier m_value; }; @@ -374,1158 +364,682 @@ namespace JSC { class RegExpNode : public ExpressionNode, public ThrowableExpressionData { public: - RegExpNode(JSGlobalData* globalData, const UString& pattern, const UString& flags) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_pattern(pattern) - , m_flags(flags) - { - } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + RegExpNode(JSGlobalData*, const UString& pattern, const UString& flags); private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + UString m_pattern; UString m_flags; }; class ThisNode : public ExpressionNode { public: - ThisNode(JSGlobalData* globalData) JSC_FAST_CALL - : ExpressionNode(globalData) - { - } + ThisNode(JSGlobalData*); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; class ResolveNode : public ExpressionNode { public: - ResolveNode(JSGlobalData* globalData, const Identifier& ident, int startOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_ident(ident) - , m_startOffset(startOffset) - { - } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ResolveNode(JSGlobalData*, const Identifier&, int startOffset); - virtual bool isPure(BytecodeGenerator&) const JSC_FAST_CALL; - virtual bool isLocation() const JSC_FAST_CALL { return true; } - virtual bool isResolveNode() const JSC_FAST_CALL { return true; } - const Identifier& identifier() const JSC_FAST_CALL { return m_ident; } + const Identifier& identifier() const { return m_ident; } private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isPure(BytecodeGenerator&) const ; + virtual bool isLocation() const { return true; } + virtual bool isResolveNode() const { return true; } + Identifier m_ident; int32_t m_startOffset; }; - class ElementNode : public ParserRefCounted { + class ElementNode : public ParserArenaDeletable { public: - ElementNode(JSGlobalData* globalData, int elision, ExpressionNode* node) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_elision(elision) - , m_node(node) - { - } - - ElementNode(JSGlobalData* globalData, ElementNode* l, int elision, ExpressionNode* node) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_elision(elision) - , m_node(node) - { - l->m_next = this; - } - - virtual ~ElementNode(); - virtual void releaseNodes(NodeReleaser&); + ElementNode(JSGlobalData*, int elision, ExpressionNode*); + ElementNode(JSGlobalData*, ElementNode*, int elision, ExpressionNode*); int elision() const { return m_elision; } - ExpressionNode* value() { return m_node.get(); } - - ElementNode* next() { return m_next.get(); } + ExpressionNode* value() { return m_node; } + ElementNode* next() { return m_next; } private: - RefPtr<ElementNode> m_next; + ElementNode* m_next; int m_elision; - RefPtr<ExpressionNode> m_node; + ExpressionNode* m_node; }; class ArrayNode : public ExpressionNode { public: - ArrayNode(JSGlobalData* globalData, int elision) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_elision(elision) - , m_optional(true) - { - } + ArrayNode(JSGlobalData*, int elision); + ArrayNode(JSGlobalData*, ElementNode*); + ArrayNode(JSGlobalData*, int elision, ElementNode*); - ArrayNode(JSGlobalData* globalData, ElementNode* element) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_element(element) - , m_elision(0) - , m_optional(false) - { - } - - ArrayNode(JSGlobalData* globalData, int elision, ElementNode* element) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_element(element) - , m_elision(elision) - , m_optional(true) - { - } + ArgumentListNode* toArgumentList(JSGlobalData*) const; - virtual ~ArrayNode(); - virtual void releaseNodes(NodeReleaser&); + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual bool isSimpleArray() const ; - private: - RefPtr<ElementNode> m_element; + ElementNode* m_element; int m_elision; bool m_optional; }; - class PropertyNode : public ParserRefCounted { + class PropertyNode : public ParserArenaDeletable { public: enum Type { Constant, Getter, Setter }; - PropertyNode(JSGlobalData* globalData, const Identifier& name, ExpressionNode* assign, Type type) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_name(name) - , m_assign(assign) - , m_type(type) - { - } - - virtual ~PropertyNode(); - virtual void releaseNodes(NodeReleaser&); + PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* value, Type); const Identifier& name() const { return m_name; } private: friend class PropertyListNode; Identifier m_name; - RefPtr<ExpressionNode> m_assign; + ExpressionNode* m_assign; Type m_type; }; class PropertyListNode : public Node { public: - PropertyListNode(JSGlobalData* globalData, PropertyNode* node) JSC_FAST_CALL - : Node(globalData) - , m_node(node) - { - } - - PropertyListNode(JSGlobalData* globalData, PropertyNode* node, PropertyListNode* list) JSC_FAST_CALL - : Node(globalData) - , m_node(node) - { - list->m_next = this; - } + PropertyListNode(JSGlobalData*, PropertyNode*); + PropertyListNode(JSGlobalData*, PropertyNode*, PropertyListNode*); - virtual ~PropertyListNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); private: - RefPtr<PropertyNode> m_node; - RefPtr<PropertyListNode> m_next; + PropertyNode* m_node; + PropertyListNode* m_next; }; class ObjectLiteralNode : public ExpressionNode { public: - ObjectLiteralNode(JSGlobalData* globalData) JSC_FAST_CALL - : ExpressionNode(globalData) - { - } - - ObjectLiteralNode(JSGlobalData* globalData, PropertyListNode* list) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_list(list) - { - } - - virtual ~ObjectLiteralNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ObjectLiteralNode(JSGlobalData*); + ObjectLiteralNode(JSGlobalData*, PropertyListNode*); private: - RefPtr<PropertyListNode> m_list; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + PropertyListNode* m_list; }; class BracketAccessorNode : public ExpressionNode, public ThrowableExpressionData { public: - BracketAccessorNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_base(base) - , m_subscript(subscript) - , m_subscriptHasAssignments(subscriptHasAssignments) - { - } + BracketAccessorNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments); - virtual ~BracketAccessorNode(); - virtual void releaseNodes(NodeReleaser&); + ExpressionNode* base() const { return m_base; } + ExpressionNode* subscript() const { return m_subscript; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - virtual bool isLocation() const JSC_FAST_CALL { return true; } - virtual bool isBracketAccessorNode() const JSC_FAST_CALL { return true; } - ExpressionNode* base() JSC_FAST_CALL { return m_base.get(); } - ExpressionNode* subscript() JSC_FAST_CALL { return m_subscript.get(); } + virtual bool isLocation() const { return true; } + virtual bool isBracketAccessorNode() const { return true; } - private: - RefPtr<ExpressionNode> m_base; - RefPtr<ExpressionNode> m_subscript; + ExpressionNode* m_base; + ExpressionNode* m_subscript; bool m_subscriptHasAssignments; }; class DotAccessorNode : public ExpressionNode, public ThrowableExpressionData { public: - DotAccessorNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_base(base) - , m_ident(ident) - { - } + DotAccessorNode(JSGlobalData*, ExpressionNode* base, const Identifier&); - virtual ~DotAccessorNode(); - virtual void releaseNodes(NodeReleaser&); + ExpressionNode* base() const { return m_base; } + const Identifier& identifier() const { return m_ident; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - virtual bool isLocation() const JSC_FAST_CALL { return true; } - virtual bool isDotAccessorNode() const JSC_FAST_CALL { return true; } - ExpressionNode* base() const JSC_FAST_CALL { return m_base.get(); } - const Identifier& identifier() const JSC_FAST_CALL { return m_ident; } + virtual bool isLocation() const { return true; } + virtual bool isDotAccessorNode() const { return true; } - private: - RefPtr<ExpressionNode> m_base; + ExpressionNode* m_base; Identifier m_ident; }; class ArgumentListNode : public Node { public: - ArgumentListNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : Node(globalData) - , m_expr(expr) - { - } - - ArgumentListNode(JSGlobalData* globalData, ArgumentListNode* listNode, ExpressionNode* expr) JSC_FAST_CALL - : Node(globalData) - , m_expr(expr) - { - listNode->m_next = this; - } - - virtual ~ArgumentListNode(); - virtual void releaseNodes(NodeReleaser&); + ArgumentListNode(JSGlobalData*, ExpressionNode*); + ArgumentListNode(JSGlobalData*, ArgumentListNode*, ExpressionNode*); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ArgumentListNode* m_next; + ExpressionNode* m_expr; - RefPtr<ArgumentListNode> m_next; - RefPtr<ExpressionNode> m_expr; + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; - class ArgumentsNode : public ParserRefCounted { + class ArgumentsNode : public ParserArenaDeletable { public: - ArgumentsNode(JSGlobalData* globalData) JSC_FAST_CALL - : ParserRefCounted(globalData) - { - } - - ArgumentsNode(JSGlobalData* globalData, ArgumentListNode* listNode) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_listNode(listNode) - { - } + ArgumentsNode(JSGlobalData*); + ArgumentsNode(JSGlobalData*, ArgumentListNode*); - virtual ~ArgumentsNode(); - virtual void releaseNodes(NodeReleaser&); - - RefPtr<ArgumentListNode> m_listNode; + ArgumentListNode* m_listNode; }; class NewExprNode : public ExpressionNode, public ThrowableExpressionData { public: - NewExprNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_expr(expr) - { - } - - NewExprNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_expr(expr) - , m_args(args) - { - } - - virtual ~NewExprNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + NewExprNode(JSGlobalData*, ExpressionNode*); + NewExprNode(JSGlobalData*, ExpressionNode*, ArgumentsNode*); private: - RefPtr<ExpressionNode> m_expr; - RefPtr<ArgumentsNode> m_args; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + ArgumentsNode* m_args; }; class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData { public: - EvalFunctionCallNode(JSGlobalData* globalData, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_args(args) - { - } - - virtual ~EvalFunctionCallNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + EvalFunctionCallNode(JSGlobalData*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ArgumentsNode> m_args; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ArgumentsNode* m_args; }; class FunctionCallValueNode : public ExpressionNode, public ThrowableExpressionData { public: - FunctionCallValueNode(JSGlobalData* globalData, ExpressionNode* expr, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_expr(expr) - , m_args(args) - { - } - - virtual ~FunctionCallValueNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + FunctionCallValueNode(JSGlobalData*, ExpressionNode*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_expr; - RefPtr<ArgumentsNode> m_args; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + ArgumentsNode* m_args; }; class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - FunctionCallResolveNode(JSGlobalData* globalData, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_ident(ident) - , m_args(args) - { - } - - virtual ~FunctionCallResolveNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + FunctionCallResolveNode(JSGlobalData*, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + Identifier m_ident; - RefPtr<ArgumentsNode> m_args; + ArgumentsNode* m_args; size_t m_index; // Used by LocalVarFunctionCallNode. size_t m_scopeDepth; // Used by ScopedVarFunctionCallNode and NonLocalVarFunctionCallNode }; class FunctionCallBracketNode : public ExpressionNode, public ThrowableSubExpressionData { public: - FunctionCallBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_subscript(subscript) - , m_args(args) - { - } - - virtual ~FunctionCallBracketNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + FunctionCallBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_base; - RefPtr<ExpressionNode> m_subscript; - RefPtr<ArgumentsNode> m_args; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + ArgumentsNode* m_args; }; class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData { public: - FunctionCallDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_ident(ident) - , m_args(args) - { - } + FunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); - virtual ~FunctionCallDotNode(); - virtual void releaseNodes(NodeReleaser&); + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + protected: + ExpressionNode* m_base; + const Identifier m_ident; + ArgumentsNode* m_args; + }; + + class CallFunctionCallDotNode : public FunctionCallDotNode { + public: + CallFunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_base; - Identifier m_ident; - RefPtr<ArgumentsNode> m_args; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class ApplyFunctionCallDotNode : public FunctionCallDotNode { + public: + ApplyFunctionCallDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; class PrePostResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - PrePostResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::numberType()) // could be reusable for pre? - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_ident(ident) - { - } + PrePostResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); protected: - Identifier m_ident; + const Identifier m_ident; }; class PostfixResolveNode : public PrePostResolveNode { public: - PostfixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset) - , m_operator(oper) - { - } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + PostfixResolveNode(JSGlobalData*, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + Operator m_operator; }; class PostfixBracketNode : public ExpressionNode, public ThrowableSubExpressionData { public: - PostfixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_subscript(subscript) - , m_operator(oper) - { - } - - virtual ~PostfixBracketNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + PostfixBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_base; - RefPtr<ExpressionNode> m_subscript; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; Operator m_operator; }; class PostfixDotNode : public ExpressionNode, public ThrowableSubExpressionData { public: - PostfixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_ident(ident) - , m_operator(oper) - { - } - - virtual ~PostfixDotNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + PostfixDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_base; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; Identifier m_ident; Operator m_operator; }; class PostfixErrorNode : public ExpressionNode, public ThrowableSubExpressionData { public: - PostfixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableSubExpressionData(divot, startOffset, endOffset) - , m_expr(expr) - , m_operator(oper) - { - } - - virtual ~PostfixErrorNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + PostfixErrorNode(JSGlobalData*, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_expr; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; Operator m_operator; }; class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteResolveNode(JSGlobalData* globalData, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_ident(ident) - { - } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + DeleteResolveNode(JSGlobalData*, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + Identifier m_ident; }; class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_subscript(subscript) - { - } - - virtual ~DeleteBracketNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + DeleteBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_base; - RefPtr<ExpressionNode> m_subscript; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; }; class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_ident(ident) - { - } - - virtual ~DeleteDotNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + DeleteDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_base; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; Identifier m_ident; }; class DeleteValueNode : public ExpressionNode { public: - DeleteValueNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_expr(expr) - { - } - - virtual ~DeleteValueNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + DeleteValueNode(JSGlobalData*, ExpressionNode*); private: - RefPtr<ExpressionNode> m_expr; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; }; class VoidNode : public ExpressionNode { public: - VoidNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_expr(expr) - { - } - - virtual ~VoidNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + VoidNode(JSGlobalData*, ExpressionNode*); private: - RefPtr<ExpressionNode> m_expr; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; }; class TypeOfResolveNode : public ExpressionNode { public: - TypeOfResolveNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::stringType()) - , m_ident(ident) - { - } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + TypeOfResolveNode(JSGlobalData*, const Identifier&); - const Identifier& identifier() const JSC_FAST_CALL { return m_ident; } + const Identifier& identifier() const { return m_ident; } private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + Identifier m_ident; }; class TypeOfValueNode : public ExpressionNode { public: - TypeOfValueNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::stringType()) - , m_expr(expr) - { - } - - virtual ~TypeOfValueNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + TypeOfValueNode(JSGlobalData*, ExpressionNode*); private: - RefPtr<ExpressionNode> m_expr; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; }; class PrefixResolveNode : public PrePostResolveNode { public: - PrefixResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : PrePostResolveNode(globalData, ident, divot, startOffset, endOffset) - , m_operator(oper) - { - } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + PrefixResolveNode(JSGlobalData*, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + Operator m_operator; }; class PrefixBracketNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { public: - PrefixBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_subscript(subscript) - , m_operator(oper) - { - } - - virtual ~PrefixBracketNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + PrefixBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_base; - RefPtr<ExpressionNode> m_subscript; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; Operator m_operator; }; class PrefixDotNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { public: - PrefixDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_ident(ident) - , m_operator(oper) - { - } - - virtual ~PrefixDotNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + PrefixDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_base; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; Identifier m_ident; Operator m_operator; }; class PrefixErrorNode : public ExpressionNode, public ThrowableExpressionData { public: - PrefixErrorNode(JSGlobalData* globalData, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_expr(expr) - , m_operator(oper) - { - } - - virtual ~PrefixErrorNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + PrefixErrorNode(JSGlobalData*, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_expr; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; Operator m_operator; }; class UnaryOpNode : public ExpressionNode { public: - UnaryOpNode(JSGlobalData* globalData, ExpressionNode* expr) - : ExpressionNode(globalData) - , m_expr(expr) - { - } + UnaryOpNode(JSGlobalData*, ResultType, ExpressionNode*, OpcodeID); - UnaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr) - : ExpressionNode(globalData, type) - , m_expr(expr) - { - } + protected: + ExpressionNode* expr() { return m_expr; } - virtual ~UnaryOpNode(); - virtual void releaseNodes(NodeReleaser&); + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual OpcodeID opcodeID() const JSC_FAST_CALL = 0; + OpcodeID opcodeID() const { return m_opcodeID; } - protected: - RefPtr<ExpressionNode> m_expr; + ExpressionNode* m_expr; + OpcodeID m_opcodeID; }; class UnaryPlusNode : public UnaryOpNode { public: - UnaryPlusNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : UnaryOpNode(globalData, ResultType::numberType(), expr) - { - } - - virtual ExpressionNode* stripUnaryPlus() { return m_expr.get(); } + UnaryPlusNode(JSGlobalData*, ExpressionNode*); - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_to_jsnumber; } + private: + virtual ExpressionNode* stripUnaryPlus() { return expr(); } }; class NegateNode : public UnaryOpNode { public: - NegateNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : UnaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_negate; } + NegateNode(JSGlobalData*, ExpressionNode*); }; class BitwiseNotNode : public UnaryOpNode { public: - BitwiseNotNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : UnaryOpNode(globalData, ResultType::forBitOp(), expr) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitnot; } + BitwiseNotNode(JSGlobalData*, ExpressionNode*); }; class LogicalNotNode : public UnaryOpNode { public: - LogicalNotNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : UnaryOpNode(globalData, ResultType::booleanType(), expr) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_not; } + LogicalNotNode(JSGlobalData*, ExpressionNode*); }; class BinaryOpNode : public ExpressionNode { public: - BinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : ExpressionNode(globalData) - , m_expr1(expr1) - , m_expr2(expr2) - , m_rightHasAssignments(rightHasAssignments) - { - } + BinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + BinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); - BinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : ExpressionNode(globalData, type) - , m_expr1(expr1) - , m_expr2(expr2) - , m_rightHasAssignments(rightHasAssignments) - { - } + RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0); - virtual ~BinaryOpNode(); - virtual void releaseNodes(NodeReleaser&); + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual OpcodeID opcodeID() const JSC_FAST_CALL = 0; + protected: + OpcodeID opcodeID() const { return m_opcodeID; } protected: - RefPtr<ExpressionNode> m_expr1; - RefPtr<ExpressionNode> m_expr2; + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; + private: + OpcodeID m_opcodeID; + protected: bool m_rightHasAssignments; }; class ReverseBinaryOpNode : public BinaryOpNode { public: - ReverseBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(globalData, expr1, expr2, rightHasAssignments) - { - } + ReverseBinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + ReverseBinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); - ReverseBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(globalData, type, expr1, expr2, rightHasAssignments) - { - } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; class MultNode : public BinaryOpNode { public: - MultNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_mul; } + MultNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class DivNode : public BinaryOpNode { public: - DivNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_div; } + DivNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class ModNode : public BinaryOpNode { public: - ModNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_mod; } + ModNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class AddNode : public BinaryOpNode { public: - AddNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::forAdd(expr1->resultDescriptor(), expr2->resultDescriptor()), expr1, expr2, rightHasAssignments) - { - } + AddNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_add; } + virtual bool isAdd() const { return true; } }; class SubNode : public BinaryOpNode { public: - SubNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_sub; } + SubNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class LeftShiftNode : public BinaryOpNode { public: - LeftShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lshift; } + LeftShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class RightShiftNode : public BinaryOpNode { public: - RightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_rshift; } + RightShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class UnsignedRightShiftNode : public BinaryOpNode { public: - UnsignedRightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::numberTypeCanReuse(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_urshift; } + UnsignedRightShiftNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class LessNode : public BinaryOpNode { public: - LessNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_less; } + LessNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class GreaterNode : public ReverseBinaryOpNode { public: - GreaterNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_less; } + GreaterNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class LessEqNode : public BinaryOpNode { public: - LessEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lesseq; } + LessEqNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class GreaterEqNode : public ReverseBinaryOpNode { public: - GreaterEqNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : ReverseBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_lesseq; } + GreaterEqNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class ThrowableBinaryOpNode : public BinaryOpNode, public ThrowableExpressionData { public: - ThrowableBinaryOpNode(JSGlobalData* globalData, ResultType type, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, type, expr1, expr2, rightHasAssignments) - { - } - ThrowableBinaryOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, expr1, expr2, rightHasAssignments) - { - } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ThrowableBinaryOpNode(JSGlobalData*, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + ThrowableBinaryOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; class InstanceOfNode : public ThrowableBinaryOpNode { public: - InstanceOfNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : ThrowableBinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } + InstanceOfNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_instanceof; } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; class InNode : public ThrowableBinaryOpNode { public: - InNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : ThrowableBinaryOpNode(globalData, expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_in; } + InNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class EqualNode : public BinaryOpNode { public: - EqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } + EqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_eq; } + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; class NotEqualNode : public BinaryOpNode { public: - NotEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_neq; } + NotEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class StrictEqualNode : public BinaryOpNode { public: - StrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } + StrictEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_stricteq; } + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; class NotStrictEqualNode : public BinaryOpNode { public: - NotStrictEqualNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::booleanType(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_nstricteq; } + NotStrictEqualNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class BitAndNode : public BinaryOpNode { public: - BitAndNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitand; } + BitAndNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class BitOrNode : public BinaryOpNode { public: - BitOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitor; } + BitOrNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; class BitXOrNode : public BinaryOpNode { public: - BitXOrNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) JSC_FAST_CALL - : BinaryOpNode(globalData, ResultType::forBitOp(), expr1, expr2, rightHasAssignments) - { - } - - virtual OpcodeID opcodeID() const JSC_FAST_CALL { return op_bitxor; } + BitXOrNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); }; - /** - * m_expr1 && m_expr2, m_expr1 || m_expr2 - */ + // m_expr1 && m_expr2, m_expr1 || m_expr2 class LogicalOpNode : public ExpressionNode { public: - LogicalOpNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator oper) JSC_FAST_CALL - : ExpressionNode(globalData, ResultType::booleanType()) - , m_expr1(expr1) - , m_expr2(expr2) - , m_operator(oper) - { - } - - virtual ~LogicalOpNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + LogicalOpNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator); private: - RefPtr<ExpressionNode> m_expr1; - RefPtr<ExpressionNode> m_expr2; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; LogicalOperator m_operator; }; - /** - * The ternary operator, "m_logical ? m_expr1 : m_expr2" - */ + // The ternary operator, "m_logical ? m_expr1 : m_expr2" class ConditionalNode : public ExpressionNode { public: - ConditionalNode(JSGlobalData* globalData, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_logical(logical) - , m_expr1(expr1) - , m_expr2(expr2) - { - } - - virtual ~ConditionalNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ConditionalNode(JSGlobalData*, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2); private: - RefPtr<ExpressionNode> m_logical; - RefPtr<ExpressionNode> m_expr1; - RefPtr<ExpressionNode> m_expr2; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_logical; + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; }; class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - ReadModifyResolveNode(JSGlobalData* globalData, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_ident(ident) - , m_right(right) - , m_operator(oper) - , m_rightHasAssignments(rightHasAssignments) - { - } - - virtual ~ReadModifyResolveNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ReadModifyResolveNode(JSGlobalData*, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + Identifier m_ident; - RefPtr<ExpressionNode> m_right; + ExpressionNode* m_right; size_t m_index; // Used by ReadModifyLocalVarNode. - Operator m_operator : 31; - bool m_rightHasAssignments : 1; + Operator m_operator; + bool m_rightHasAssignments; }; class AssignResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignResolveNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_ident(ident) - , m_right(right) - , m_rightHasAssignments(rightHasAssignments) - { - } - - virtual ~AssignResolveNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + AssignResolveNode(JSGlobalData*, const Identifier&, ExpressionNode* right, bool rightHasAssignments); private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + Identifier m_ident; - RefPtr<ExpressionNode> m_right; + ExpressionNode* m_right; size_t m_index; // Used by ReadModifyLocalVarNode. bool m_rightHasAssignments; }; class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData { public: - ReadModifyBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_subscript(subscript) - , m_right(right) - , m_operator(oper) - , m_subscriptHasAssignments(subscriptHasAssignments) - , m_rightHasAssignments(rightHasAssignments) - { - } - - virtual ~ReadModifyBracketNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ReadModifyBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_base; - RefPtr<ExpressionNode> m_subscript; - RefPtr<ExpressionNode> m_right; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + ExpressionNode* m_right; Operator m_operator : 30; bool m_subscriptHasAssignments : 1; bool m_rightHasAssignments : 1; @@ -1533,168 +1047,105 @@ namespace JSC { class AssignBracketNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignBracketNode(JSGlobalData* globalData, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_subscript(subscript) - , m_right(right) - , m_subscriptHasAssignments(subscriptHasAssignments) - , m_rightHasAssignments(rightHasAssignments) - { - } - - virtual ~AssignBracketNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + AssignBracketNode(JSGlobalData*, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_base; - RefPtr<ExpressionNode> m_subscript; - RefPtr<ExpressionNode> m_right; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + ExpressionNode* m_right; bool m_subscriptHasAssignments : 1; bool m_rightHasAssignments : 1; }; class AssignDotNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_ident(ident) - , m_right(right) - , m_rightHasAssignments(rightHasAssignments) - { - } - - virtual ~AssignDotNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + AssignDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_base; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; Identifier m_ident; - RefPtr<ExpressionNode> m_right; + ExpressionNode* m_right; bool m_rightHasAssignments; }; class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData { public: - ReadModifyDotNode(JSGlobalData* globalData, ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableSubExpressionData(divot, startOffset, endOffset) - , m_base(base) - , m_ident(ident) - , m_right(right) - , m_operator(oper) - , m_rightHasAssignments(rightHasAssignments) - { - } - - virtual ~ReadModifyDotNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ReadModifyDotNode(JSGlobalData*, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_base; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; Identifier m_ident; - RefPtr<ExpressionNode> m_right; + ExpressionNode* m_right; Operator m_operator : 31; bool m_rightHasAssignments : 1; }; class AssignErrorNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignErrorNode(JSGlobalData* globalData, ExpressionNode* left, Operator oper, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset) JSC_FAST_CALL - : ExpressionNode(globalData) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_left(left) - , m_operator(oper) - , m_right(right) - { - } - - virtual ~AssignErrorNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + AssignErrorNode(JSGlobalData*, ExpressionNode* left, Operator, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset); private: - RefPtr<ExpressionNode> m_left; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_left; Operator m_operator; - RefPtr<ExpressionNode> m_right; + ExpressionNode* m_right; }; class CommaNode : public ExpressionNode { public: - CommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_expr1(expr1) - , m_expr2(expr2) - { - } - - virtual ~CommaNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + CommaNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2); private: - RefPtr<ExpressionNode> m_expr1; - RefPtr<ExpressionNode> m_expr2; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; }; - class VarDeclCommaNode : public CommaNode { - public: - VarDeclCommaNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2) JSC_FAST_CALL - : CommaNode(globalData, expr1, expr2) - { - } - }; - class ConstDeclNode : public ExpressionNode { public: - ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in) JSC_FAST_CALL; + ConstDeclNode(JSGlobalData*, const Identifier&, ExpressionNode*); - virtual ~ConstDeclNode(); - virtual void releaseNodes(NodeReleaser&); + bool hasInitializer() const { return m_init; } + const Identifier& ident() { return m_ident; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitCodeSingle(BytecodeGenerator&); Identifier m_ident; - RefPtr<ConstDeclNode> m_next; - RefPtr<ExpressionNode> m_init; - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual RegisterID* emitCodeSingle(BytecodeGenerator&) JSC_FAST_CALL; - }; - class ConstStatementNode : public StatementNode { public: - ConstStatementNode(JSGlobalData* globalData, ConstDeclNode* next) JSC_FAST_CALL - : StatementNode(globalData) - , m_next(next) - { - } + ConstDeclNode* m_next; - virtual ~ConstStatementNode(); - virtual void releaseNodes(NodeReleaser&); + private: + ExpressionNode* m_init; + }; - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + class ConstStatementNode : public StatementNode { + public: + ConstStatementNode(JSGlobalData*, ConstDeclNode* next); private: - RefPtr<ConstDeclNode> m_next; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ConstDeclNode* m_next; }; - typedef Vector<RefPtr<StatementNode> > StatementVector; + typedef Vector<StatementNode*> StatementVector; - class SourceElements : public ParserRefCounted { + class SourceElements : public ParserArenaDeletable { public: - SourceElements(JSGlobalData* globalData) : ParserRefCounted(globalData) {} + SourceElements(JSGlobalData*); - void append(PassRefPtr<StatementNode>); + void append(StatementNode*); void releaseContentsIntoVector(StatementVector& destination) { ASSERT(destination.isEmpty()); @@ -1708,369 +1159,235 @@ namespace JSC { class BlockNode : public StatementNode { public: - BlockNode(JSGlobalData*, SourceElements* children) JSC_FAST_CALL; - - virtual ~BlockNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + BlockNode(JSGlobalData*, SourceElements* children); StatementVector& children() { return m_children; } - virtual bool isBlock() const JSC_FAST_CALL { return true; } - private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isBlock() const { return true; } + StatementVector m_children; }; class EmptyStatementNode : public StatementNode { public: - EmptyStatementNode(JSGlobalData* globalData) JSC_FAST_CALL // debug - : StatementNode(globalData) - { - } + EmptyStatementNode(JSGlobalData*); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - virtual bool isEmptyStatement() const JSC_FAST_CALL { return true; } + virtual bool isEmptyStatement() const { return true; } }; class DebuggerStatementNode : public StatementNode { public: - DebuggerStatementNode(JSGlobalData* globalData) JSC_FAST_CALL - : StatementNode(globalData) - { - } + DebuggerStatementNode(JSGlobalData*); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; class ExprStatementNode : public StatementNode { public: - ExprStatementNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : StatementNode(globalData) - , m_expr(expr) - { - } + ExprStatementNode(JSGlobalData*, ExpressionNode*); - virtual bool isExprStatement() const JSC_FAST_CALL { return true; } + ExpressionNode* expr() const { return m_expr; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + private: + virtual bool isExprStatement() const { return true; } - ExpressionNode* expr() const { return m_expr.get(); } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - private: - RefPtr<ExpressionNode> m_expr; + ExpressionNode* m_expr; }; class VarStatementNode : public StatementNode { public: - VarStatementNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : StatementNode(globalData) - , m_expr(expr) - { - } - - virtual ~VarStatementNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + VarStatementNode(JSGlobalData*, ExpressionNode*); private: - RefPtr<ExpressionNode> m_expr; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; }; class IfNode : public StatementNode { public: - IfNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock) JSC_FAST_CALL - : StatementNode(globalData) - , m_condition(condition) - , m_ifBlock(ifBlock) - { - } - - virtual ~IfNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + IfNode(JSGlobalData*, ExpressionNode* condition, StatementNode* ifBlock); protected: - RefPtr<ExpressionNode> m_condition; - RefPtr<StatementNode> m_ifBlock; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_condition; + StatementNode* m_ifBlock; }; class IfElseNode : public IfNode { public: - IfElseNode(JSGlobalData* globalData, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock) JSC_FAST_CALL - : IfNode(globalData, condition, ifBlock) - , m_elseBlock(elseBlock) - { - } - - virtual ~IfElseNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + IfElseNode(JSGlobalData*, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock); private: - RefPtr<StatementNode> m_elseBlock; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + StatementNode* m_elseBlock; }; class DoWhileNode : public StatementNode { public: - DoWhileNode(JSGlobalData* globalData, StatementNode* statement, ExpressionNode* expr) JSC_FAST_CALL - : StatementNode(globalData) - , m_statement(statement) - , m_expr(expr) - { - } - - virtual ~DoWhileNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + DoWhileNode(JSGlobalData*, StatementNode* statement, ExpressionNode*); private: - RefPtr<StatementNode> m_statement; - RefPtr<ExpressionNode> m_expr; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + StatementNode* m_statement; + ExpressionNode* m_expr; }; class WhileNode : public StatementNode { public: - WhileNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement) JSC_FAST_CALL - : StatementNode(globalData) - , m_expr(expr) - , m_statement(statement) - { - } - - virtual ~WhileNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + WhileNode(JSGlobalData*, ExpressionNode*, StatementNode* statement); private: - RefPtr<ExpressionNode> m_expr; - RefPtr<StatementNode> m_statement; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + StatementNode* m_statement; }; class ForNode : public StatementNode { public: - ForNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl) JSC_FAST_CALL - : StatementNode(globalData) - , m_expr1(expr1) - , m_expr2(expr2) - , m_expr3(expr3) - , m_statement(statement) - , m_expr1WasVarDecl(expr1 && expr1WasVarDecl) - { - ASSERT(statement); - } - - virtual ~ForNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ForNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode* statement, bool expr1WasVarDecl); private: - RefPtr<ExpressionNode> m_expr1; - RefPtr<ExpressionNode> m_expr2; - RefPtr<ExpressionNode> m_expr3; - RefPtr<StatementNode> m_statement; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; + ExpressionNode* m_expr3; + StatementNode* m_statement; bool m_expr1WasVarDecl; }; class ForInNode : public StatementNode, public ThrowableExpressionData { public: - ForInNode(JSGlobalData*, ExpressionNode*, ExpressionNode*, StatementNode*) JSC_FAST_CALL; - ForInNode(JSGlobalData*, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset) JSC_FAST_CALL; - - virtual ~ForInNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ForInNode(JSGlobalData*, ExpressionNode*, ExpressionNode*, StatementNode*); + ForInNode(JSGlobalData*, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset); private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + Identifier m_ident; - RefPtr<ExpressionNode> m_init; - RefPtr<ExpressionNode> m_lexpr; - RefPtr<ExpressionNode> m_expr; - RefPtr<StatementNode> m_statement; + ExpressionNode* m_init; + ExpressionNode* m_lexpr; + ExpressionNode* m_expr; + StatementNode* m_statement; bool m_identIsVarDecl; }; class ContinueNode : public StatementNode, public ThrowableExpressionData { public: - ContinueNode(JSGlobalData* globalData) JSC_FAST_CALL - : StatementNode(globalData) - { - } - - ContinueNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL - : StatementNode(globalData) - , m_ident(ident) - { - } + ContinueNode(JSGlobalData*); + ContinueNode(JSGlobalData*, const Identifier&); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + Identifier m_ident; }; class BreakNode : public StatementNode, public ThrowableExpressionData { public: - BreakNode(JSGlobalData* globalData) JSC_FAST_CALL - : StatementNode(globalData) - { - } - - BreakNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL - : StatementNode(globalData) - , m_ident(ident) - { - } + BreakNode(JSGlobalData*); + BreakNode(JSGlobalData*, const Identifier&); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + Identifier m_ident; }; class ReturnNode : public StatementNode, public ThrowableExpressionData { public: - ReturnNode(JSGlobalData* globalData, ExpressionNode* value) JSC_FAST_CALL - : StatementNode(globalData) - , m_value(value) - { - } + ReturnNode(JSGlobalData*, ExpressionNode* value); - virtual ~ReturnNode(); - virtual void releaseNodes(NodeReleaser&); + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - virtual bool isReturnNode() const JSC_FAST_CALL { return true; } + virtual bool isReturnNode() const { return true; } - private: - RefPtr<ExpressionNode> m_value; + ExpressionNode* m_value; }; class WithNode : public StatementNode { public: - WithNode(JSGlobalData* globalData, ExpressionNode* expr, StatementNode* statement, uint32_t divot, uint32_t expressionLength) JSC_FAST_CALL - : StatementNode(globalData) - , m_expr(expr) - , m_statement(statement) - , m_divot(divot) - , m_expressionLength(expressionLength) - { - } - - virtual ~WithNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + WithNode(JSGlobalData*, ExpressionNode*, StatementNode*, uint32_t divot, uint32_t expressionLength); private: - RefPtr<ExpressionNode> m_expr; - RefPtr<StatementNode> m_statement; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + StatementNode* m_statement; uint32_t m_divot; uint32_t m_expressionLength; }; class LabelNode : public StatementNode, public ThrowableExpressionData { public: - LabelNode(JSGlobalData* globalData, const Identifier& name, StatementNode* statement) JSC_FAST_CALL - : StatementNode(globalData) - , m_name(name) - , m_statement(statement) - { - } - - virtual ~LabelNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + LabelNode(JSGlobalData*, const Identifier& name, StatementNode*); private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + Identifier m_name; - RefPtr<StatementNode> m_statement; + StatementNode* m_statement; }; class ThrowNode : public StatementNode, public ThrowableExpressionData { public: - ThrowNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : StatementNode(globalData) - , m_expr(expr) - { - } - - virtual ~ThrowNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + ThrowNode(JSGlobalData*, ExpressionNode*); private: - RefPtr<ExpressionNode> m_expr; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; }; class TryNode : public StatementNode { public: - TryNode(JSGlobalData* globalData, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock) JSC_FAST_CALL - : StatementNode(globalData) - , m_tryBlock(tryBlock) - , m_exceptionIdent(exceptionIdent) - , m_catchBlock(catchBlock) - , m_finallyBlock(finallyBlock) - , m_catchHasEval(catchHasEval) - { - } - - virtual ~TryNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0) JSC_FAST_CALL; + TryNode(JSGlobalData*, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock); private: - RefPtr<StatementNode> m_tryBlock; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* dst = 0); + + StatementNode* m_tryBlock; Identifier m_exceptionIdent; - RefPtr<StatementNode> m_catchBlock; - RefPtr<StatementNode> m_finallyBlock; + StatementNode* m_catchBlock; + StatementNode* m_finallyBlock; bool m_catchHasEval; }; - class ParameterNode : public ParserRefCounted { + class ParameterNode : public ParserArenaDeletable { public: - ParameterNode(JSGlobalData* globalData, const Identifier& ident) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_ident(ident) - { - } - - ParameterNode(JSGlobalData* globalData, ParameterNode* l, const Identifier& ident) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_ident(ident) - { - l->m_next = this; - } - - virtual ~ParameterNode(); - virtual void releaseNodes(NodeReleaser&); + ParameterNode(JSGlobalData*, const Identifier&); + ParameterNode(JSGlobalData*, ParameterNode*, const Identifier&); - const Identifier& ident() const JSC_FAST_CALL { return m_ident; } - ParameterNode* nextParam() const JSC_FAST_CALL { return m_next.get(); } + const Identifier& ident() const { return m_ident; } + ParameterNode* nextParam() const { return m_next; } private: Identifier m_ident; - RefPtr<ParameterNode> m_next; + ParameterNode* m_next; }; struct ScopeNodeData { typedef DeclarationStacks::VarStack VarStack; typedef DeclarationStacks::FunctionStack FunctionStack; - ScopeNodeData(SourceElements*, VarStack*, FunctionStack*, int numConstants); + ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, int numConstants); + ParserArena m_arena; VarStack m_varStack; FunctionStack m_functionStack; int m_numConstants; @@ -2079,22 +1396,25 @@ namespace JSC { void mark(); }; - class ScopeNode : public StatementNode { + class ScopeNode : public StatementNode, public ParserArenaRefCounted { public: typedef DeclarationStacks::VarStack VarStack; typedef DeclarationStacks::FunctionStack FunctionStack; - ScopeNode(JSGlobalData*) JSC_FAST_CALL; - ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants) JSC_FAST_CALL; - virtual ~ScopeNode(); - virtual void releaseNodes(NodeReleaser&); + ScopeNode(JSGlobalData*); + ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants); - void adoptData(std::auto_ptr<ScopeNodeData> data) { m_data.adopt(data); } + void adoptData(std::auto_ptr<ScopeNodeData> data) + { + ASSERT(!data->m_arena.contains(this)); + ASSERT(!m_data); + m_data.adopt(data); + } ScopeNodeData* data() const { return m_data.get(); } void destroyData() { m_data.clear(); } const SourceCode& source() const { return m_source; } - const UString& sourceURL() const JSC_FAST_CALL { return m_source.provider()->url(); } + const UString& sourceURL() const { return m_source.provider()->url(); } intptr_t sourceID() const { return m_source.provider()->asID(); } void setFeatures(CodeFeatures features) { m_features = features; } @@ -2121,9 +1441,31 @@ namespace JSC { virtual void mark() { } +#if ENABLE(JIT) + JITCode& generatedJITCode() + { + ASSERT(m_jitCode); + return m_jitCode; + } + + ExecutablePool* getExecutablePool() + { + return m_jitCode.getExecutablePool(); + } + + void setJITCode(const JITCode jitCode) + { + m_jitCode = jitCode; + } +#endif + protected: void setSource(const SourceCode& source) { m_source = source; } +#if ENABLE(JIT) + JITCode m_jitCode; +#endif + private: OwnPtr<ScopeNodeData> m_data; CodeFeatures m_features; @@ -2132,44 +1474,70 @@ namespace JSC { class ProgramNode : public ScopeNode { public: - static ProgramNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; + static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); - ProgramCodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL + ProgramCodeBlock& bytecode(ScopeChainNode* scopeChain) { if (!m_code) generateBytecode(scopeChain); return *m_code; } +#if ENABLE(JIT) + JITCode& jitCode(ScopeChainNode* scopeChain) + { + if (!m_jitCode) + generateJITCode(scopeChain); + return m_jitCode; + } +#endif + private: - ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; + ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); + + void generateBytecode(ScopeChainNode*); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - void generateBytecode(ScopeChainNode*) JSC_FAST_CALL; - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; +#if ENABLE(JIT) + void generateJITCode(ScopeChainNode*); +#endif OwnPtr<ProgramCodeBlock> m_code; }; class EvalNode : public ScopeNode { public: - static EvalNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; + static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); - EvalCodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL + EvalCodeBlock& bytecode(ScopeChainNode* scopeChain) { if (!m_code) generateBytecode(scopeChain); return *m_code; } - EvalCodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*) JSC_FAST_CALL; + EvalCodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*); virtual void mark(); +#if ENABLE(JIT) + JITCode& jitCode(ScopeChainNode* scopeChain) + { + if (!m_jitCode) + generateJITCode(scopeChain); + return m_jitCode; + } +#endif + private: - EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; + EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); - void generateBytecode(ScopeChainNode*) JSC_FAST_CALL; - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + void generateBytecode(ScopeChainNode*); + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + +#if ENABLE(JIT) + void generateJITCode(ScopeChainNode*); +#endif OwnPtr<EvalCodeBlock> m_code; }; @@ -2177,34 +1545,32 @@ namespace JSC { class FunctionBodyNode : public ScopeNode { friend class JIT; public: - static FunctionBodyNode* create(JSGlobalData*) JSC_FAST_CALL; - static FunctionBodyNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; +#if ENABLE(JIT) + static PassRefPtr<FunctionBodyNode> createNativeThunk(JSGlobalData*); +#endif + static FunctionBodyNode* create(JSGlobalData*); + static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); virtual ~FunctionBodyNode(); - const Identifier* parameters() const JSC_FAST_CALL { return m_parameters; } + const Identifier* parameters() const { return m_parameters; } size_t parameterCount() const { return m_parameterCount; } - UString paramString() const JSC_FAST_CALL; + UString paramString() const ; Identifier* copyParameters(); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - - CodeBlock& bytecode(ScopeChainNode* scopeChain) JSC_FAST_CALL - { - ASSERT(scopeChain); - if (!m_code) - generateBytecode(scopeChain); - return *m_code; - } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - CodeBlock& generatedBytecode() JSC_FAST_CALL + bool isGenerated() const { - ASSERT(m_code); - return *m_code; + return m_code; } - bool isGenerated() JSC_FAST_CALL + bool isHostFunction() const { - return m_code; +#if ENABLE(JIT) + return !!m_jitCode && !m_code; +#else + return true; +#endif } virtual void mark(); @@ -2212,182 +1578,126 @@ namespace JSC { void finishParsing(const SourceCode&, ParameterNode*); void finishParsing(Identifier* parameters, size_t parameterCount); - UString toSourceString() const JSC_FAST_CALL { return source().toString(); } + UString toSourceString() const { return source().toString(); } - // These objects are ref/deref'd a lot in the scope chain, so this is a faster ref/deref. - // If the virtual machine changes so this doesn't happen as much we can change back. - void ref() + CodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*); +#if ENABLE(JIT) + JITCode& jitCode(ScopeChainNode* scopeChain) { - if (++m_refCount == 1) - ScopeNode::ref(); + if (!m_jitCode) + generateJITCode(scopeChain); + return m_jitCode; } - void deref() +#endif + + CodeBlock& bytecode(ScopeChainNode* scopeChain) { - ASSERT(m_refCount); - if (!--m_refCount) - ScopeNode::deref(); + ASSERT(scopeChain); + if (!m_code) + generateBytecode(scopeChain); + return *m_code; } - - CodeBlock& bytecodeForExceptionInfoReparse(ScopeChainNode*, CodeBlock*) JSC_FAST_CALL; - + + CodeBlock& generatedBytecode() + { + ASSERT(m_code); + return *m_code; + } + private: - FunctionBodyNode(JSGlobalData*) JSC_FAST_CALL; - FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL; - - void generateBytecode(ScopeChainNode*) JSC_FAST_CALL; + FunctionBodyNode(JSGlobalData*); + FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); + void generateBytecode(ScopeChainNode*); +#if ENABLE(JIT) + void generateJITCode(ScopeChainNode*); +#endif Identifier* m_parameters; size_t m_parameterCount; OwnPtr<CodeBlock> m_code; - unsigned m_refCount; }; - class FuncExprNode : public ExpressionNode { + class FuncExprNode : public ExpressionNode, public ParserArenaRefCounted { public: - FuncExprNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0) JSC_FAST_CALL - : ExpressionNode(globalData) - , m_ident(ident) - , m_parameter(parameter) - , m_body(body) - { - m_body->finishParsing(source, m_parameter.get()); - } - - virtual ~FuncExprNode(); - virtual void releaseNodes(NodeReleaser&); + FuncExprNode(JSGlobalData*, const Identifier&, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0); - virtual bool isFuncExprNode() const JSC_FAST_CALL { return true; } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; - JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL; + JSFunction* makeFunction(ExecState*, ScopeChainNode*); FunctionBodyNode* body() { return m_body.get(); } private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isFuncExprNode() const { return true; } + Identifier m_ident; - RefPtr<ParameterNode> m_parameter; RefPtr<FunctionBodyNode> m_body; }; - class FuncDeclNode : public StatementNode { + class FuncDeclNode : public StatementNode, public ParserArenaRefCounted { public: - FuncDeclNode(JSGlobalData* globalData, const Identifier& ident, FunctionBodyNode* body, const SourceCode& source, ParameterNode* parameter = 0) JSC_FAST_CALL - : StatementNode(globalData) - , m_ident(ident) - , m_parameter(parameter) - , m_body(body) - { - m_body->finishParsing(source, m_parameter.get()); - } - - virtual ~FuncDeclNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + FuncDeclNode(JSGlobalData*, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); - JSFunction* makeFunction(ExecState*, ScopeChainNode*) JSC_FAST_CALL; + JSFunction* makeFunction(ExecState*, ScopeChainNode*); Identifier m_ident; FunctionBodyNode* body() { return m_body.get(); } private: - RefPtr<ParameterNode> m_parameter; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + RefPtr<FunctionBodyNode> m_body; }; - class CaseClauseNode : public ParserRefCounted { + class CaseClauseNode : public ParserArenaDeletable { public: - CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_expr(expr) - { - } + CaseClauseNode(JSGlobalData*, ExpressionNode*); + CaseClauseNode(JSGlobalData*, ExpressionNode*, SourceElements*); - CaseClauseNode(JSGlobalData* globalData, ExpressionNode* expr, SourceElements* children) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_expr(expr) - { - if (children) - children->releaseContentsIntoVector(m_children); - } - - virtual ~CaseClauseNode(); - virtual void releaseNodes(NodeReleaser&); - - ExpressionNode* expr() const { return m_expr.get(); } + ExpressionNode* expr() const { return m_expr; } StatementVector& children() { return m_children; } private: - RefPtr<ExpressionNode> m_expr; + ExpressionNode* m_expr; StatementVector m_children; }; - class ClauseListNode : public ParserRefCounted { + class ClauseListNode : public ParserArenaDeletable { public: - ClauseListNode(JSGlobalData* globalData, CaseClauseNode* clause) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_clause(clause) - { - } - - ClauseListNode(JSGlobalData* globalData, ClauseListNode* clauseList, CaseClauseNode* clause) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_clause(clause) - { - clauseList->m_next = this; - } - - virtual ~ClauseListNode(); - virtual void releaseNodes(NodeReleaser&); + ClauseListNode(JSGlobalData*, CaseClauseNode*); + ClauseListNode(JSGlobalData*, ClauseListNode*, CaseClauseNode*); - CaseClauseNode* getClause() const JSC_FAST_CALL { return m_clause.get(); } - ClauseListNode* getNext() const JSC_FAST_CALL { return m_next.get(); } + CaseClauseNode* getClause() const { return m_clause; } + ClauseListNode* getNext() const { return m_next; } private: - RefPtr<CaseClauseNode> m_clause; - RefPtr<ClauseListNode> m_next; + CaseClauseNode* m_clause; + ClauseListNode* m_next; }; - class CaseBlockNode : public ParserRefCounted { + class CaseBlockNode : public ParserArenaDeletable { public: - CaseBlockNode(JSGlobalData* globalData, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2) JSC_FAST_CALL - : ParserRefCounted(globalData) - , m_list1(list1) - , m_defaultClause(defaultClause) - , m_list2(list2) - { - } + CaseBlockNode(JSGlobalData*, ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2); - virtual ~CaseBlockNode(); - virtual void releaseNodes(NodeReleaser&); - - RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* dst = 0) JSC_FAST_CALL; + RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* dst = 0); private: SwitchInfo::SwitchType tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num); - RefPtr<ClauseListNode> m_list1; - RefPtr<CaseClauseNode> m_defaultClause; - RefPtr<ClauseListNode> m_list2; + ClauseListNode* m_list1; + CaseClauseNode* m_defaultClause; + ClauseListNode* m_list2; }; class SwitchNode : public StatementNode { public: - SwitchNode(JSGlobalData* globalData, ExpressionNode* expr, CaseBlockNode* block) JSC_FAST_CALL - : StatementNode(globalData) - , m_expr(expr) - , m_block(block) - { - } - - virtual ~SwitchNode(); - virtual void releaseNodes(NodeReleaser&); - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) JSC_FAST_CALL; + SwitchNode(JSGlobalData*, ExpressionNode*, CaseBlockNode*); private: - RefPtr<ExpressionNode> m_expr; - RefPtr<CaseBlockNode> m_block; + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + CaseBlockNode* m_block; }; struct ElementList { @@ -2422,4 +1732,4 @@ namespace JSC { } // namespace JSC -#endif // NODES_H_ +#endif // Nodes_h diff --git a/JavaScriptCore/parser/Parser.cpp b/JavaScriptCore/parser/Parser.cpp index 886a513..96f4ae6 100644 --- a/JavaScriptCore/parser/Parser.cpp +++ b/JavaScriptCore/parser/Parser.cpp @@ -39,7 +39,7 @@ namespace JSC { void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg) { - ASSERT(!m_sourceElements); + m_sourceElements = 0; int defaultErrLine; UString defaultErrMsg; @@ -57,14 +57,13 @@ void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg) int parseError = jscyyparse(globalData); bool lexError = lexer.sawError(); + int lineNumber = lexer.lineNumber(); lexer.clear(); - ParserRefCounted::deleteNewObjects(globalData); - if (parseError || lexError) { - *errLine = lexer.lineNo(); + *errLine = lineNumber; *errMsg = "Parse error"; - m_sourceElements.clear(); + m_sourceElements = 0; } } @@ -77,23 +76,26 @@ void Parser::reparseInPlace(JSGlobalData* globalData, FunctionBodyNode* function parse(globalData, 0, 0); ASSERT(m_sourceElements); - functionBodyNode->adoptData(std::auto_ptr<ScopeNodeData>(new ScopeNodeData(m_sourceElements.get(), - m_varDeclarations ? &m_varDeclarations->data : 0, - m_funcDeclarations ? &m_funcDeclarations->data : 0, - m_numConstants))); + functionBodyNode->adoptData(std::auto_ptr<ScopeNodeData>(new ScopeNodeData(globalData->parser->arena(), + m_sourceElements, + m_varDeclarations ? &m_varDeclarations->data : 0, + m_funcDeclarations ? &m_funcDeclarations->data : 0, + m_numConstants))); bool usesArguments = functionBodyNode->usesArguments(); functionBodyNode->setFeatures(m_features); if (usesArguments && !functionBodyNode->usesArguments()) functionBodyNode->setUsesArguments(); + ASSERT(globalData->parser->arena().isEmpty()); + m_source = 0; m_sourceElements = 0; m_varDeclarations = 0; m_funcDeclarations = 0; } -void Parser::didFinishParsing(SourceElements* sourceElements, ParserRefCountedData<DeclarationStacks::VarStack>* varStack, - ParserRefCountedData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants) +void Parser::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack, + ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants) { m_sourceElements = sourceElements; m_varDeclarations = varStack; diff --git a/JavaScriptCore/parser/Parser.h b/JavaScriptCore/parser/Parser.h index 6191ccb..6f4c2b7 100644 --- a/JavaScriptCore/parser/Parser.h +++ b/JavaScriptCore/parser/Parser.h @@ -23,9 +23,9 @@ #ifndef Parser_h #define Parser_h -#include "SourceProvider.h" #include "Debugger.h" #include "Nodes.h" +#include "SourceProvider.h" #include <wtf/Forward.h> #include <wtf/Noncopyable.h> #include <wtf/OwnPtr.h> @@ -37,15 +37,7 @@ namespace JSC { class ProgramNode; class UString; - template <typename T> - struct ParserRefCountedData : ParserRefCounted { - ParserRefCountedData(JSGlobalData* globalData) - : ParserRefCounted(globalData) - { - } - - T data; - }; + template <typename T> struct ParserArenaData : ParserArenaDeletable { T data; }; class Parser : Noncopyable { public: @@ -53,16 +45,19 @@ namespace JSC { template <class ParsedNode> PassRefPtr<ParsedNode> reparse(JSGlobalData*, ParsedNode*); void reparseInPlace(JSGlobalData*, FunctionBodyNode*); - void didFinishParsing(SourceElements*, ParserRefCountedData<DeclarationStacks::VarStack>*, - ParserRefCountedData<DeclarationStacks::FunctionStack>*, CodeFeatures features, int lastLine, int numConstants); + void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, + ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures features, int lastLine, int numConstants); + + ParserArena& arena() { return m_arena; } private: void parse(JSGlobalData*, int* errLine, UString* errMsg); + ParserArena m_arena; const SourceCode* m_source; - RefPtr<SourceElements> m_sourceElements; - RefPtr<ParserRefCountedData<DeclarationStacks::VarStack> > m_varDeclarations; - RefPtr<ParserRefCountedData<DeclarationStacks::FunctionStack> > m_funcDeclarations; + SourceElements* m_sourceElements; + ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; + ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; CodeFeatures m_features; int m_lastLine; int m_numConstants; @@ -75,7 +70,7 @@ namespace JSC { RefPtr<ParsedNode> result; if (m_sourceElements) { result = ParsedNode::create(&exec->globalData(), - m_sourceElements.get(), + m_sourceElements, m_varDeclarations ? &m_varDeclarations->data : 0, m_funcDeclarations ? &m_funcDeclarations->data : 0, *m_source, @@ -84,8 +79,9 @@ namespace JSC { result->setLoc(m_source->firstLine(), m_lastLine); } + m_arena.reset(); + m_source = 0; - m_sourceElements = 0; m_varDeclarations = 0; m_funcDeclarations = 0; @@ -101,7 +97,7 @@ namespace JSC { RefPtr<ParsedNode> result; if (m_sourceElements) { result = ParsedNode::create(globalData, - m_sourceElements.get(), + m_sourceElements, m_varDeclarations ? &m_varDeclarations->data : 0, m_funcDeclarations ? &m_funcDeclarations->data : 0, *m_source, @@ -110,8 +106,9 @@ namespace JSC { result->setLoc(m_source->firstLine(), m_lastLine); } + m_arena.reset(); + m_source = 0; - m_sourceElements = 0; m_varDeclarations = 0; m_funcDeclarations = 0; diff --git a/JavaScriptCore/parser/ParserArena.cpp b/JavaScriptCore/parser/ParserArena.cpp new file mode 100644 index 0000000..2617506 --- /dev/null +++ b/JavaScriptCore/parser/ParserArena.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ParserArena.h" + +#include "Nodes.h" + +namespace JSC { + +ParserArena::~ParserArena() +{ + deleteAllValues(m_deletableObjects); +} + +bool ParserArena::contains(ParserArenaRefCounted* object) const +{ + return m_refCountedObjects.find(object) != notFound; +} + +ParserArenaRefCounted* ParserArena::last() const +{ + return m_refCountedObjects.last().get(); +} + +void ParserArena::removeLast() +{ + m_refCountedObjects.removeLast(); +} + +void ParserArena::reset() +{ + deleteAllValues(m_deletableObjects); + m_deletableObjects.shrink(0); + m_refCountedObjects.shrink(0); +} + +} diff --git a/JavaScriptCore/parser/ParserArena.h b/JavaScriptCore/parser/ParserArena.h new file mode 100644 index 0000000..66c8529 --- /dev/null +++ b/JavaScriptCore/parser/ParserArena.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ParserArena_h +#define ParserArena_h + +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> +#include <wtf/Vector.h> + +namespace JSC { + + class ParserArenaDeletable; + class ParserArenaRefCounted; + + class ParserArena { + public: + void swap(ParserArena& otherArena) + { + m_deletableObjects.swap(otherArena.m_deletableObjects); + m_refCountedObjects.swap(otherArena.m_refCountedObjects); + } + ~ParserArena(); + + void deleteWithArena(ParserArenaDeletable* object) { m_deletableObjects.append(object); } + void derefWithArena(PassRefPtr<ParserArenaRefCounted> object) { m_refCountedObjects.append(object); } + + bool contains(ParserArenaRefCounted*) const; + ParserArenaRefCounted* last() const; + void removeLast(); + + bool isEmpty() const { return m_deletableObjects.isEmpty() && m_refCountedObjects.isEmpty(); } + void reset(); + + private: + Vector<ParserArenaDeletable*> m_deletableObjects; + Vector<RefPtr<ParserArenaRefCounted> > m_refCountedObjects; + }; + +} + +#endif diff --git a/JavaScriptCore/parser/ResultType.h b/JavaScriptCore/parser/ResultType.h index 3e7fddb..27b8112 100644 --- a/JavaScriptCore/parser/ResultType.h +++ b/JavaScriptCore/parser/ResultType.h @@ -63,6 +63,11 @@ namespace JSC { return (m_type & TypeBits) == TypeMaybeNumber; } + bool definitelyIsString() + { + return (m_type & TypeBits) == TypeMaybeString; + } + bool mightBeNumber() { return m_type & TypeMaybeNumber; @@ -117,7 +122,7 @@ namespace JSC { { if (op1.definitelyIsNumber() && op2.definitelyIsNumber()) return numberTypeCanReuse(); - if (op1.isNotNumber() || op2.isNotNumber()) + if (op1.definitelyIsString() || op2.definitelyIsString()) return stringType(); return stringOrNumberTypeCanReuse(); } diff --git a/JavaScriptCore/parser/SourceProvider.h b/JavaScriptCore/parser/SourceProvider.h index 07da9e0..1c59eed 100644 --- a/JavaScriptCore/parser/SourceProvider.h +++ b/JavaScriptCore/parser/SourceProvider.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,10 +34,13 @@ namespace JSC { + enum SourceBOMPresence { SourceHasNoBOMs, SourceCouldHaveBOMs }; + class SourceProvider : public RefCounted<SourceProvider> { public: - SourceProvider(const UString& url) + SourceProvider(const UString& url, SourceBOMPresence hasBOMs = SourceCouldHaveBOMs) : m_url(url) + , m_hasBOMs(hasBOMs) { } virtual ~SourceProvider() { } @@ -49,8 +52,11 @@ namespace JSC { const UString& url() { return m_url; } intptr_t asID() { return reinterpret_cast<intptr_t>(this); } + SourceBOMPresence hasBOMs() const { return m_hasBOMs; } + private: UString m_url; + SourceBOMPresence m_hasBOMs; }; class UStringSourceProvider : public SourceProvider { |