diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-03-12 14:11:15 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-03-12 14:11:15 +0100 |
commit | dd91e772430dc294e3bf478c119ef8d43c0a3358 (patch) | |
tree | 6f33ce4d5872a5691e0291eb45bf6ab373a5f567 /Source/JavaScriptCore/parser | |
parent | ad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (diff) | |
download | qtwebkit-dd91e772430dc294e3bf478c119ef8d43c0a3358.tar.gz |
Imported WebKit commit 3db4eb1820ac8fb03065d7ea73a4d9db1e8fea1a (http://svn.webkit.org/repository/webkit/trunk@110422)
This includes build fixes for the latest qtbase/qtdeclarative as well as the final QML2 API.
Diffstat (limited to 'Source/JavaScriptCore/parser')
-rw-r--r-- | Source/JavaScriptCore/parser/ASTBuilder.h | 49 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/Lexer.cpp | 245 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/Lexer.h | 26 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/NodeConstructors.h | 15 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/NodeInfo.h | 4 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/Nodes.cpp | 85 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/Nodes.h | 139 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/Parser.cpp | 70 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/Parser.h | 118 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/ParserArena.cpp | 6 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/ParserArena.h | 7 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/ResultType.h | 27 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/SourceProvider.h | 2 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/SourceProviderCacheItem.h | 4 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/SyntaxChecker.h | 7 |
15 files changed, 467 insertions, 337 deletions
diff --git a/Source/JavaScriptCore/parser/ASTBuilder.h b/Source/JavaScriptCore/parser/ASTBuilder.h index b8718709b..a173cc10f 100644 --- a/Source/JavaScriptCore/parser/ASTBuilder.h +++ b/Source/JavaScriptCore/parser/ASTBuilder.h @@ -77,7 +77,6 @@ public: : m_globalData(globalData) , m_sourceCode(sourceCode) , m_scope(globalData) - , m_evalCount(0) { } @@ -119,7 +118,6 @@ public: ParserArenaData<DeclarationStacks::VarStack>* varDeclarations() { return m_scope.m_varDeclarations; } ParserArenaData<DeclarationStacks::FunctionStack>* funcDeclarations() { return m_scope.m_funcDeclarations; } - int features() const { return m_scope.m_features; } int numConstants() const { return m_scope.m_numConstants; } void appendToComma(CommaNode* commaNode, ExpressionNode* expr) { commaNode->append(expr); } @@ -152,17 +150,8 @@ public: incConstants(); return new (m_globalData) VoidNode(lineNumber, expr); } - ExpressionNode* thisExpr(int lineNumber) - { - usesThis(); - return new (m_globalData) ThisNode(lineNumber); - } - ExpressionNode* createResolve(int lineNumber, const Identifier* ident, int start) - { - if (m_globalData->propertyNames->arguments == *ident) - usesArguments(); - return new (m_globalData) ResolveNode(lineNumber, *ident, start); - } + ExpressionNode* thisExpr(int lineNumber) { return new (m_globalData) ThisNode(lineNumber); } + ExpressionNode* createResolve(int lineNumber, const Identifier* ident, int start) { return new (m_globalData) ResolveNode(lineNumber, *ident, start); } ExpressionNode* createObjectLiteral(int lineNumber) { return new (m_globalData) ObjectLiteralNode(lineNumber); } ExpressionNode* createObjectLiteral(int lineNumber, PropertyListNode* properties) { return new (m_globalData) ObjectLiteralNode(lineNumber, properties); } @@ -263,9 +252,9 @@ public: return result; } - FunctionBodyNode* createFunctionBody(int lineNumber, bool inStrictContext) + FunctionBodyNode* createFunctionBody(int lineNumber, ScopeFlags scopeFlags) { - return FunctionBodyNode::create(m_globalData, lineNumber, inStrictContext); + return FunctionBodyNode::create(m_globalData, lineNumber, scopeFlags); } template <bool> PropertyNode* createGetterOrSetterProperty(int lineNumber, PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) @@ -276,6 +265,11 @@ public: return new (m_globalData) PropertyNode(m_globalData, *name, new (m_globalData) FuncExprNode(lineNumber, m_globalData->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), params), type); } + template <bool> PropertyNode* createGetterOrSetterProperty(JSGlobalData*, int lineNumber, PropertyNode::Type type, double name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) + { + body->setLoc(bodyStartLine, bodyEndLine); + return new (m_globalData) PropertyNode(m_globalData, name, new (m_globalData) FuncExprNode(lineNumber, m_globalData->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), params), type); + } ArgumentsNode* createArguments() { return new (m_globalData) ArgumentsNode(); } ArgumentsNode* createArguments(ArgumentListNode* args) { return new (m_globalData) ArgumentsNode(args); } @@ -307,8 +301,6 @@ public: StatementNode* createFuncDeclStatement(int lineNumber, const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) { FuncDeclNode* decl = new (m_globalData) FuncDeclNode(lineNumber, *name, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), parameters); - if (*name == m_globalData->propertyNames->arguments) - usesArguments(); m_scope.m_funcDeclarations->data.append(decl->body()); body->setLoc(bodyStartLine, bodyEndLine); return decl; @@ -421,8 +413,6 @@ public: StatementNode* createTryStatement(int lineNumber, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine) { TryNode* result = new (m_globalData) TryNode(lineNumber, tryBlock, *ident, catchBlock, finallyBlock); - if (catchBlock) - usesCatch(); result->setLoc(startLine, endLine); return result; } @@ -458,7 +448,6 @@ public: StatementNode* createWithStatement(int lineNumber, ExpressionNode* expr, StatementNode* statement, int start, int end, int startLine, int endLine) { - usesWith(); WithNode* result = new (m_globalData) WithNode(lineNumber, expr, statement, end, end - start); result->setLoc(startLine, endLine); return result; @@ -501,8 +490,6 @@ public: void addVar(const Identifier* ident, int attrs) { - if (m_globalData->propertyNames->arguments == *ident) - usesArguments(); m_scope.m_varDeclarations->data.append(std::make_pair(ident, attrs)); } @@ -517,8 +504,6 @@ public: return new (m_globalData) CommaNode(lineNumber, list, init); } - int evalCount() const { return m_evalCount; } - void appendBinaryExpressionInfo(int& operandStackDepth, ExpressionNode* current, int exprStart, int lhs, int rhs, bool hasAssignments) { operandStackDepth++; @@ -605,13 +590,11 @@ private: Scope(JSGlobalData* globalData) : m_varDeclarations(new (globalData) ParserArenaData<DeclarationStacks::VarStack>) , m_funcDeclarations(new (globalData) ParserArenaData<DeclarationStacks::FunctionStack>) - , m_features(0) , m_numConstants(0) { } ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; - int m_features; int m_numConstants; }; @@ -621,15 +604,6 @@ private: } void incConstants() { m_scope.m_numConstants++; } - void usesThis() { m_scope.m_features |= ThisFeature; } - void usesCatch() { m_scope.m_features |= CatchFeature; } - void usesArguments() { m_scope.m_features |= ArgumentsFeature; } - void usesWith() { m_scope.m_features |= WithFeature; } - void usesEval() - { - m_evalCount++; - m_scope.m_features |= EvalFeature; - } ExpressionNode* createNumber(int lineNumber, double d) { return new (m_globalData) NumberNode(lineNumber, d); @@ -642,7 +616,6 @@ private: Vector<AssignmentInfo, 10> m_assignmentInfoStack; Vector<pair<int, int>, 10> m_binaryOperatorStack; Vector<pair<int, int>, 10> m_unaryTokenStack; - int m_evalCount; }; ExpressionNode* ASTBuilder::makeTypeOfNode(int lineNumber, ExpressionNode* expr) @@ -792,10 +765,8 @@ ExpressionNode* ASTBuilder::makeFunctionCallNode(int lineNumber, ExpressionNode* if (func->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(func); const Identifier& identifier = resolve->identifier(); - if (identifier == m_globalData->propertyNames->eval) { - usesEval(); + if (identifier == m_globalData->propertyNames->eval) return new (m_globalData) EvalFunctionCallNode(lineNumber, args, divot, divot - start, end - divot); - } return new (m_globalData) FunctionCallResolveNode(lineNumber, identifier, args, divot, divot - start, end - divot); } if (func->isBracketAccessorNode()) { diff --git a/Source/JavaScriptCore/parser/Lexer.cpp b/Source/JavaScriptCore/parser/Lexer.cpp index 015c1509d..8d50afc54 100644 --- a/Source/JavaScriptCore/parser/Lexer.cpp +++ b/Source/JavaScriptCore/parser/Lexer.cpp @@ -31,7 +31,7 @@ #include "Identifier.h" #include "NodeInfo.h" #include "Nodes.h" -#include "dtoa.h" +#include <wtf/dtoa.h> #include <ctype.h> #include <limits.h> #include <string.h> @@ -95,8 +95,8 @@ enum CharacterType { CharacterWhiteSpace, }; -// 128 ASCII codes -static const unsigned short typesOfASCIICharacters[128] = { +// 256 Latin-1 codes +static const unsigned short typesOfLatin1Characters[256] = { /* 0 - Null */ CharacterInvalid, /* 1 - Start of Heading */ CharacterInvalid, /* 2 - Start of Text */ CharacterInvalid, @@ -225,6 +225,134 @@ static const unsigned short typesOfASCIICharacters[128] = { /* 125 - } */ CharacterCloseBrace, /* 126 - ~ */ CharacterTilde, /* 127 - Delete */ CharacterInvalid, +/* 128 - Cc category */ CharacterInvalid, +/* 129 - Cc category */ CharacterInvalid, +/* 130 - Cc category */ CharacterInvalid, +/* 131 - Cc category */ CharacterInvalid, +/* 132 - Cc category */ CharacterInvalid, +/* 133 - Cc category */ CharacterInvalid, +/* 134 - Cc category */ CharacterInvalid, +/* 135 - Cc category */ CharacterInvalid, +/* 136 - Cc category */ CharacterInvalid, +/* 137 - Cc category */ CharacterInvalid, +/* 138 - Cc category */ CharacterInvalid, +/* 139 - Cc category */ CharacterInvalid, +/* 140 - Cc category */ CharacterInvalid, +/* 141 - Cc category */ CharacterInvalid, +/* 142 - Cc category */ CharacterInvalid, +/* 143 - Cc category */ CharacterInvalid, +/* 144 - Cc category */ CharacterInvalid, +/* 145 - Cc category */ CharacterInvalid, +/* 146 - Cc category */ CharacterInvalid, +/* 147 - Cc category */ CharacterInvalid, +/* 148 - Cc category */ CharacterInvalid, +/* 149 - Cc category */ CharacterInvalid, +/* 150 - Cc category */ CharacterInvalid, +/* 151 - Cc category */ CharacterInvalid, +/* 152 - Cc category */ CharacterInvalid, +/* 153 - Cc category */ CharacterInvalid, +/* 154 - Cc category */ CharacterInvalid, +/* 155 - Cc category */ CharacterInvalid, +/* 156 - Cc category */ CharacterInvalid, +/* 157 - Cc category */ CharacterInvalid, +/* 158 - Cc category */ CharacterInvalid, +/* 159 - Cc category */ CharacterInvalid, +/* 160 - Zs category (nbsp) */ CharacterWhiteSpace, +/* 161 - Po category */ CharacterInvalid, +/* 162 - Sc category */ CharacterInvalid, +/* 163 - Sc category */ CharacterInvalid, +/* 164 - Sc category */ CharacterInvalid, +/* 165 - Sc category */ CharacterInvalid, +/* 166 - So category */ CharacterInvalid, +/* 167 - So category */ CharacterInvalid, +/* 168 - Sk category */ CharacterInvalid, +/* 169 - So category */ CharacterInvalid, +/* 170 - Ll category */ CharacterIdentifierStart, +/* 171 - Pi category */ CharacterInvalid, +/* 172 - Sm category */ CharacterInvalid, +/* 173 - Cf category */ CharacterInvalid, +/* 174 - So category */ CharacterInvalid, +/* 175 - Sk category */ CharacterInvalid, +/* 176 - So category */ CharacterInvalid, +/* 177 - Sm category */ CharacterInvalid, +/* 178 - No category */ CharacterInvalid, +/* 179 - No category */ CharacterInvalid, +/* 180 - Sk category */ CharacterInvalid, +/* 181 - Ll category */ CharacterIdentifierStart, +/* 182 - So category */ CharacterInvalid, +/* 183 - Po category */ CharacterInvalid, +/* 184 - Sk category */ CharacterInvalid, +/* 185 - No category */ CharacterInvalid, +/* 186 - Ll category */ CharacterIdentifierStart, +/* 187 - Pf category */ CharacterInvalid, +/* 188 - No category */ CharacterInvalid, +/* 189 - No category */ CharacterInvalid, +/* 190 - No category */ CharacterInvalid, +/* 191 - Po category */ CharacterInvalid, +/* 192 - Lu category */ CharacterIdentifierStart, +/* 193 - Lu category */ CharacterIdentifierStart, +/* 194 - Lu category */ CharacterIdentifierStart, +/* 195 - Lu category */ CharacterIdentifierStart, +/* 196 - Lu category */ CharacterIdentifierStart, +/* 197 - Lu category */ CharacterIdentifierStart, +/* 198 - Lu category */ CharacterIdentifierStart, +/* 199 - Lu category */ CharacterIdentifierStart, +/* 200 - Lu category */ CharacterIdentifierStart, +/* 201 - Lu category */ CharacterIdentifierStart, +/* 202 - Lu category */ CharacterIdentifierStart, +/* 203 - Lu category */ CharacterIdentifierStart, +/* 204 - Lu category */ CharacterIdentifierStart, +/* 205 - Lu category */ CharacterIdentifierStart, +/* 206 - Lu category */ CharacterIdentifierStart, +/* 207 - Lu category */ CharacterIdentifierStart, +/* 208 - Lu category */ CharacterIdentifierStart, +/* 209 - Lu category */ CharacterIdentifierStart, +/* 210 - Lu category */ CharacterIdentifierStart, +/* 211 - Lu category */ CharacterIdentifierStart, +/* 212 - Lu category */ CharacterIdentifierStart, +/* 213 - Lu category */ CharacterIdentifierStart, +/* 214 - Lu category */ CharacterIdentifierStart, +/* 215 - Sm category */ CharacterInvalid, +/* 216 - Lu category */ CharacterIdentifierStart, +/* 217 - Lu category */ CharacterIdentifierStart, +/* 218 - Lu category */ CharacterIdentifierStart, +/* 219 - Lu category */ CharacterIdentifierStart, +/* 220 - Lu category */ CharacterIdentifierStart, +/* 221 - Lu category */ CharacterIdentifierStart, +/* 222 - Lu category */ CharacterIdentifierStart, +/* 223 - Ll category */ CharacterIdentifierStart, +/* 224 - Ll category */ CharacterIdentifierStart, +/* 225 - Ll category */ CharacterIdentifierStart, +/* 226 - Ll category */ CharacterIdentifierStart, +/* 227 - Ll category */ CharacterIdentifierStart, +/* 228 - Ll category */ CharacterIdentifierStart, +/* 229 - Ll category */ CharacterIdentifierStart, +/* 230 - Ll category */ CharacterIdentifierStart, +/* 231 - Ll category */ CharacterIdentifierStart, +/* 232 - Ll category */ CharacterIdentifierStart, +/* 233 - Ll category */ CharacterIdentifierStart, +/* 234 - Ll category */ CharacterIdentifierStart, +/* 235 - Ll category */ CharacterIdentifierStart, +/* 236 - Ll category */ CharacterIdentifierStart, +/* 237 - Ll category */ CharacterIdentifierStart, +/* 238 - Ll category */ CharacterIdentifierStart, +/* 239 - Ll category */ CharacterIdentifierStart, +/* 240 - Ll category */ CharacterIdentifierStart, +/* 241 - Ll category */ CharacterIdentifierStart, +/* 242 - Ll category */ CharacterIdentifierStart, +/* 243 - Ll category */ CharacterIdentifierStart, +/* 244 - Ll category */ CharacterIdentifierStart, +/* 245 - Ll category */ CharacterIdentifierStart, +/* 246 - Ll category */ CharacterIdentifierStart, +/* 247 - Sm category */ CharacterInvalid, +/* 248 - Ll category */ CharacterIdentifierStart, +/* 249 - Ll category */ CharacterIdentifierStart, +/* 250 - Ll category */ CharacterIdentifierStart, +/* 251 - Ll category */ CharacterIdentifierStart, +/* 252 - Ll category */ CharacterIdentifierStart, +/* 253 - Ll category */ CharacterIdentifierStart, +/* 254 - Ll category */ CharacterIdentifierStart, +/* 255 - Ll category */ CharacterIdentifierStart }; template <typename T> @@ -350,7 +478,7 @@ int Lexer<T>::getUnicodeCharacter() template <typename T> void Lexer<T>::shiftLineTerminator() { - ASSERT(isLineTerminator(m_current)); + ASSERT(isLineTerminator(static_cast<T>(m_current))); int m_prev = m_current; shift(); @@ -368,28 +496,48 @@ ALWAYS_INLINE bool Lexer<T>::lastTokenWasRestrKeyword() const return m_lastToken == CONTINUE || m_lastToken == BREAK || m_lastToken == RETURN || m_lastToken == THROW; } -static NEVER_INLINE bool isNonASCIIIdentStart(int c) +static NEVER_INLINE bool isNonLatin1IdentStart(int c) { return category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other); } -static inline bool isIdentStart(int c) +static ALWAYS_INLINE bool isLatin1(LChar) { - return isASCII(c) ? typesOfASCIICharacters[c] == CharacterIdentifierStart : isNonASCIIIdentStart(c); + return true; +} + +static ALWAYS_INLINE bool isLatin1(UChar c) +{ + return c < 256; } -static NEVER_INLINE bool isNonASCIIIdentPart(int c) +static inline bool isIdentStart(LChar c) +{ + return typesOfLatin1Characters[c] == CharacterIdentifierStart; +} + +static inline bool isIdentStart(UChar c) +{ + return isLatin1(c) ? isIdentStart(static_cast<LChar>(c)) : isNonLatin1IdentStart(c); +} + +static NEVER_INLINE bool isNonLatin1IdentPart(int c) { return (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector)) || c == 0x200C || c == 0x200D; } -static ALWAYS_INLINE bool isIdentPart(int c) +static ALWAYS_INLINE bool isIdentPart(LChar c) { // Character types are divided into two groups depending on whether they can be part of an // identifier or not. Those whose type value is less or equal than CharacterNumber can be // part of an identifier. (See the CharacterType definition for more details.) - return isASCII(c) ? typesOfASCIICharacters[c] <= CharacterNumber : isNonASCIIIdentPart(c); + return typesOfLatin1Characters[c] <= CharacterNumber; +} + +static ALWAYS_INLINE bool isIdentPart(UChar c) +{ + return isLatin1(c) ? isIdentPart(static_cast<LChar>(c)) : isNonLatin1IdentPart(c); } static inline int singleEscape(int c) @@ -499,7 +647,7 @@ template <> const LChar* identifierStart = currentCharacter(); - while (isIdentPart(m_current)) + while (m_current != -1 && isIdentPart(static_cast<LChar>(m_current))) shift(); if (UNLIKELY(m_current == '\\')) { @@ -550,7 +698,7 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<UChar>::p UChar orAllChars = 0; - while (isIdentPart(m_current)) { + while (m_current != -1 && isIdentPart(static_cast<UChar>(m_current))) { orAllChars |= m_current; shift(); } @@ -604,7 +752,7 @@ template <bool shouldCreateIdentifier> JSTokenType Lexer<T>::parseIdentifierSlow bool bufferRequired = false; while (true) { - if (LIKELY(isIdentPart(m_current))) { + if (LIKELY(m_current != -1 && isIdentPart(static_cast<T>(m_current)))) { shift(); continue; } @@ -622,10 +770,11 @@ template <bool shouldCreateIdentifier> JSTokenType Lexer<T>::parseIdentifierSlow int character = getUnicodeCharacter(); if (UNLIKELY(character == -1)) return ERRORTOK; - if (UNLIKELY(m_buffer16.size() ? !isIdentPart(character) : !isIdentStart(character))) + UChar ucharacter = static_cast<UChar>(character); + if (UNLIKELY(m_buffer16.size() ? !isIdentPart(ucharacter) : !isIdentStart(ucharacter))) return ERRORTOK; if (shouldCreateIdentifier) - record16(character); + record16(ucharacter); identifierStart = currentCharacter(); } @@ -692,14 +841,15 @@ template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer<T>::parseString(JSTo shiftLineTerminator(); else if (m_current == 'x') { shift(); - if (isASCIIHexDigit(m_current) && isASCIIHexDigit(peek(1))) { - int prev = m_current; - shift(); - if (shouldBuildStrings) - record8(convertHex(prev, m_current)); - shift(); - } else if (shouldBuildStrings) - record8('x'); + if (!isASCIIHexDigit(m_current) || !isASCIIHexDigit(peek(1))) { + m_lexErrorMessage = "\\x can only be followed by a hex character sequence"; + return false; + } + int prev = m_current; + shift(); + if (shouldBuildStrings) + record8(convertHex(prev, m_current)); + shift(); } else { setOffset(startingOffset); setLineNumber(startingLineNumber); @@ -752,18 +902,19 @@ template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenDat if (shouldBuildStrings) record16(escape); shift(); - } else if (UNLIKELY(isLineTerminator(m_current))) + } else if (UNLIKELY(isLineTerminator(static_cast<T>(m_current)))) shiftLineTerminator(); else if (m_current == 'x') { shift(); - if (isASCIIHexDigit(m_current) && isASCIIHexDigit(peek(1))) { - int prev = m_current; - shift(); - if (shouldBuildStrings) - record16(convertHex(prev, m_current)); - shift(); - } else if (shouldBuildStrings) - record16('x'); + if (!isASCIIHexDigit(m_current) || !isASCIIHexDigit(peek(1))) { + m_lexErrorMessage = "\\x can only be followed by a hex character sequence"; + return false; + } + int prev = m_current; + shift(); + if (shouldBuildStrings) + record16(convertHex(prev, m_current)); + shift(); } else if (m_current == 'u') { shift(); int character = getUnicodeCharacter(); @@ -824,7 +975,7 @@ template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenDat // as possible, and lets through all common ASCII characters. if (UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) { // New-line or end of input is not allowed - if (UNLIKELY(isLineTerminator(m_current)) || UNLIKELY(m_current == -1)) { + if (UNLIKELY(m_current == -1) || UNLIKELY(isLineTerminator(static_cast<T>(m_current)))) { m_lexErrorMessage = "Unexpected EOF"; return false; } @@ -1004,7 +1155,7 @@ ALWAYS_INLINE bool Lexer<T>::parseMultilineComment() if (UNLIKELY(m_current == -1)) return false; - if (isLineTerminator(m_current)) { + if (isLineTerminator(static_cast<T>(m_current))) { shiftLineTerminator(); m_terminator = true; } else @@ -1033,7 +1184,7 @@ JSTokenType Lexer<T>::lex(JSTokenData* tokenData, JSTokenInfo* tokenInfo, unsign m_terminator = false; start: - while (isWhiteSpace(m_current)) + while (m_current != -1 && isWhiteSpace(static_cast<T>(m_current))) shift(); int startOffset = currentOffset(); @@ -1044,11 +1195,11 @@ start: m_delimited = false; CharacterType type; - if (LIKELY(isASCII(m_current))) - type = static_cast<CharacterType>(typesOfASCIICharacters[m_current]); - else if (isNonASCIIIdentStart(m_current)) + if (LIKELY(isLatin1(static_cast<T>(m_current)))) + type = static_cast<CharacterType>(typesOfLatin1Characters[m_current]); + else if (isNonLatin1IdentStart(m_current)) type = CharacterIdentifierStart; - else if (isLineTerminator(m_current)) + else if (isLineTerminator(static_cast<T>(m_current))) type = CharacterLineTerminator; else type = CharacterInvalid; @@ -1335,7 +1486,7 @@ inNumberAfterDecimalPoint: } // No identifiers allowed directly after numeric literal, e.g. "3in" is bad. - if (UNLIKELY(isIdentStart(m_current))) { + if (UNLIKELY(m_current != -1 && isIdentStart(static_cast<T>(m_current)))) { m_lexErrorMessage = "At least one digit must occur after a decimal point"; goto returnError; } @@ -1355,7 +1506,7 @@ inNumberAfterDecimalPoint: token = STRING; break; case CharacterIdentifierStart: - ASSERT(isIdentStart(m_current)); + ASSERT(isIdentStart(static_cast<T>(m_current))); // Fall through into CharacterBackSlash. case CharacterBackSlash: if (lexerFlags & LexexFlagsDontBuildKeywords) @@ -1364,7 +1515,7 @@ inNumberAfterDecimalPoint: token = parseIdentifier<true>(tokenData, lexerFlags, strictMode); break; case CharacterLineTerminator: - ASSERT(isLineTerminator(m_current)); + ASSERT(isLineTerminator(static_cast<T>(m_current))); shiftLineTerminator(); m_atLineStart = true; m_terminator = true; @@ -1382,7 +1533,7 @@ inNumberAfterDecimalPoint: goto returnToken; inSingleLineComment: - while (!isLineTerminator(m_current)) { + while (!isLineTerminator(static_cast<T>(m_current))) { if (UNLIKELY(m_current == -1)) return EOFTOK; shift(); @@ -1430,7 +1581,7 @@ bool Lexer<T>::scanRegExp(const Identifier*& pattern, const Identifier*& flags, while (true) { int current = m_current; - if (isLineTerminator(current) || current == -1) { + if (isLineTerminator(static_cast<T>(current)) || current == -1) { m_buffer16.resize(0); return false; } @@ -1463,7 +1614,7 @@ bool Lexer<T>::scanRegExp(const Identifier*& pattern, const Identifier*& flags, pattern = makeIdentifier(m_buffer16.data(), m_buffer16.size()); m_buffer16.resize(0); - while (isIdentPart(m_current)) { + while (m_current != -1 && isIdentPart(static_cast<T>(m_current))) { record16(m_current); shift(); } @@ -1483,7 +1634,7 @@ bool Lexer<T>::skipRegExp() while (true) { int current = m_current; - if (isLineTerminator(current) || current == -1) + if (isLineTerminator(static_cast<T>(current)) || current == -1) return false; shift(); @@ -1509,7 +1660,7 @@ bool Lexer<T>::skipRegExp() } } - while (isIdentPart(m_current)) + while (m_current != -1 && isIdentPart(static_cast<T>(m_current))) shift(); return true; diff --git a/Source/JavaScriptCore/parser/Lexer.h b/Source/JavaScriptCore/parser/Lexer.h index 6fe0c9a1c..81558fa96 100644 --- a/Source/JavaScriptCore/parser/Lexer.h +++ b/Source/JavaScriptCore/parser/Lexer.h @@ -79,8 +79,8 @@ public: ~Lexer(); // Character manipulation functions. - static bool isWhiteSpace(int character); - static bool isLineTerminator(int character); + static bool isWhiteSpace(T character); + static bool isLineTerminator(T character); static unsigned char convertHex(int c1, int c2); static UChar convertUnicode(int c1, int c2, int c3, int c4); @@ -191,14 +191,26 @@ private: JSGlobalData* m_globalData; }; -template <typename T> -ALWAYS_INLINE bool Lexer<T>::isWhiteSpace(int ch) +template <> +ALWAYS_INLINE bool Lexer<LChar>::isWhiteSpace(LChar ch) { - return isASCII(ch) ? (ch == ' ' || ch == '\t' || ch == 0xB || ch == 0xC) : (WTF::Unicode::isSeparatorSpace(ch) || ch == 0xFEFF); + return ch == ' ' || ch == '\t' || ch == 0xB || ch == 0xC || ch == 0xA0; } -template <typename T> -ALWAYS_INLINE bool Lexer<T>::isLineTerminator(int ch) +template <> +ALWAYS_INLINE bool Lexer<UChar>::isWhiteSpace(UChar ch) +{ + return (ch < 256) ? Lexer<LChar>::isWhiteSpace(static_cast<LChar>(ch)) : (WTF::Unicode::isSeparatorSpace(ch) || ch == 0xFEFF); +} + +template <> +ALWAYS_INLINE bool Lexer<LChar>::isLineTerminator(LChar ch) +{ + return ch == '\r' || ch == '\n'; +} + +template <> +ALWAYS_INLINE bool Lexer<UChar>::isLineTerminator(UChar ch) { return ch == '\r' || ch == '\n' || (ch & ~1) == 0x2028; } diff --git a/Source/JavaScriptCore/parser/NodeConstructors.h b/Source/JavaScriptCore/parser/NodeConstructors.h index eea3f575c..e496d2342 100644 --- a/Source/JavaScriptCore/parser/NodeConstructors.h +++ b/Source/JavaScriptCore/parser/NodeConstructors.h @@ -417,12 +417,13 @@ namespace JSC { } inline NegateNode::NegateNode(int lineNumber, ExpressionNode* expr) - : UnaryOpNode(lineNumber, ResultType::numberTypeCanReuse(), expr, op_negate) + : UnaryOpNode(lineNumber, ResultType::numberType(), expr, op_negate) { } inline BitwiseNotNode::BitwiseNotNode(int lineNumber, ExpressionNode* expr) - : UnaryOpNode(lineNumber, ResultType::forBitOp(), expr, op_bitnot) + : ExpressionNode(lineNumber, ResultType::forBitOp()) + , m_expr(expr) { } @@ -450,18 +451,18 @@ namespace JSC { } inline MultNode::MultNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::numberTypeCanReuse(), expr1, expr2, op_mul, rightHasAssignments) + : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_mul, rightHasAssignments) { } inline DivNode::DivNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::numberTypeCanReuse(), expr1, expr2, op_div, rightHasAssignments) + : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_div, rightHasAssignments) { } inline ModNode::ModNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::numberTypeCanReuse(), expr1, expr2, op_mod, rightHasAssignments) + : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_mod, rightHasAssignments) { } @@ -471,7 +472,7 @@ namespace JSC { } inline SubNode::SubNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::numberTypeCanReuse(), expr1, expr2, op_sub, rightHasAssignments) + : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_sub, rightHasAssignments) { } @@ -486,7 +487,7 @@ namespace JSC { } inline UnsignedRightShiftNode::UnsignedRightShiftNode(int lineNumber, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) - : BinaryOpNode(lineNumber, ResultType::numberTypeCanReuse(), expr1, expr2, op_urshift, rightHasAssignments) + : BinaryOpNode(lineNumber, ResultType::numberType(), expr1, expr2, op_urshift, rightHasAssignments) { } diff --git a/Source/JavaScriptCore/parser/NodeInfo.h b/Source/JavaScriptCore/parser/NodeInfo.h index 4853aec42..e0d4ffec4 100644 --- a/Source/JavaScriptCore/parser/NodeInfo.h +++ b/Source/JavaScriptCore/parser/NodeInfo.h @@ -26,7 +26,7 @@ namespace JSC { template <typename T> struct NodeInfo { T m_node; - CodeFeatures m_features; + ScopeFlags m_scopeFlags; int m_numConstants; }; @@ -44,7 +44,7 @@ namespace JSC { T m_node; ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; - CodeFeatures m_features; + ScopeFlags m_scopeFlags; int m_numConstants; }; diff --git a/Source/JavaScriptCore/parser/Nodes.cpp b/Source/JavaScriptCore/parser/Nodes.cpp index 8ad474e54..75c848bce 100644 --- a/Source/JavaScriptCore/parser/Nodes.cpp +++ b/Source/JavaScriptCore/parser/Nodes.cpp @@ -73,75 +73,70 @@ StatementNode* SourceElements::singleStatement() const return size == 1 ? m_statements[0] : 0; } -// -----------------------------ScopeNodeData --------------------------- - -ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, int numConstants) - : m_numConstants(numConstants) - , m_statements(statements) -{ - m_arena.swap(arena); - if (varStack) - m_varStack.swap(*varStack); - if (funcStack) - m_functionStack.swap(*funcStack); - m_capturedVariables.swap(capturedVariables); -} - // ------------------------------ ScopeNode ----------------------------- -ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, bool inStrictContext) +ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, ScopeFlags scopeFlags) : StatementNode(lineNumber) , ParserArenaRefCounted(globalData) - , m_features(inStrictContext ? StrictModeFeature : NoFeatures) + , m_scopeFlags(scopeFlags) + , m_numConstants(0) + , m_statements(0) { } -ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants) +ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, ScopeFlags scopeFlags, int numConstants) : StatementNode(lineNumber) , ParserArenaRefCounted(globalData) - , m_data(adoptPtr(new ScopeNodeData(*globalData->parserArena, children, varStack, funcStack, capturedVariables, numConstants))) - , m_features(features) + , m_scopeFlags(scopeFlags) , m_source(source) + , m_numConstants(numConstants) + , m_statements(children) { + m_arena.swap(*globalData->parserArena); + if (varStack) + m_varStack.swap(*varStack); + if (funcStack) + m_functionStack.swap(*funcStack); + m_capturedVariables.swap(capturedVariables); } StatementNode* ScopeNode::singleStatement() const { - return m_data->m_statements ? m_data->m_statements->singleStatement() : 0; + return m_statements ? m_statements->singleStatement() : 0; } // ------------------------------ ProgramNode ----------------------------- -inline ProgramNode::ProgramNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) - : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, features, numConstants) +inline ProgramNode::ProgramNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, ScopeFlags scopeFlags, int numConstants) + : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, scopeFlags, numConstants) { } -PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) +PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, ScopeFlags scopeFlags, int numConstants) { - RefPtr<ProgramNode> node = new ProgramNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, features, numConstants); + RefPtr<ProgramNode> node = new ProgramNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, scopeFlags, numConstants); - ASSERT(node->data()->m_arena.last() == node); - node->data()->m_arena.removeLast(); - ASSERT(!node->data()->m_arena.contains(node.get())); + ASSERT(node->m_arena.last() == node); + node->m_arena.removeLast(); + ASSERT(!node->m_arena.contains(node.get())); return node.release(); } // ------------------------------ EvalNode ----------------------------- -inline EvalNode::EvalNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) - : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, features, numConstants) +inline EvalNode::EvalNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, ScopeFlags scopeFlags, int numConstants) + : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, scopeFlags, numConstants) { } -PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) +PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, ScopeFlags scopeFlags, int numConstants) { - RefPtr<EvalNode> node = new EvalNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, features, numConstants); + RefPtr<EvalNode> node = new EvalNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, scopeFlags, numConstants); - ASSERT(node->data()->m_arena.last() == node); - node->data()->m_arena.removeLast(); - ASSERT(!node->data()->m_arena.contains(node.get())); + ASSERT(node->m_arena.last() == node); + node->m_arena.removeLast(); + ASSERT(!node->m_arena.contains(node.get())); return node.release(); } @@ -154,13 +149,13 @@ FunctionParameters::FunctionParameters(ParameterNode* firstParameter) append(parameter->ident()); } -inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, bool inStrictContext) - : ScopeNode(globalData, lineNumber, inStrictContext) +inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, ScopeFlags scopeFlags) + : ScopeNode(globalData, lineNumber, scopeFlags) { } -inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) - : ScopeNode(globalData, lineNumber, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants) +inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, ScopeFlags scopeFlags, int numConstants) + : ScopeNode(globalData, lineNumber, sourceCode, children, varStack, funcStack, capturedVariables, scopeFlags, numConstants) { } @@ -177,18 +172,18 @@ void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters, m_ident = ident; } -FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, bool inStrictContext) +FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, ScopeFlags scopeFlags) { - return new FunctionBodyNode(globalData, lineNumber, inStrictContext); + return new FunctionBodyNode(globalData, lineNumber, scopeFlags); } -PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) +PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, ScopeFlags scopeFlags, int numConstants) { - RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants); + RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, sourceCode, scopeFlags, numConstants); - ASSERT(node->data()->m_arena.last() == node); - node->data()->m_arena.removeLast(); - ASSERT(!node->data()->m_arena.contains(node.get())); + ASSERT(node->m_arena.last() == node); + node->m_arena.removeLast(); + ASSERT(!node->m_arena.contains(node.get())); return node.release(); } diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h index 0373766b5..f752b91e9 100644 --- a/Source/JavaScriptCore/parser/Nodes.h +++ b/Source/JavaScriptCore/parser/Nodes.h @@ -47,19 +47,31 @@ namespace JSC { class ScopeChainNode; class ScopeNode; - typedef unsigned CodeFeatures; - - const CodeFeatures NoFeatures = 0; - const CodeFeatures EvalFeature = 1 << 0; - const CodeFeatures ArgumentsFeature = 1 << 1; - const CodeFeatures WithFeature = 1 << 2; - const CodeFeatures CatchFeature = 1 << 3; - const CodeFeatures ThisFeature = 1 << 4; - const CodeFeatures StrictModeFeature = 1 << 5; - const CodeFeatures ShadowsArgumentsFeature = 1 << 6; + typedef unsigned short ScopeFlags; + + const ScopeFlags NoScopeFlags = 0; + + // Some scope flags propagate down the parse tree from parent scopes, like + // strict mode. They are modal to an entire set of nested scopes. + const ScopeFlags StrictModeFlag = 1 << 0; + const ScopeFlags FunctionModeFlag = 1 << 1; + const ScopeFlags AllScopeModeFlags = StrictModeFlag | FunctionModeFlag; + + // Some scope flags refer only to a specific scope, and don't propagate down + // or up. + const ScopeFlags BlockScopeFlag = 1 << 4; + const ScopeFlags AllScopeKindFlags = BlockScopeFlag; + + // Other flags reflect uses within nested scopes, and so propagate up + // from the leaves. + const ScopeFlags UsesEvalFlag = 1 << 8; + const ScopeFlags UsesArgumentsFlag = 1 << 9; + const ScopeFlags UsesWithFlag = 1 << 10; + const ScopeFlags UsesCatchFlag = 1 << 11; + const ScopeFlags UsesThisFlag = 1 << 12; + const ScopeFlags ShadowsArgumentsFlag = 1 << 13; + const ScopeFlags AllScopeUsesFlags = UsesEvalFlag | UsesArgumentsFlag | UsesWithFlag | UsesCatchFlag | UsesThisFlag | ShadowsArgumentsFlag; - const CodeFeatures AllFeatures = EvalFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature; - enum Operator { OpEqual, OpPlusEq, @@ -793,11 +805,20 @@ namespace JSC { NegateNode(int, ExpressionNode*); }; - class BitwiseNotNode : public UnaryOpNode { + class BitwiseNotNode : public ExpressionNode { public: BitwiseNotNode(int, ExpressionNode*); - }; + protected: + ExpressionNode* expr() { return m_expr; } + const ExpressionNode* expr() const { return m_expr; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + }; + class LogicalNotNode : public UnaryOpNode { public: LogicalNotNode(int, ExpressionNode*); @@ -1369,62 +1390,53 @@ namespace JSC { ParameterNode* m_next; }; - struct ScopeNodeData { - WTF_MAKE_FAST_ALLOCATED; + class ScopeNode : public StatementNode, public ParserArenaRefCounted { public: typedef DeclarationStacks::VarStack VarStack; typedef DeclarationStacks::FunctionStack FunctionStack; - ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, int numConstants); + ScopeNode(JSGlobalData*, int, ScopeFlags); + ScopeNode(JSGlobalData*, int, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, ScopeFlags, int numConstants); - ParserArena m_arena; - VarStack m_varStack; - FunctionStack m_functionStack; - int m_numConstants; - SourceElements* m_statements; - IdentifierSet m_capturedVariables; - }; + using ParserArenaRefCounted::operator new; - class ScopeNode : public StatementNode, public ParserArenaRefCounted { - public: - typedef DeclarationStacks::VarStack VarStack; - typedef DeclarationStacks::FunctionStack FunctionStack; + void destroyData() + { + m_arena.reset(); + m_varStack.clear(); + m_functionStack.clear(); + m_statements = 0; + m_capturedVariables.clear(); + } - ScopeNode(JSGlobalData*, int, bool inStrictContext); - ScopeNode(JSGlobalData*, int, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants); + bool hasCapturedVariables() const { return !!m_capturedVariables.size(); } + size_t capturedVariableCount() const { return m_capturedVariables.size(); } + bool captures(const Identifier& ident) { return m_capturedVariables.contains(ident.impl()); } - using ParserArenaRefCounted::operator new; + void addScopeFlags(ScopeFlags scopeFlags) { m_scopeFlags |= scopeFlags; } + ScopeFlags scopeFlags() const { return m_scopeFlags; } - ScopeNodeData* data() const { return m_data.get(); } - void destroyData() { m_data.clear(); } + bool isStrictMode() const { return m_scopeFlags & StrictModeFlag; } + bool usesEval() const { return m_scopeFlags & UsesEvalFlag; } + bool usesArguments() const { return (m_scopeFlags & UsesArgumentsFlag) && !(m_scopeFlags & ShadowsArgumentsFlag); } + void setUsesArguments() { m_scopeFlags |= UsesArgumentsFlag; } + bool usesThis() const { return m_scopeFlags & UsesThisFlag; } + + bool needsActivationForMoreThanVariables() const { return m_scopeFlags & (UsesEvalFlag | UsesWithFlag | UsesCatchFlag); } + bool needsActivation() const { return hasCapturedVariables() || needsActivationForMoreThanVariables(); } const SourceCode& source() const { return m_source; } 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; } - CodeFeatures features() { return m_features; } - - bool usesEval() const { return m_features & EvalFeature; } - bool usesArguments() const { return (m_features & ArgumentsFeature) && !(m_features & ShadowsArgumentsFeature); } - bool isStrictMode() const { return m_features & StrictModeFeature; } - void setUsesArguments() { m_features |= ArgumentsFeature; } - bool usesThis() const { return m_features & ThisFeature; } - bool needsActivationForMoreThanVariables() const { ASSERT(m_data); return m_features & (EvalFeature | WithFeature | CatchFeature); } - bool needsActivation() const { ASSERT(m_data); return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature | CatchFeature)); } - bool hasCapturedVariables() const { return !!m_data->m_capturedVariables.size(); } - size_t capturedVariableCount() const { return m_data->m_capturedVariables.size(); } - bool captures(const Identifier& ident) { return m_data->m_capturedVariables.contains(ident.impl()); } - - VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; } - FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; } + VarStack& varStack() { return m_varStack; } + FunctionStack& functionStack() { return m_functionStack; } int neededConstants() { - ASSERT(m_data); // We may need 2 more constants than the count given by the parser, // because of the various uses of jsUndefined() and jsNull(). - return m_data->m_numConstants + 2; + return m_numConstants + 2; } StatementNode* singleStatement() const; @@ -1433,22 +1445,27 @@ namespace JSC { protected: void setSource(const SourceCode& source) { m_source = source; } + ParserArena m_arena; private: - OwnPtr<ScopeNodeData> m_data; - CodeFeatures m_features; + ScopeFlags m_scopeFlags; SourceCode m_source; + VarStack m_varStack; + FunctionStack m_functionStack; + int m_numConstants; + SourceElements* m_statements; + IdentifierSet m_capturedVariables; }; class ProgramNode : public ScopeNode { public: static const bool isFunctionNode = false; - static PassRefPtr<ProgramNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + static PassRefPtr<ProgramNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); static const bool scopeIsFunction = false; private: - ProgramNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + ProgramNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; @@ -1456,12 +1473,12 @@ namespace JSC { class EvalNode : public ScopeNode { public: static const bool isFunctionNode = false; - static PassRefPtr<EvalNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + static PassRefPtr<EvalNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); static const bool scopeIsFunction = false; private: - EvalNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + EvalNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; @@ -1478,8 +1495,8 @@ namespace JSC { class FunctionBodyNode : public ScopeNode { public: static const bool isFunctionNode = true; - static FunctionBodyNode* create(JSGlobalData*, int, bool isStrictMode); - static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + static FunctionBodyNode* create(JSGlobalData*, int, ScopeFlags); + static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); FunctionParameters* parameters() const { return m_parameters.get(); } size_t parameterCount() const { return m_parameters->size(); } @@ -1496,8 +1513,8 @@ namespace JSC { static const bool scopeIsFunction = true; private: - FunctionBodyNode(JSGlobalData*, int, bool inStrictContext); - FunctionBodyNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + FunctionBodyNode(JSGlobalData*, int, ScopeFlags); + FunctionBodyNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); Identifier m_ident; Identifier m_inferredName; diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp index 939d2696c..f58847fd2 100644 --- a/Source/JavaScriptCore/parser/Parser.cpp +++ b/Source/JavaScriptCore/parser/Parser.cpp @@ -62,11 +62,12 @@ Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, Fu m_lexer->setCode(source, m_arena); m_functionCache = source.provider()->cache(); - ScopeRef scope = pushScope(); - if (parserMode == JSParseFunctionCode) - scope->setIsFunction(); + ScopeFlags scopeFlags = NoScopeFlags; if (strictness == JSParseStrict) - scope->setStrictMode(); + scopeFlags |= StrictModeFlag; + if (parserMode == JSParseFunctionCode) + scopeFlags |= FunctionModeFlag; + ScopeRef scope = pushScope(scopeFlags); if (parameters) { for (unsigned i = 0; i < parameters->size(); i++) scope->declareParameter(¶meters->at(i)); @@ -96,16 +97,12 @@ UString Parser<LexerType>::parseInner() IdentifierSet capturedVariables; scope->getCapturedVariables(capturedVariables); - CodeFeatures features = context.features(); - if (scope->strictMode()) - features |= StrictModeFeature; - if (scope->shadowsArguments()) - features |= ShadowsArgumentsFeature; + ScopeFlags scopeFlags = scope->modeFlags() | scope->usesFlags(); unsigned functionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0; if (functionCacheSize != oldFunctionCacheSize) m_lexer->sourceProvider()->notifyCacheSizeChanged(functionCacheSize - oldFunctionCacheSize); - didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features, + didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), scopeFlags, m_lastLine, context.numConstants(), capturedVariables); return parseError; @@ -113,13 +110,13 @@ UString Parser<LexerType>::parseInner() template <typename LexerType> void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack, - ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants, IdentifierSet& capturedVars) + ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, ScopeFlags scopeFlags, int lastLine, int numConstants, IdentifierSet& capturedVars) { m_sourceElements = sourceElements; m_varDeclarations = varStack; m_funcDeclarations = funcStack; m_capturedVariables.swap(capturedVars); - m_features = features; + m_scopeFlags = scopeFlags; m_lastLine = lastLine; m_numConstants = numConstants; } @@ -147,7 +144,7 @@ template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements Parser< if (directive) { // "use strict" must be the exact literal without escape sequences or line continuation. if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_globalData->propertyNames->useStrictIdentifier == *directive) { - setStrictMode(); + currentScope()->setFlags(StrictModeFlag); hasSetStrict = true; failIfFalse(isValidStrictMode()); m_lexer->setOffset(startOffset); @@ -255,6 +252,8 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarati next(); bool hasInitializer = match(EQUAL); failIfFalseIfStrictWithNameAndMessage(declareVariable(name), "Cannot declare a variable named", name->impl(), "in strict mode."); + if (m_globalData->propertyNames->arguments == *name) + currentScope()->setFlags(UsesArgumentsFlag); context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0); if (hasInitializer) { int varDivot = tokenStart() + 1; @@ -289,6 +288,8 @@ template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDecl next(); bool hasInitializer = match(EQUAL); declareVariable(name); + if (m_globalData->propertyNames->arguments == *name) + currentScope()->setFlags(UsesArgumentsFlag); context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0)); TreeExpression initializer = 0; if (hasInitializer) { @@ -511,7 +512,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement { ASSERT(match(WITH)); failIfTrueWithMessage(strictMode(), "'with' statements are not valid in strict mode"); - currentScope()->setNeedsFullActivation(); + currentScope()->setFlags(UsesWithFlag); int startLine = tokenLine(); next(); consumeOrFail(OPENPAREN); @@ -526,6 +527,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement TreeStatement statement = parseStatement(context, unused); failIfFalse(statement); + currentScope()->setFlags(UsesWithFlag); return context.createWithStatement(m_lexer->lastLineNumber(), expr, statement, start, end, startLine, endLine); } @@ -614,15 +616,15 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement( int lastLine = m_lastLine; if (match(CATCH)) { - currentScope()->setNeedsFullActivation(); + currentScope()->setFlags(UsesCatchFlag); next(); consumeOrFail(OPENPAREN); matchOrFail(IDENT); ident = m_token.m_data.ident; next(); - AutoPopScopeRef catchScope(this, pushScope()); + AutoPopScopeRef catchScope(this, pushScope(currentScope()->modeFlags())); failIfFalseIfStrictWithNameAndMessage(declareVariable(ident), "Cannot declare a variable named", ident->impl(), "in strict mode"); - catchScope->preventNewDecls(); + currentScope()->setFlags(BlockScopeFlag | UsesCatchFlag); consumeOrFail(CLOSEPAREN); matchOrFail(OPENBRACE); catchBlock = parseBlockStatement(context); @@ -759,7 +761,7 @@ template <typename LexerType> template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(TreeBuilder& context) { if (match(CLOSEBRACE)) - return context.createFunctionBody(m_lexer->lastLineNumber(), strictMode()); + return context.createFunctionBody(m_lexer->lastLineNumber(), currentScope()->modeFlags()); DepthManager statementDepth(&m_statementDepth); m_statementDepth = 0; typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<JSGlobalData*>(m_globalData), m_lexer.get()); @@ -770,8 +772,7 @@ template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBo template <typename LexerType> template <FunctionRequirements requirements, bool nameIsInContainingScope, class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, int& openBracePos, int& closeBracePos, int& bodyStartLine) { - AutoPopScopeRef functionScope(this, pushScope()); - functionScope->setIsFunction(); + AutoPopScopeRef functionScope(this, pushScope(currentScope()->modeFlags() | FunctionModeFlag)); if (match(IDENT)) { name = m_token.m_data.ident; next(); @@ -793,8 +794,8 @@ template <FunctionRequirements requirements, bool nameIsInContainingScope, class // If we know about this function already, we can use the cached info and skip the parser to the end of the function. if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBracePos) : 0) { // If we're in a strict context, the cached function info must say it was strict too. - ASSERT(!strictMode() || cachedInfo->strictMode); - body = context.createFunctionBody(m_lexer->lastLineNumber(), cachedInfo->strictMode); + ASSERT(!strictMode() || (cachedInfo->scopeFlags & StrictModeFlag)); + body = context.createFunctionBody(m_lexer->lastLineNumber(), cachedInfo->scopeFlags); functionScope->restoreFunctionInfo(cachedInfo); failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo)); @@ -854,6 +855,8 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDecla failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine))); failIfFalse(name); failIfFalseIfStrict(declareVariable(name)); + if (*name == m_globalData->propertyNames->arguments) + currentScope()->setFlags(UsesArgumentsFlag); return context.createFuncDeclStatement(m_lexer->lastLineNumber(), name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine); } @@ -1204,7 +1207,6 @@ template <bool complete, class TreeBuilder> TreeProperty Parser<LexerType>::pars return context.template createProperty<complete>(ident, node, PropertyNode::Constant); } failIfFalse(wasIdent); - matchOrFail(IDENT); const Identifier* accessorName = 0; TreeFormalParameterList parameters = 0; TreeFunctionBody body = 0; @@ -1218,8 +1220,19 @@ template <bool complete, class TreeBuilder> TreeProperty Parser<LexerType>::pars type = PropertyNode::Setter; else fail(); - failIfFalse((parseFunctionInfo<FunctionNeedsName, false>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine))); - return context.template createGetterOrSetterProperty<complete>(m_lexer->lastLineNumber(), type, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine); + const Identifier* stringPropertyName = 0; + double numericPropertyName = 0; + if (m_token.m_type == IDENT || m_token.m_type == STRING) + stringPropertyName = m_token.m_data.ident; + else if (m_token.m_type == NUMBER) + numericPropertyName = m_token.m_data.doubleValue; + else + fail(); + next(); + failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine))); + if (stringPropertyName) + return context.template createGetterOrSetterProperty<complete>(m_lexer->lastLineNumber(), type, stringPropertyName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine); + return context.template createGetterOrSetterProperty<complete>(const_cast<JSGlobalData*>(m_globalData), m_lexer->lastLineNumber(), type, numericPropertyName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine); } case NUMBER: { double propertyName = m_token.m_data.doubleValue; @@ -1391,13 +1404,18 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpre } case THISTOKEN: { next(); + currentScope()->setFlags(UsesThisFlag); return context.thisExpr(m_lexer->lastLineNumber()); } case IDENT: { int start = tokenStart(); const Identifier* ident = m_token.m_data.ident; next(); - currentScope()->useVariable(ident, m_globalData->propertyNames->eval == *ident); + if (m_globalData->propertyNames->eval == *ident) + currentScope()->setFlags(UsesEvalFlag); + else if (m_globalData->propertyNames->arguments == *ident) + currentScope()->setFlags(UsesArgumentsFlag); + currentScope()->useVariable(ident); m_lastIdentifier = ident; return context.createResolve(m_lexer->lastLineNumber(), ident, start); } diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h index 9b76242d4..7513d1f11 100644 --- a/Source/JavaScriptCore/parser/Parser.h +++ b/Source/JavaScriptCore/parser/Parser.h @@ -130,30 +130,19 @@ struct ScopeLabelInfo { }; struct Scope { - Scope(const JSGlobalData* globalData, bool isFunction, bool strictMode) + Scope(const JSGlobalData* globalData, ScopeFlags scopeFlags) : m_globalData(globalData) - , m_shadowsArguments(false) - , m_usesEval(false) - , m_needsFullActivation(false) - , m_allowsNewDecls(true) - , m_strictMode(strictMode) - , m_isFunction(isFunction) - , m_isFunctionBoundary(false) + , m_scopeFlags(scopeFlags) , m_isValidStrictMode(true) , m_loopDepth(0) , m_switchDepth(0) { + ASSERT(!(scopeFlags & ~AllScopeModeFlags)); } Scope(const Scope& rhs) : m_globalData(rhs.m_globalData) - , m_shadowsArguments(rhs.m_shadowsArguments) - , m_usesEval(rhs.m_usesEval) - , m_needsFullActivation(rhs.m_needsFullActivation) - , m_allowsNewDecls(rhs.m_allowsNewDecls) - , m_strictMode(rhs.m_strictMode) - , m_isFunction(rhs.m_isFunction) - , m_isFunctionBoundary(rhs.m_isFunctionBoundary) + , m_scopeFlags(rhs.m_scopeFlags) , m_isValidStrictMode(rhs.m_isValidStrictMode) , m_loopDepth(rhs.m_loopDepth) , m_switchDepth(rhs.m_switchDepth) @@ -168,6 +157,22 @@ struct Scope { } } + ALWAYS_INLINE ScopeFlags scopeFlags() const { return m_scopeFlags; } + ALWAYS_INLINE ScopeFlags modeFlags() const { return m_scopeFlags & AllScopeModeFlags; } + ALWAYS_INLINE ScopeFlags usesFlags() const { return m_scopeFlags & AllScopeUsesFlags; } + ALWAYS_INLINE void setFlags(ScopeFlags scopeFlags) { m_scopeFlags |= scopeFlags; } + + ALWAYS_INLINE bool needsFullActivation() const { return m_scopeFlags & (UsesEvalFlag | UsesWithFlag | UsesCatchFlag); } + ALWAYS_INLINE bool strictMode() const { return m_scopeFlags & StrictModeFlag; } + ALWAYS_INLINE bool shadowsArguments() const { return m_scopeFlags & ShadowsArgumentsFlag; } + ALWAYS_INLINE bool isFunction() const { return m_scopeFlags & FunctionModeFlag; } + ALWAYS_INLINE bool isBlockScope() const { return m_scopeFlags & BlockScopeFlag; } + ALWAYS_INLINE bool isFunctionBoundary() const { return isFunction() && !isBlockScope(); } + + ALWAYS_INLINE bool allowsNewDecls() const { return !isBlockScope(); } + + ALWAYS_INLINE bool isValidStrictMode() const { return m_isValidStrictMode; } + void startSwitch() { m_switchDepth++; } void endSwitch() { m_switchDepth--; } void startLoop() { m_loopDepth++; } @@ -201,14 +206,6 @@ struct Scope { return 0; } - void setIsFunction() - { - m_isFunction = true; - m_isFunctionBoundary = true; - } - bool isFunction() { return m_isFunction; } - bool isFunctionBoundary() { return m_isFunctionBoundary; } - bool declareVariable(const Identifier* ident) { bool isValidStrictMode = m_globalData->propertyNames->eval != *ident && m_globalData->propertyNames->arguments != *ident; @@ -219,35 +216,28 @@ struct Scope { void declareWrite(const Identifier* ident) { - ASSERT(m_strictMode); + ASSERT(strictMode()); m_writtenVariables.add(ident->impl()); } - void preventNewDecls() { m_allowsNewDecls = false; } - bool allowsNewDecls() const { return m_allowsNewDecls; } - bool declareParameter(const Identifier* ident) { bool isArguments = m_globalData->propertyNames->arguments == *ident; bool isValidStrictMode = m_declaredVariables.add(ident->ustring().impl()).second && m_globalData->propertyNames->eval != *ident && !isArguments; m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; if (isArguments) - m_shadowsArguments = true; + setFlags(ShadowsArgumentsFlag); return isValidStrictMode; } - void useVariable(const Identifier* ident, bool isEval) + void useVariable(const Identifier* ident) { - m_usesEval |= isEval; m_usedVariables.add(ident->ustring().impl()); } - void setNeedsFullActivation() { m_needsFullActivation = true; } - bool collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables) { - if (nestedScope->m_usesEval) - m_usesEval = true; + setFlags(nestedScope->usesFlags()); IdentifierSet::iterator end = nestedScope->m_usedVariables.end(); for (IdentifierSet::iterator ptr = nestedScope->m_usedVariables.begin(); ptr != end; ++ptr) { if (nestedScope->m_declaredVariables.contains(*ptr)) @@ -279,7 +269,7 @@ struct Scope { void getCapturedVariables(IdentifierSet& capturedVariables) { - if (m_needsFullActivation || m_usesEval) { + if (needsFullActivation()) { capturedVariables.swap(m_declaredVariables); return; } @@ -289,11 +279,6 @@ struct Scope { capturedVariables.add(*ptr); } } - void setStrictMode() { m_strictMode = true; } - bool strictMode() const { return m_strictMode; } - bool isValidStrictMode() const { return m_isValidStrictMode; } - bool shadowsArguments() const { return m_shadowsArguments; } - void copyCapturedVariablesToVector(const IdentifierSet& capturedVariables, Vector<RefPtr<StringImpl> >& vector) { IdentifierSet::iterator end = capturedVariables.end(); @@ -307,20 +292,16 @@ struct Scope { void saveFunctionInfo(SourceProviderCacheItem* info) { - ASSERT(m_isFunction); - info->usesEval = m_usesEval; - info->strictMode = m_strictMode; - info->needsFullActivation = m_needsFullActivation; + ASSERT(isFunction()); + info->scopeFlags = m_scopeFlags; copyCapturedVariablesToVector(m_writtenVariables, info->writtenVariables); copyCapturedVariablesToVector(m_usedVariables, info->usedVariables); } void restoreFunctionInfo(const SourceProviderCacheItem* info) { - ASSERT(m_isFunction); - m_usesEval = info->usesEval; - m_strictMode = info->strictMode; - m_needsFullActivation = info->needsFullActivation; + ASSERT(isFunction()); + m_scopeFlags |= info->scopeFlags; unsigned size = info->usedVariables.size(); for (unsigned i = 0; i < size; ++i) m_usedVariables.add(info->usedVariables[i]); @@ -331,13 +312,7 @@ struct Scope { private: const JSGlobalData* m_globalData; - bool m_shadowsArguments : 1; - bool m_usesEval : 1; - bool m_needsFullActivation : 1; - bool m_allowsNewDecls : 1; - bool m_strictMode : 1; - bool m_isFunction : 1; - bool m_isFunctionBoundary : 1; + ScopeFlags m_scopeFlags; bool m_isValidStrictMode : 1; int m_loopDepth; int m_switchDepth; @@ -427,20 +402,14 @@ private: Parser* m_parser; }; - ScopeRef currentScope() + ALWAYS_INLINE ScopeRef currentScope() { return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1); } - ScopeRef pushScope() + ScopeRef pushScope(ScopeFlags scopeFlags) { - bool isFunction = false; - bool isStrict = false; - if (!m_scopeStack.isEmpty()) { - isStrict = m_scopeStack.last().strictMode(); - isFunction = m_scopeStack.last().isFunction(); - } - m_scopeStack.append(Scope(m_globalData, isFunction, isStrict)); + m_scopeStack.append(Scope(m_globalData, scopeFlags)); return currentScope(); } @@ -492,7 +461,7 @@ private: UString parseInner(); void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, - ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures, + ParserArenaData<DeclarationStacks::FunctionStack>*, ScopeFlags, int, int, IdentifierSet&); // Used to determine type of error to report. @@ -823,14 +792,13 @@ private: m_errorMessage = UString(msg); } - void startLoop() { currentScope()->startLoop(); } - void endLoop() { currentScope()->endLoop(); } - void startSwitch() { currentScope()->startSwitch(); } - void endSwitch() { currentScope()->endSwitch(); } - void setStrictMode() { currentScope()->setStrictMode(); } - bool strictMode() { return currentScope()->strictMode(); } - bool isValidStrictMode() { return currentScope()->isValidStrictMode(); } - bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); } + ALWAYS_INLINE void startLoop() { currentScope()->startLoop(); } + ALWAYS_INLINE void endLoop() { currentScope()->endLoop(); } + ALWAYS_INLINE void startSwitch() { currentScope()->startSwitch(); } + ALWAYS_INLINE void endSwitch() { currentScope()->endSwitch(); } + ALWAYS_INLINE bool strictMode() { return currentScope()->strictMode(); } + ALWAYS_INLINE bool isValidStrictMode() { return currentScope()->isValidStrictMode(); } + ALWAYS_INLINE bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); } bool breakIsValid() { ScopeRef current = currentScope(); @@ -949,7 +917,7 @@ private: ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; IdentifierSet m_capturedVariables; - CodeFeatures m_features; + ScopeFlags m_scopeFlags; int m_numConstants; struct DepthManager { @@ -1010,7 +978,7 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(JSGlobalObject* lexicalGlobalObj m_funcDeclarations ? &m_funcDeclarations->data : 0, m_capturedVariables, *m_source, - m_features, + m_scopeFlags, m_numConstants); result->setLoc(m_source->firstLine(), m_lastLine); } else if (lexicalGlobalObject) { diff --git a/Source/JavaScriptCore/parser/ParserArena.cpp b/Source/JavaScriptCore/parser/ParserArena.cpp index 56c58dacf..c53f30753 100644 --- a/Source/JavaScriptCore/parser/ParserArena.cpp +++ b/Source/JavaScriptCore/parser/ParserArena.cpp @@ -34,7 +34,6 @@ namespace JSC { ParserArena::ParserArena() : m_freeableMemory(0) , m_freeablePoolEnd(0) - , m_identifierArena(adoptPtr(new IdentifierArena)) { } @@ -88,7 +87,8 @@ void ParserArena::reset() m_freeableMemory = 0; m_freeablePoolEnd = 0; - m_identifierArena->clear(); + if (m_identifierArena) + m_identifierArena->clear(); m_freeablePools.clear(); m_deletableObjects.clear(); m_refCountedObjects.clear(); @@ -108,7 +108,7 @@ void ParserArena::allocateFreeablePool() bool ParserArena::isEmpty() const { return !m_freeablePoolEnd - && m_identifierArena->isEmpty() + && (!m_identifierArena || m_identifierArena->isEmpty()) && m_freeablePools.isEmpty() && m_deletableObjects.isEmpty() && m_refCountedObjects.isEmpty(); diff --git a/Source/JavaScriptCore/parser/ParserArena.h b/Source/JavaScriptCore/parser/ParserArena.h index 49f0ab6bf..067b83a26 100644 --- a/Source/JavaScriptCore/parser/ParserArena.h +++ b/Source/JavaScriptCore/parser/ParserArena.h @@ -161,7 +161,12 @@ namespace JSC { bool isEmpty() const; JS_EXPORT_PRIVATE void reset(); - IdentifierArena& identifierArena() { return *m_identifierArena; } + IdentifierArena& identifierArena() + { + if (UNLIKELY (!m_identifierArena)) + m_identifierArena = adoptPtr(new IdentifierArena); + return *m_identifierArena; + } private: static const size_t freeablePoolSize = 8000; diff --git a/Source/JavaScriptCore/parser/ResultType.h b/Source/JavaScriptCore/parser/ResultType.h index 27b8112a0..8f30e5b64 100644 --- a/Source/JavaScriptCore/parser/ResultType.h +++ b/Source/JavaScriptCore/parser/ResultType.h @@ -32,8 +32,7 @@ namespace JSC { friend struct OperandTypes; typedef char Type; - static const Type TypeReusable = 1; - static const Type TypeInt32 = 2; + static const Type TypeInt32 = 1; static const Type TypeMaybeNumber = 0x04; static const Type TypeMaybeString = 0x08; @@ -48,11 +47,6 @@ namespace JSC { { } - bool isReusable() - { - return m_type & TypeReusable; - } - bool isInt32() { return m_type & TypeInt32; @@ -93,19 +87,14 @@ namespace JSC { return ResultType(TypeMaybeNumber); } - static ResultType numberTypeCanReuse() - { - return ResultType(TypeReusable | TypeMaybeNumber); - } - - static ResultType numberTypeCanReuseIsInt32() + static ResultType numberTypeIsInt32() { - return ResultType(TypeReusable | TypeInt32 | TypeMaybeNumber); + return ResultType(TypeInt32 | TypeMaybeNumber); } - static ResultType stringOrNumberTypeCanReuse() + static ResultType stringOrNumberType() { - return ResultType(TypeReusable | TypeMaybeNumber | TypeMaybeString); + return ResultType(TypeMaybeNumber | TypeMaybeString); } static ResultType stringType() @@ -121,15 +110,15 @@ namespace JSC { static ResultType forAdd(ResultType op1, ResultType op2) { if (op1.definitelyIsNumber() && op2.definitelyIsNumber()) - return numberTypeCanReuse(); + return numberType(); if (op1.definitelyIsString() || op2.definitelyIsString()) return stringType(); - return stringOrNumberTypeCanReuse(); + return stringOrNumberType(); } static ResultType forBitOp() { - return numberTypeCanReuseIsInt32(); + return numberTypeIsInt32(); } private: diff --git a/Source/JavaScriptCore/parser/SourceProvider.h b/Source/JavaScriptCore/parser/SourceProvider.h index dfc8d88e2..f66a921f5 100644 --- a/Source/JavaScriptCore/parser/SourceProvider.h +++ b/Source/JavaScriptCore/parser/SourceProvider.h @@ -47,7 +47,7 @@ namespace JSC { , m_cache(cache ? cache : new SourceProviderCache) , m_cacheOwned(!cache) { - deprecatedTurnOffVerifier(); + turnOffVerifier(); } virtual ~SourceProvider() { diff --git a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h index 3662367a0..ad7a759ce 100644 --- a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h +++ b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h @@ -61,9 +61,7 @@ public: int closeBraceLine; int closeBracePos; - bool usesEval; - bool strictMode; - bool needsFullActivation; + unsigned short scopeFlags; Vector<RefPtr<StringImpl> > usedVariables; Vector<RefPtr<StringImpl> > writtenVariables; }; diff --git a/Source/JavaScriptCore/parser/SyntaxChecker.h b/Source/JavaScriptCore/parser/SyntaxChecker.h index 32cbf7d6c..2acb5097d 100644 --- a/Source/JavaScriptCore/parser/SyntaxChecker.h +++ b/Source/JavaScriptCore/parser/SyntaxChecker.h @@ -210,11 +210,16 @@ public: return Property(type); return Property(name, type); } + template <bool strict> Property createGetterOrSetterProperty(JSGlobalData* globalData, int, PropertyNode::Type type, double name, int, int, int, int, int, int) + { + if (!strict) + return Property(type); + return Property(&globalData->parserArena->identifierArena().makeNumericIdentifier(globalData, name), type); + } void appendStatement(int, int) { } void addVar(const Identifier*, bool) { } int combineCommaNodes(int, int, int) { return 1; } - int evalCount() const { return 0; } void appendBinaryExpressionInfo(int& operandStackDepth, int expr, int, int, int, bool) { if (!m_topBinaryExpr) |