summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/parser
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-03-12 14:11:15 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-03-12 14:11:15 +0100
commitdd91e772430dc294e3bf478c119ef8d43c0a3358 (patch)
tree6f33ce4d5872a5691e0291eb45bf6ab373a5f567 /Source/JavaScriptCore/parser
parentad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (diff)
downloadqtwebkit-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.h49
-rw-r--r--Source/JavaScriptCore/parser/Lexer.cpp245
-rw-r--r--Source/JavaScriptCore/parser/Lexer.h26
-rw-r--r--Source/JavaScriptCore/parser/NodeConstructors.h15
-rw-r--r--Source/JavaScriptCore/parser/NodeInfo.h4
-rw-r--r--Source/JavaScriptCore/parser/Nodes.cpp85
-rw-r--r--Source/JavaScriptCore/parser/Nodes.h139
-rw-r--r--Source/JavaScriptCore/parser/Parser.cpp70
-rw-r--r--Source/JavaScriptCore/parser/Parser.h118
-rw-r--r--Source/JavaScriptCore/parser/ParserArena.cpp6
-rw-r--r--Source/JavaScriptCore/parser/ParserArena.h7
-rw-r--r--Source/JavaScriptCore/parser/ResultType.h27
-rw-r--r--Source/JavaScriptCore/parser/SourceProvider.h2
-rw-r--r--Source/JavaScriptCore/parser/SourceProviderCacheItem.h4
-rw-r--r--Source/JavaScriptCore/parser/SyntaxChecker.h7
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(&parameters->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)