diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-11 09:43:24 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-11 09:43:24 +0200 |
commit | 1b914638db989aaa98631a1c1e02c7b2d44805d8 (patch) | |
tree | 87f4fd2c7b38db320079a5de8877890d2ca3c485 /Source/JavaScriptCore/parser | |
parent | 2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (diff) | |
download | qtwebkit-1b914638db989aaa98631a1c1e02c7b2d44805d8.tar.gz |
Imported WebKit commit 9a52e27980f47e8b0d8f8b7cc0fd7b5741bceb92 (http://svn.webkit.org/repository/webkit/trunk@116736)
New snapshot to include QDeclarative* -> QQml* build fixes
Diffstat (limited to 'Source/JavaScriptCore/parser')
-rw-r--r-- | Source/JavaScriptCore/parser/ASTBuilder.h | 44 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/NodeInfo.h | 4 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/Nodes.cpp | 40 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/Nodes.h | 88 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/Parser.cpp | 54 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/Parser.h | 118 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/SourceProviderCacheItem.h | 4 | ||||
-rw-r--r-- | Source/JavaScriptCore/parser/SyntaxChecker.h | 1 |
8 files changed, 200 insertions, 153 deletions
diff --git a/Source/JavaScriptCore/parser/ASTBuilder.h b/Source/JavaScriptCore/parser/ASTBuilder.h index a173cc10f..0eb60cf89 100644 --- a/Source/JavaScriptCore/parser/ASTBuilder.h +++ b/Source/JavaScriptCore/parser/ASTBuilder.h @@ -77,6 +77,7 @@ public: : m_globalData(globalData) , m_sourceCode(sourceCode) , m_scope(globalData) + , m_evalCount(0) { } @@ -118,6 +119,7 @@ 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); } @@ -150,8 +152,17 @@ public: incConstants(); return new (m_globalData) VoidNode(lineNumber, expr); } - 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* 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* createObjectLiteral(int lineNumber) { return new (m_globalData) ObjectLiteralNode(lineNumber); } ExpressionNode* createObjectLiteral(int lineNumber, PropertyListNode* properties) { return new (m_globalData) ObjectLiteralNode(lineNumber, properties); } @@ -252,9 +263,9 @@ public: return result; } - FunctionBodyNode* createFunctionBody(int lineNumber, ScopeFlags scopeFlags) + FunctionBodyNode* createFunctionBody(int lineNumber, bool inStrictContext) { - return FunctionBodyNode::create(m_globalData, lineNumber, scopeFlags); + return FunctionBodyNode::create(m_globalData, lineNumber, inStrictContext); } template <bool> PropertyNode* createGetterOrSetterProperty(int lineNumber, PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) @@ -301,6 +312,8 @@ 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; @@ -413,6 +426,8 @@ 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; } @@ -448,6 +463,7 @@ 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; @@ -490,6 +506,8 @@ 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)); } @@ -504,6 +522,8 @@ 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++; @@ -590,11 +610,13 @@ 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; }; @@ -604,6 +626,15 @@ 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); @@ -616,6 +647,7 @@ 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) @@ -765,8 +797,10 @@ 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) + if (identifier == m_globalData->propertyNames->eval) { + usesEval(); 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/NodeInfo.h b/Source/JavaScriptCore/parser/NodeInfo.h index e0d4ffec4..4853aec42 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; - ScopeFlags m_scopeFlags; + CodeFeatures m_features; int m_numConstants; }; @@ -44,7 +44,7 @@ namespace JSC { T m_node; ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; - ScopeFlags m_scopeFlags; + CodeFeatures m_features; int m_numConstants; }; diff --git a/Source/JavaScriptCore/parser/Nodes.cpp b/Source/JavaScriptCore/parser/Nodes.cpp index 75c848bce..c32e4c73a 100644 --- a/Source/JavaScriptCore/parser/Nodes.cpp +++ b/Source/JavaScriptCore/parser/Nodes.cpp @@ -75,19 +75,19 @@ StatementNode* SourceElements::singleStatement() const // ------------------------------ ScopeNode ----------------------------- -ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, ScopeFlags scopeFlags) +ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, bool inStrictContext) : StatementNode(lineNumber) , ParserArenaRefCounted(globalData) - , m_scopeFlags(scopeFlags) + , m_features(inStrictContext ? StrictModeFeature : NoFeatures) , m_numConstants(0) , m_statements(0) { } -ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, ScopeFlags scopeFlags, int numConstants) +ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants) : StatementNode(lineNumber) , ParserArenaRefCounted(globalData) - , m_scopeFlags(scopeFlags) + , m_features(features) , m_source(source) , m_numConstants(numConstants) , m_statements(children) @@ -107,14 +107,14 @@ StatementNode* ScopeNode::singleStatement() const // ------------------------------ ProgramNode ----------------------------- -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) +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) { } -PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, ScopeFlags scopeFlags, int numConstants) +PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) { - RefPtr<ProgramNode> node = new ProgramNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, scopeFlags, numConstants); + RefPtr<ProgramNode> node = new ProgramNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, features, numConstants); ASSERT(node->m_arena.last() == node); node->m_arena.removeLast(); @@ -125,14 +125,14 @@ PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, int lineNu // ------------------------------ EvalNode ----------------------------- -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) +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) { } -PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, ScopeFlags scopeFlags, int numConstants) +PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) { - RefPtr<EvalNode> node = new EvalNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, scopeFlags, numConstants); + RefPtr<EvalNode> node = new EvalNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, features, numConstants); ASSERT(node->m_arena.last() == node); node->m_arena.removeLast(); @@ -149,13 +149,13 @@ FunctionParameters::FunctionParameters(ParameterNode* firstParameter) append(parameter->ident()); } -inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, ScopeFlags scopeFlags) - : ScopeNode(globalData, lineNumber, scopeFlags) +inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, bool inStrictContext) + : ScopeNode(globalData, lineNumber, inStrictContext) { } -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) +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) { } @@ -172,14 +172,14 @@ void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters, m_ident = ident; } -FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, ScopeFlags scopeFlags) +FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, bool inStrictContext) { - return new FunctionBodyNode(globalData, lineNumber, scopeFlags); + return new FunctionBodyNode(globalData, lineNumber, inStrictContext); } -PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, ScopeFlags scopeFlags, int numConstants) +PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) { - RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, sourceCode, scopeFlags, numConstants); + RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants); ASSERT(node->m_arena.last() == node); node->m_arena.removeLast(); diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h index f752b91e9..26c829da6 100644 --- a/Source/JavaScriptCore/parser/Nodes.h +++ b/Source/JavaScriptCore/parser/Nodes.h @@ -47,31 +47,19 @@ namespace JSC { class ScopeChainNode; class ScopeNode; - 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; + 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; + const CodeFeatures AllFeatures = EvalFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature; + enum Operator { OpEqual, OpPlusEq, @@ -1395,8 +1383,8 @@ namespace JSC { typedef DeclarationStacks::VarStack VarStack; typedef DeclarationStacks::FunctionStack FunctionStack; - ScopeNode(JSGlobalData*, int, ScopeFlags); - ScopeNode(JSGlobalData*, int, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, ScopeFlags, int numConstants); + ScopeNode(JSGlobalData*, int, bool inStrictContext); + ScopeNode(JSGlobalData*, int, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants); using ParserArenaRefCounted::operator new; @@ -1409,26 +1397,24 @@ namespace JSC { m_capturedVariables.clear(); } - 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()); } - - void addScopeFlags(ScopeFlags scopeFlags) { m_scopeFlags |= scopeFlags; } - ScopeFlags scopeFlags() const { return m_scopeFlags; } - - 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 { return m_features & (EvalFeature | WithFeature | CatchFeature); } + bool needsActivation() const { return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature | CatchFeature)); } + 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()); } + VarStack& varStack() { return m_varStack; } FunctionStack& functionStack() { return m_functionStack; } @@ -1448,7 +1434,7 @@ namespace JSC { ParserArena m_arena; private: - ScopeFlags m_scopeFlags; + CodeFeatures m_features; SourceCode m_source; VarStack m_varStack; FunctionStack m_functionStack; @@ -1460,12 +1446,12 @@ namespace JSC { class ProgramNode : public ScopeNode { public: static const bool isFunctionNode = false; - static PassRefPtr<ProgramNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); + static PassRefPtr<ProgramNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); static const bool scopeIsFunction = false; private: - ProgramNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); + ProgramNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; @@ -1473,12 +1459,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&, ScopeFlags, int numConstants); + static PassRefPtr<EvalNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); static const bool scopeIsFunction = false; private: - EvalNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); + EvalNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; @@ -1495,8 +1481,8 @@ namespace JSC { class FunctionBodyNode : public ScopeNode { public: static const bool isFunctionNode = true; - static FunctionBodyNode* create(JSGlobalData*, int, ScopeFlags); - static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); + static FunctionBodyNode* create(JSGlobalData*, int, bool isStrictMode); + static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); FunctionParameters* parameters() const { return m_parameters.get(); } size_t parameterCount() const { return m_parameters->size(); } @@ -1513,8 +1499,8 @@ namespace JSC { static const bool scopeIsFunction = true; private: - FunctionBodyNode(JSGlobalData*, int, ScopeFlags); - FunctionBodyNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants); + FunctionBodyNode(JSGlobalData*, int, bool inStrictContext); + FunctionBodyNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); Identifier m_ident; Identifier m_inferredName; diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp index a03af24df..d88a9a8b7 100644 --- a/Source/JavaScriptCore/parser/Parser.cpp +++ b/Source/JavaScriptCore/parser/Parser.cpp @@ -62,12 +62,11 @@ Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, Fu m_lexer->setCode(source, m_arena); m_functionCache = source.provider()->cache(); - ScopeFlags scopeFlags = NoScopeFlags; - if (strictness == JSParseStrict) - scopeFlags |= StrictModeFlag; + ScopeRef scope = pushScope(); if (parserMode == JSParseFunctionCode) - scopeFlags |= FunctionModeFlag; - ScopeRef scope = pushScope(scopeFlags); + scope->setIsFunction(); + if (strictness == JSParseStrict) + scope->setStrictMode(); if (parameters) { for (unsigned i = 0; i < parameters->size(); i++) scope->declareParameter(¶meters->at(i)); @@ -97,12 +96,16 @@ UString Parser<LexerType>::parseInner() IdentifierSet capturedVariables; scope->getCapturedVariables(capturedVariables); - ScopeFlags scopeFlags = scope->modeFlags() | scope->usesFlags(); + CodeFeatures features = context.features(); + if (scope->strictMode()) + features |= StrictModeFeature; + if (scope->shadowsArguments()) + features |= ShadowsArgumentsFeature; unsigned functionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0; if (functionCacheSize != oldFunctionCacheSize) m_lexer->sourceProvider()->notifyCacheSizeChanged(functionCacheSize - oldFunctionCacheSize); - didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), scopeFlags, + didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features, m_lastLine, context.numConstants(), capturedVariables); return parseError; @@ -110,13 +113,13 @@ UString Parser<LexerType>::parseInner() template <typename LexerType> void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack, - ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, ScopeFlags scopeFlags, int lastLine, int numConstants, IdentifierSet& capturedVars) + ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants, IdentifierSet& capturedVars) { m_sourceElements = sourceElements; m_varDeclarations = varStack; m_funcDeclarations = funcStack; m_capturedVariables.swap(capturedVars); - m_scopeFlags = scopeFlags; + m_features = features; m_lastLine = lastLine; m_numConstants = numConstants; } @@ -144,7 +147,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) { - currentScope()->setFlags(StrictModeFlag); + setStrictMode(); hasSetStrict = true; failIfFalse(isValidStrictMode()); m_lexer->setOffset(startOffset); @@ -252,8 +255,6 @@ 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; @@ -288,8 +289,6 @@ 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) { @@ -512,7 +511,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement { ASSERT(match(WITH)); failIfTrueWithMessage(strictMode(), "'with' statements are not valid in strict mode"); - currentScope()->setFlags(UsesWithFlag); + currentScope()->setNeedsFullActivation(); int startLine = tokenLine(); next(); consumeOrFail(OPENPAREN); @@ -527,7 +526,6 @@ 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); } @@ -616,15 +614,15 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement( int lastLine = m_lastLine; if (match(CATCH)) { - currentScope()->setFlags(UsesCatchFlag); + currentScope()->setNeedsFullActivation(); next(); consumeOrFail(OPENPAREN); matchOrFail(IDENT); ident = m_token.m_data.ident; next(); - AutoPopScopeRef catchScope(this, pushScope(currentScope()->modeFlags())); + AutoPopScopeRef catchScope(this, pushScope()); failIfFalseIfStrictWithNameAndMessage(declareVariable(ident), "Cannot declare a variable named", ident->impl(), "in strict mode"); - currentScope()->setFlags(BlockScopeFlag | UsesCatchFlag); + catchScope->preventNewDecls(); consumeOrFail(CLOSEPAREN); matchOrFail(OPENBRACE); catchBlock = parseBlockStatement(context); @@ -761,7 +759,7 @@ template <typename LexerType> template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(TreeBuilder& context) { if (match(CLOSEBRACE)) - return context.createFunctionBody(m_lexer->lastLineNumber(), currentScope()->modeFlags()); + return context.createFunctionBody(m_lexer->lastLineNumber(), strictMode()); DepthManager statementDepth(&m_statementDepth); m_statementDepth = 0; typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<JSGlobalData*>(m_globalData), m_lexer.get()); @@ -772,7 +770,8 @@ 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(currentScope()->modeFlags() | FunctionModeFlag)); + AutoPopScopeRef functionScope(this, pushScope()); + functionScope->setIsFunction(); if (match(IDENT)) { name = m_token.m_data.ident; next(); @@ -794,8 +793,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->scopeFlags & StrictModeFlag)); - body = context.createFunctionBody(m_lexer->lastLineNumber(), cachedInfo->scopeFlags); + ASSERT(!strictMode() || cachedInfo->strictMode); + body = context.createFunctionBody(m_lexer->lastLineNumber(), cachedInfo->strictMode); functionScope->restoreFunctionInfo(cachedInfo); failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo)); @@ -855,8 +854,6 @@ 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); } @@ -1416,18 +1413,13 @@ 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(); - if (m_globalData->propertyNames->eval == *ident) - currentScope()->setFlags(UsesEvalFlag); - else if (m_globalData->propertyNames->arguments == *ident) - currentScope()->setFlags(UsesArgumentsFlag); - currentScope()->useVariable(ident); + currentScope()->useVariable(ident, m_globalData->propertyNames->eval == *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 c0b13c53a..c2a11d665 100644 --- a/Source/JavaScriptCore/parser/Parser.h +++ b/Source/JavaScriptCore/parser/Parser.h @@ -130,19 +130,30 @@ struct ScopeLabelInfo { }; struct Scope { - Scope(const JSGlobalData* globalData, ScopeFlags scopeFlags) + Scope(const JSGlobalData* globalData, bool isFunction, bool strictMode) : m_globalData(globalData) - , m_scopeFlags(scopeFlags) + , m_shadowsArguments(false) + , m_usesEval(false) + , m_needsFullActivation(false) + , m_allowsNewDecls(true) + , m_strictMode(strictMode) + , m_isFunction(isFunction) + , m_isFunctionBoundary(false) , m_isValidStrictMode(true) , m_loopDepth(0) , m_switchDepth(0) { - ASSERT(!(scopeFlags & ~AllScopeModeFlags)); } Scope(const Scope& rhs) : m_globalData(rhs.m_globalData) - , m_scopeFlags(rhs.m_scopeFlags) + , 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_isValidStrictMode(rhs.m_isValidStrictMode) , m_loopDepth(rhs.m_loopDepth) , m_switchDepth(rhs.m_switchDepth) @@ -157,22 +168,6 @@ 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 usesEval() const { return m_scopeFlags & UsesEvalFlag; } - 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++; } @@ -206,6 +201,14 @@ 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; @@ -216,28 +219,35 @@ struct Scope { void declareWrite(const Identifier* ident) { - ASSERT(strictMode()); + ASSERT(m_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()).isNewEntry && m_globalData->propertyNames->eval != *ident && !isArguments; m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; if (isArguments) - setFlags(ShadowsArgumentsFlag); + m_shadowsArguments = true; return isValidStrictMode; } - void useVariable(const Identifier* ident) + void useVariable(const Identifier* ident, bool isEval) { + m_usesEval |= isEval; m_usedVariables.add(ident->ustring().impl()); } + void setNeedsFullActivation() { m_needsFullActivation = true; } + bool collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables) { - setFlags(nestedScope->usesFlags()); + if (nestedScope->m_usesEval) + m_usesEval = true; IdentifierSet::iterator end = nestedScope->m_usedVariables.end(); for (IdentifierSet::iterator ptr = nestedScope->m_usedVariables.begin(); ptr != end; ++ptr) { if (nestedScope->m_declaredVariables.contains(*ptr)) @@ -269,7 +279,7 @@ struct Scope { void getCapturedVariables(IdentifierSet& capturedVariables) { - if (usesEval()) { + if (m_needsFullActivation || m_usesEval) { capturedVariables.swap(m_declaredVariables); return; } @@ -279,6 +289,11 @@ 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(); @@ -292,16 +307,20 @@ struct Scope { void saveFunctionInfo(SourceProviderCacheItem* info) { - ASSERT(isFunction()); - info->scopeFlags = m_scopeFlags; + ASSERT(m_isFunction); + info->usesEval = m_usesEval; + info->strictMode = m_strictMode; + info->needsFullActivation = m_needsFullActivation; copyCapturedVariablesToVector(m_writtenVariables, info->writtenVariables); copyCapturedVariablesToVector(m_usedVariables, info->usedVariables); } void restoreFunctionInfo(const SourceProviderCacheItem* info) { - ASSERT(isFunction()); - m_scopeFlags |= info->scopeFlags; + ASSERT(m_isFunction); + m_usesEval = info->usesEval; + m_strictMode = info->strictMode; + m_needsFullActivation = info->needsFullActivation; unsigned size = info->usedVariables.size(); for (unsigned i = 0; i < size; ++i) m_usedVariables.add(info->usedVariables[i]); @@ -312,7 +331,13 @@ struct Scope { private: const JSGlobalData* m_globalData; - ScopeFlags m_scopeFlags; + 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; bool m_isValidStrictMode : 1; int m_loopDepth; int m_switchDepth; @@ -402,14 +427,20 @@ private: Parser* m_parser; }; - ALWAYS_INLINE ScopeRef currentScope() + ScopeRef currentScope() { return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1); } - ScopeRef pushScope(ScopeFlags scopeFlags) + ScopeRef pushScope() { - m_scopeStack.append(Scope(m_globalData, 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)); return currentScope(); } @@ -461,7 +492,7 @@ private: UString parseInner(); void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, - ParserArenaData<DeclarationStacks::FunctionStack>*, ScopeFlags, + ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures, int, int, IdentifierSet&); // Used to determine type of error to report. @@ -792,13 +823,14 @@ private: m_errorMessage = UString(msg); } - 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); } + 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); } bool breakIsValid() { ScopeRef current = currentScope(); @@ -917,7 +949,7 @@ private: ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; IdentifierSet m_capturedVariables; - ScopeFlags m_scopeFlags; + CodeFeatures m_features; int m_numConstants; struct DepthManager { @@ -978,7 +1010,7 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(JSGlobalObject* lexicalGlobalObj m_funcDeclarations ? &m_funcDeclarations->data : 0, m_capturedVariables, *m_source, - m_scopeFlags, + m_features, m_numConstants); result->setLoc(m_source->firstLine(), m_lastLine); } else if (lexicalGlobalObject) { diff --git a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h index ad7a759ce..3662367a0 100644 --- a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h +++ b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h @@ -61,7 +61,9 @@ public: int closeBraceLine; int closeBracePos; - unsigned short scopeFlags; + bool usesEval; + bool strictMode; + bool needsFullActivation; Vector<RefPtr<StringImpl> > usedVariables; Vector<RefPtr<StringImpl> > writtenVariables; }; diff --git a/Source/JavaScriptCore/parser/SyntaxChecker.h b/Source/JavaScriptCore/parser/SyntaxChecker.h index 2acb5097d..c2c93756d 100644 --- a/Source/JavaScriptCore/parser/SyntaxChecker.h +++ b/Source/JavaScriptCore/parser/SyntaxChecker.h @@ -220,6 +220,7 @@ public: 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) |