diff options
author | Steve Block <steveblock@google.com> | 2010-09-29 17:32:26 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2010-09-29 17:35:08 +0100 |
commit | 68513a70bcd92384395513322f1b801e7bf9c729 (patch) | |
tree | 161b50f75a5921d61731bb25e730005994fcec85 /JavaScriptCore/parser/JSParser.cpp | |
parent | fd5c6425ce58eb75211be7718d5dee960842a37e (diff) | |
download | external_webkit-68513a70bcd92384395513322f1b801e7bf9c729.zip external_webkit-68513a70bcd92384395513322f1b801e7bf9c729.tar.gz external_webkit-68513a70bcd92384395513322f1b801e7bf9c729.tar.bz2 |
Merge WebKit at r67908: Initial merge by Git
Change-Id: I43a553e7b3299b28cb6ee8aa035ed70fe342b972
Diffstat (limited to 'JavaScriptCore/parser/JSParser.cpp')
-rw-r--r-- | JavaScriptCore/parser/JSParser.cpp | 134 |
1 files changed, 123 insertions, 11 deletions
diff --git a/JavaScriptCore/parser/JSParser.cpp b/JavaScriptCore/parser/JSParser.cpp index 820811e..540dc3b 100644 --- a/JavaScriptCore/parser/JSParser.cpp +++ b/JavaScriptCore/parser/JSParser.cpp @@ -67,7 +67,7 @@ static const ptrdiff_t kMaxParserStackUsage = 128 * sizeof(void*) * 1024; class JSParser { public: - JSParser(Lexer*, JSGlobalData*, SourceProvider*); + JSParser(Lexer*, JSGlobalData*, FunctionParameters*, SourceProvider*); bool parseProgram(); private: struct AllowInOverride { @@ -161,7 +161,7 @@ private: template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd); template <class TreeBuilder> ALWAYS_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder& context); enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName }; - template <FunctionRequirements, class TreeBuilder> bool parseFunctionInfo(TreeBuilder&, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, int& openBrace, int& closeBrace, int& bodyStartLine); + template <FunctionRequirements, bool nameIsInContainingScope, class TreeBuilder> bool parseFunctionInfo(TreeBuilder&, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, int& openBrace, int& closeBrace, int& bodyStartLine); ALWAYS_INLINE int isBinaryOperator(JSTokenType token); bool allowAutomaticSemicolon(); @@ -199,15 +199,105 @@ private: int m_assignmentCount; int m_nonLHSCount; bool m_syntaxAlreadyValidated; + + struct Scope { + Scope() + : m_usesEval(false) + , m_needsFullActivation(false) + { + } + + void declareVariable(const Identifier* ident) + { + m_declaredVariables.add(ident->ustring().impl()); + } + + void useVariable(const Identifier* ident, bool isEval) + { + m_usesEval |= isEval; + m_usedVariables.add(ident->ustring().impl()); + } + + void needsFullActivation() { m_needsFullActivation = true; } + + void collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables) + { + 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)) + continue; + m_usedVariables.add(*ptr); + if (shouldTrackClosedVariables) + m_closedVariables.add(*ptr); + } + } + + void getCapturedVariables(IdentifierSet& capturedVariables) + { + if (m_needsFullActivation || m_usesEval) { + capturedVariables.swap(m_declaredVariables); + return; + } + for (IdentifierSet::iterator ptr = m_closedVariables.begin(); ptr != m_closedVariables.end(); ++ptr) { + if (!m_declaredVariables.contains(*ptr)) + continue; + capturedVariables.add(*ptr); + } + } + private: + bool m_usesEval; + bool m_needsFullActivation; + IdentifierSet m_declaredVariables; + IdentifierSet m_usedVariables; + IdentifierSet m_closedVariables; + }; + + typedef Vector<Scope, 10> ScopeStack; + + struct ScopeRef { + ScopeRef(ScopeStack* scopeStack, unsigned index) + : m_scopeStack(scopeStack) + , m_index(index) + { + } + Scope* operator->() { return &m_scopeStack->at(m_index); } + unsigned index() const { return m_index; } + private: + ScopeStack* m_scopeStack; + unsigned m_index; + }; + + ScopeRef currentScope() + { + return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1); + } + + ScopeRef pushScope() + { + m_scopeStack.append(Scope()); + return currentScope(); + } + + void popScope(ScopeRef scope, bool shouldTrackClosedVariables) + { + ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1); + ASSERT(m_scopeStack.size() > 1); + m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables); + m_scopeStack.removeLast(); + } + + ScopeStack m_scopeStack; }; -int jsParse(JSGlobalData* globalData, const SourceCode* source) +int jsParse(JSGlobalData* globalData, FunctionParameters* parameters, const SourceCode* source) { - JSParser parser(globalData->lexer, globalData, source->provider()); + JSParser parser(globalData->lexer, globalData, parameters, source->provider()); return parser.parseProgram(); } -JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, SourceProvider* provider) +JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* parameters, SourceProvider* provider) : m_lexer(lexer) , m_endAddress(0) , m_error(false) @@ -223,16 +313,24 @@ JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, SourceProvider* provi m_endAddress = wtfThreadData().approximatedStackStart() - kMaxParserStackUsage; next(); m_lexer->setLastLineNumber(tokenLine()); + ScopeRef scope = pushScope(); + if (parameters) { + for (unsigned i = 0; i < parameters->size(); i++) + scope->declareVariable(¶meters->at(i)); + } } bool JSParser::parseProgram() { ASTBuilder context(m_globalData, m_lexer); + ScopeRef scope = currentScope(); SourceElements* sourceElements = parseSourceElements<ASTBuilder>(context); if (!sourceElements || !consume(EOFTOK)) return true; + IdentifierSet capturedVariables; + scope->getCapturedVariables(capturedVariables); m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), context.features(), - m_lastLine, context.numConstants()); + m_lastLine, context.numConstants(), capturedVariables); return false; } @@ -327,6 +425,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseVarDeclarationList(Tr lastIdent = name; next(); bool hasInitializer = match(EQUAL); + currentScope()->declareVariable(name); context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0); if (hasInitializer) { int varDivot = tokenStart() + 1; @@ -358,6 +457,7 @@ template <class TreeBuilder> TreeConstDeclList JSParser::parseConstDeclarationLi const Identifier* name = m_token.m_data.ident; next(); bool hasInitializer = match(EQUAL); + currentScope()->declareVariable(name); context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0)); TreeExpression initializer = 0; if (hasInitializer) { @@ -552,6 +652,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseThrowStatement(TreeBui template <class TreeBuilder> TreeStatement JSParser::parseWithStatement(TreeBuilder& context) { ASSERT(match(WITH)); + currentScope()->needsFullActivation(); int startLine = tokenLine(); next(); consumeOrFail(OPENPAREN); @@ -650,17 +751,21 @@ template <class TreeBuilder> TreeStatement JSParser::parseTryStatement(TreeBuild int lastLine = m_lastLine; if (match(CATCH)) { + currentScope()->needsFullActivation(); next(); consumeOrFail(OPENPAREN); matchOrFail(IDENT); ident = m_token.m_data.ident; next(); + ScopeRef catchScope = pushScope(); + catchScope->declareVariable(ident); consumeOrFail(CLOSEPAREN); matchOrFail(OPENBRACE); int initialEvalCount = context.evalCount(); catchBlock = parseBlockStatement(context); failIfFalse(catchBlock); catchHasEval = initialEvalCount != context.evalCount(); + popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo); } if (match(FINALLY)) { @@ -757,6 +862,7 @@ template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParame { matchOrFail(IDENT); usesArguments = m_globalData->propertyNames->arguments == *m_token.m_data.ident; + currentScope()->declareVariable(m_token.m_data.ident); TreeFormalParameterList list = context.createFormalParameterList(*m_token.m_data.ident); TreeFormalParameterList tail = list; next(); @@ -764,6 +870,7 @@ template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParame next(); matchOrFail(IDENT); const Identifier* ident = m_token.m_data.ident; + currentScope()->declareVariable(ident); next(); usesArguments = usesArguments || m_globalData->propertyNames->arguments == *ident; tail = context.createFormalParameterList(tail, *ident); @@ -780,11 +887,14 @@ template <class TreeBuilder> TreeFunctionBody JSParser::parseFunctionBody(TreeBu return context.createFunctionBody(); } -template <JSParser::FunctionRequirements requirements, class TreeBuilder> bool JSParser::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, int& openBracePos, int& closeBracePos, int& bodyStartLine) +template <JSParser::FunctionRequirements requirements, bool nameIsInContainingScope, class TreeBuilder> bool JSParser::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, int& openBracePos, int& closeBracePos, int& bodyStartLine) { + ScopeRef functionScope = pushScope(); if (match(IDENT)) { name = m_token.m_data.ident; next(); + if (!nameIsInContainingScope) + functionScope->declareVariable(name); } else if (requirements == FunctionNeedsName) return false; consumeOrFail(OPENPAREN); @@ -804,7 +914,7 @@ template <JSParser::FunctionRequirements requirements, class TreeBuilder> bool J failIfFalse(body); if (usesArguments) context.setUsesArguments(body); - + popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo); matchOrFail(CLOSEBRACE); closeBracePos = m_token.m_data.intValue; next(); @@ -821,8 +931,9 @@ template <class TreeBuilder> TreeStatement JSParser::parseFunctionDeclaration(Tr int openBracePos = 0; int closeBracePos = 0; int bodyStartLine = 0; - failIfFalse(parseFunctionInfo<FunctionNeedsName>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine)); + failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine))); failIfFalse(name); + currentScope()->declareVariable(name); return context.createFuncDeclStatement(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine); } @@ -1113,7 +1224,7 @@ template <bool complete, class TreeBuilder> TreeProperty JSParser::parseProperty type = PropertyNode::Setter; else fail(); - failIfFalse(parseFunctionInfo<FunctionNeedsName>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine)); + failIfFalse((parseFunctionInfo<FunctionNeedsName, false>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine))); return context.template createGetterOrSetterProperty<complete>(type, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine); } case NUMBER: { @@ -1281,6 +1392,7 @@ template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(Tre int start = tokenStart(); const Identifier* ident = m_token.m_data.ident; next(); + currentScope()->useVariable(ident, m_globalData->propertyNames->eval == *ident); return context.createResolve(ident, start); } case STRING: { @@ -1364,7 +1476,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(Tree int closeBracePos = 0; int bodyStartLine = 0; next(); - failIfFalse(parseFunctionInfo<FunctionNoRequirements>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine)); + failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine))); base = context.createFunctionExpr(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine); } else base = parsePrimaryExpression(context); |