diff options
Diffstat (limited to 'JavaScriptCore/parser')
| -rw-r--r-- | JavaScriptCore/parser/ASTBuilder.h | 6 | ||||
| -rw-r--r-- | JavaScriptCore/parser/JSParser.cpp | 106 | ||||
| -rw-r--r-- | JavaScriptCore/parser/JSParser.h | 4 | ||||
| -rw-r--r-- | JavaScriptCore/parser/Nodes.h | 7 | ||||
| -rw-r--r-- | JavaScriptCore/parser/Parser.cpp | 8 | ||||
| -rw-r--r-- | JavaScriptCore/parser/Parser.h | 4 | ||||
| -rw-r--r-- | JavaScriptCore/parser/SyntaxChecker.h | 6 |
7 files changed, 48 insertions, 93 deletions
diff --git a/JavaScriptCore/parser/ASTBuilder.h b/JavaScriptCore/parser/ASTBuilder.h index 9a68144..04cf272 100644 --- a/JavaScriptCore/parser/ASTBuilder.h +++ b/JavaScriptCore/parser/ASTBuilder.h @@ -576,10 +576,10 @@ public: return result; } - const Identifier& getName(Property property) { return property->name(); } - PropertyNode::Type getType(Property property) { return property->type(); } + const Identifier& getName(Property property) const { return property->name(); } + PropertyNode::Type getType(Property property) const { return property->type(); } - bool isResolve(ExpressionNode* expr) { return expr->isResolveNode(); } + bool isResolve(ExpressionNode* expr) const { return expr->isResolveNode(); } private: struct Scope { diff --git a/JavaScriptCore/parser/JSParser.cpp b/JavaScriptCore/parser/JSParser.cpp index 4b7fcb2..4201555 100644 --- a/JavaScriptCore/parser/JSParser.cpp +++ b/JavaScriptCore/parser/JSParser.cpp @@ -65,13 +65,10 @@ namespace JSC { COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens); -// This matches v8 -static const ptrdiff_t kMaxParserStackUsage = 128 * sizeof(void*) * 1024; - class JSParser { public: JSParser(Lexer*, JSGlobalData*, FunctionParameters*, bool isStrictContext, bool isFunction, SourceProvider*); - bool parseProgram(JSGlobalObject*); + bool parseProgram(); private: struct AllowInOverride { AllowInOverride(JSParser* parser) @@ -174,7 +171,7 @@ private: template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&); template <bool strict, class TreeBuilder> ALWAYS_INLINE TreeProperty parseProperty(TreeBuilder&); template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&); - template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&, bool& usesArguments); + template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&); 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 }; @@ -193,9 +190,7 @@ private: bool canRecurse() { - char sample = 0; - ASSERT(m_endAddress); - return &sample > m_endAddress; + return m_stack.recursionCheck(); } int lastTokenEnd() const @@ -205,7 +200,7 @@ private: ParserArena m_arena; Lexer* m_lexer; - char* m_endAddress; + StackBounds m_stack; bool m_error; JSGlobalData* m_globalData; JSToken m_token; @@ -240,6 +235,7 @@ private: struct Scope { Scope(JSGlobalData* globalData, bool isFunction, bool strictMode) : m_globalData(globalData) + , m_shadowsArguments(false) , m_usesEval(false) , m_needsFullActivation(false) , m_allowsNewDecls(true) @@ -300,22 +296,17 @@ private: ASSERT(m_strictMode); m_writtenVariables.add(ident->impl()); } - - bool deleteProperty(const Identifier* ident) - { - if (m_declaredVariables.contains(ident->impl())) - return false; - m_deletedVariables.add(ident->impl()); - return true; - } - + void preventNewDecls() { m_allowsNewDecls = false; } bool allowsNewDecls() const { return m_allowsNewDecls; } bool declareParameter(const Identifier* ident) { - bool isValidStrictMode = m_declaredVariables.add(ident->ustring().impl()).second && m_globalData->propertyNames->eval != *ident && m_globalData->propertyNames->arguments != *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; return isValidStrictMode; } @@ -347,16 +338,7 @@ private: m_writtenVariables.add(*ptr); } } - if (nestedScope->m_deletedVariables.size()) { - IdentifierSet::iterator end = nestedScope->m_deletedVariables.end(); - for (IdentifierSet::iterator ptr = nestedScope->m_deletedVariables.begin(); ptr != end; ++ptr) { - if (nestedScope->m_declaredVariables.contains(*ptr)) - return false; - if (m_declaredVariables.contains(*ptr)) - return false; - m_deletedVariables.add(*ptr); - } - } + return true; } @@ -369,17 +351,6 @@ private: } } - bool getDeletedVariables(IdentifierSet& deletedVariables) - { - IdentifierSet::iterator end = m_deletedVariables.end(); - for (IdentifierSet::iterator ptr = m_deletedVariables.begin(); ptr != end; ++ptr) { - if (m_declaredVariables.contains(*ptr)) - return false; - } - deletedVariables.swap(m_deletedVariables); - return true; - } - void getCapturedVariables(IdentifierSet& capturedVariables) { if (m_needsFullActivation || m_usesEval) { @@ -395,9 +366,11 @@ private: void setStrictMode() { m_strictMode = true; } bool strictMode() const { return m_strictMode; } bool isValidStrictMode() const { return m_isValidStrictMode; } + bool shadowsArguments() const { return m_shadowsArguments; } private: JSGlobalData* m_globalData; + bool m_shadowsArguments : 1; bool m_usesEval : 1; bool m_needsFullActivation : 1; bool m_allowsNewDecls : 1; @@ -412,7 +385,6 @@ private: IdentifierSet m_usedVariables; IdentifierSet m_closedVariables; IdentifierSet m_writtenVariables; - IdentifierSet m_deletedVariables; }; typedef Vector<Scope, 10> ScopeStack; @@ -473,25 +445,18 @@ private: m_scopeStack.last().declareWrite(ident); } - bool deleteProperty(const Identifier* ident) - { - if (!m_syntaxAlreadyValidated) - return m_scopeStack.last().deleteProperty(ident); - return true; - } - ScopeStack m_scopeStack; }; -int jsParse(JSGlobalObject* lexicalGlobalObject, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, const SourceCode* source) +int jsParse(JSGlobalData* globalData, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, const SourceCode* source) { - JSParser parser(lexicalGlobalObject->globalData().lexer, &lexicalGlobalObject->globalData(), parameters, strictness == JSParseStrict, parserMode == JSParseFunctionCode, source->provider()); - return parser.parseProgram(lexicalGlobalObject); + JSParser parser(globalData->lexer, globalData, parameters, strictness == JSParseStrict, parserMode == JSParseFunctionCode, source->provider()); + return parser.parseProgram(); } JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* parameters, bool inStrictContext, bool isFunction, SourceProvider* provider) : m_lexer(lexer) - , m_endAddress(0) + , m_stack(globalData->stack()) , m_error(false) , m_globalData(globalData) , m_allowsIn(true) @@ -505,7 +470,6 @@ JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* p , m_nonTrivialExpressionCount(0) , m_lastIdentifier(0) { - m_endAddress = wtfThreadData().approximatedStackStart() - kMaxParserStackUsage; ScopeRef scope = pushScope(); if (isFunction) scope->setIsFunction(); @@ -519,7 +483,7 @@ JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* p m_lexer->setLastLineNumber(tokenLine()); } -bool JSParser::parseProgram(JSGlobalObject* lexicalGlobalObject) +bool JSParser::parseProgram() { ASTBuilder context(m_globalData, m_lexer); if (m_lexer->isReparsing()) @@ -528,20 +492,15 @@ bool JSParser::parseProgram(JSGlobalObject* lexicalGlobalObject) SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context); if (!sourceElements || !consume(EOFTOK)) return true; - if (!m_syntaxAlreadyValidated) { - IdentifierSet deletedVariables; - if (!scope->getDeletedVariables(deletedVariables)) - return true; - IdentifierSet::const_iterator end = deletedVariables.end(); - SymbolTable& globalEnvRecord = lexicalGlobalObject->symbolTable(); - for (IdentifierSet::const_iterator ptr = deletedVariables.begin(); ptr != end; ++ptr) { - if (!globalEnvRecord.get(*ptr).isNull()) - return true; - } - } IdentifierSet capturedVariables; scope->getCapturedVariables(capturedVariables); - m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), context.features() | (scope->strictMode() ? StrictModeFeature : 0), + CodeFeatures features = context.features(); + if (scope->strictMode()) + features |= StrictModeFeature; + if (scope->shadowsArguments()) + features |= ShadowsArgumentsFeature; + + m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features, m_lastLine, context.numConstants(), capturedVariables); return false; } @@ -1128,10 +1087,9 @@ template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder& } } -template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParameters(TreeBuilder& context, bool& usesArguments) +template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParameters(TreeBuilder& context) { matchOrFail(IDENT); - usesArguments = m_globalData->propertyNames->arguments == *m_token.m_data.ident; failIfFalseIfStrict(declareParameter(m_token.m_data.ident)); TreeFormalParameterList list = context.createFormalParameterList(*m_token.m_data.ident); TreeFormalParameterList tail = list; @@ -1140,10 +1098,8 @@ template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParame next(); matchOrFail(IDENT); const Identifier* ident = m_token.m_data.ident; - usesArguments |= m_globalData->propertyNames->arguments == *m_token.m_data.ident; failIfFalseIfStrict(declareParameter(ident)); next(); - usesArguments = usesArguments || m_globalData->propertyNames->arguments == *ident; tail = context.createFormalParameterList(tail, *ident); } return list; @@ -1172,9 +1128,8 @@ template <JSParser::FunctionRequirements requirements, bool nameIsInContainingSc } else if (requirements == FunctionNeedsName) return false; consumeOrFail(OPENPAREN); - bool usesArguments = false; if (!match(CLOSEPAREN)) { - parameters = parseFormalParameters(context, usesArguments); + parameters = parseFormalParameters(context); failIfFalse(parameters); } consumeOrFail(CLOSEPAREN); @@ -1186,8 +1141,6 @@ template <JSParser::FunctionRequirements requirements, bool nameIsInContainingSc body = parseFunctionBody(context); failIfFalse(body); - if (usesArguments) - context.setUsesArguments(body); if (functionScope->strictMode() && name) { failIfTrue(m_globalData->propertyNames->arguments == *name); failIfTrue(m_globalData->propertyNames->eval == *name); @@ -1404,7 +1357,7 @@ end: if (hadAssignment) m_nonLHSCount++; - if (!ASTBuilder::CreatesAST) + if (!TreeBuilder::CreatesAST) return lhs; while (assignmentStack) @@ -1938,8 +1891,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeB expr = context.createVoid(expr); break; case DELETETOKEN: - if (strictMode() && context.isResolve(expr)) - failIfFalse(deleteProperty(m_lastIdentifier)); + failIfTrueIfStrict(context.isResolve(expr)); expr = context.makeDeleteNode(expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end); break; default: diff --git a/JavaScriptCore/parser/JSParser.h b/JavaScriptCore/parser/JSParser.h index 64b18e7..0676b41 100644 --- a/JavaScriptCore/parser/JSParser.h +++ b/JavaScriptCore/parser/JSParser.h @@ -31,7 +31,7 @@ namespace JSC { class ExecState; class FunctionParameters; class Identifier; -class JSGlobalObject; +class JSGlobalData; class SourceCode; enum { @@ -159,6 +159,6 @@ struct JSToken { enum JSParserStrictness { JSParseNormal, JSParseStrict }; enum JSParserMode { JSParseProgramCode, JSParseFunctionCode }; -int jsParse(JSGlobalObject*, FunctionParameters*, JSParserStrictness, JSParserMode, const SourceCode*); +int jsParse(JSGlobalData*, FunctionParameters*, JSParserStrictness, JSParserMode, const SourceCode*); } #endif // JSParser_h diff --git a/JavaScriptCore/parser/Nodes.h b/JavaScriptCore/parser/Nodes.h index 6930f63..b8e9cdf 100644 --- a/JavaScriptCore/parser/Nodes.h +++ b/JavaScriptCore/parser/Nodes.h @@ -58,7 +58,10 @@ namespace JSC { const CodeFeatures CatchFeature = 1 << 5; const CodeFeatures ThisFeature = 1 << 6; const CodeFeatures StrictModeFeature = 1 << 7; - const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature; + const CodeFeatures ShadowsArgumentsFeature = 1 << 8; + + + const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature; enum Operator { OpEqual, @@ -1409,7 +1412,7 @@ namespace JSC { CodeFeatures features() { return m_features; } bool usesEval() const { return m_features & EvalFeature; } - bool usesArguments() const { return m_features & ArgumentsFeature; } + 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; } diff --git a/JavaScriptCore/parser/Parser.cpp b/JavaScriptCore/parser/Parser.cpp index 49ce848..b203b21 100644 --- a/JavaScriptCore/parser/Parser.cpp +++ b/JavaScriptCore/parser/Parser.cpp @@ -33,12 +33,12 @@ namespace JSC { -void Parser::parse(JSGlobalObject* lexicalGlobalObject, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg) +void Parser::parse(JSGlobalData* globalData, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg) { #ifdef ANDROID_INSTRUMENT android::TimeCounter::start(android::TimeCounter::JavaScriptParseTimeCounter); #endif - ASSERT(lexicalGlobalObject); + ASSERT(globalData); m_sourceElements = 0; int defaultErrLine; @@ -52,10 +52,10 @@ void Parser::parse(JSGlobalObject* lexicalGlobalObject, FunctionParameters* para *errLine = -1; *errMsg = UString(); - Lexer& lexer = *lexicalGlobalObject->globalData().lexer; + Lexer& lexer = *globalData->lexer; lexer.setCode(*m_source, m_arena); - int parseError = jsParse(lexicalGlobalObject, parameters, strictness, mode, m_source); + int parseError = jsParse(globalData, parameters, strictness, mode, m_source); int lineNumber = lexer.lineNumber(); bool lexError = lexer.sawError(); lexer.clear(); diff --git a/JavaScriptCore/parser/Parser.h b/JavaScriptCore/parser/Parser.h index 6549067..213827b 100644 --- a/JavaScriptCore/parser/Parser.h +++ b/JavaScriptCore/parser/Parser.h @@ -57,7 +57,7 @@ namespace JSC { ParserArena& arena() { return m_arena; } private: - void parse(JSGlobalObject* lexicalGlobalObject, FunctionParameters*, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg); + void parse(JSGlobalData*, FunctionParameters*, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg); // Used to determine type of error to report. bool isFunctionBodyNode(ScopeNode*) { return false; } @@ -85,7 +85,7 @@ namespace JSC { m_source = &source; if (ParsedNode::scopeIsFunction) lexicalGlobalObject->globalData().lexer->setIsReparsing(); - parse(lexicalGlobalObject, parameters, strictness, ParsedNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, &errLine, &errMsg); + parse(&lexicalGlobalObject->globalData(), parameters, strictness, ParsedNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, &errLine, &errMsg); RefPtr<ParsedNode> result; if (m_sourceElements) { diff --git a/JavaScriptCore/parser/SyntaxChecker.h b/JavaScriptCore/parser/SyntaxChecker.h index f9093a7..b00e710 100644 --- a/JavaScriptCore/parser/SyntaxChecker.h +++ b/JavaScriptCore/parser/SyntaxChecker.h @@ -203,9 +203,9 @@ public: void assignmentStackAppend(int, int, int, int, int, Operator) { } int createAssignment(int, int, int, int, int) { ASSERT_NOT_REACHED(); return 1; } - const Identifier& getName(const Property& property) { ASSERT(property.name); return *property.name; } - PropertyNode::Type getType(const Property& property) { return property.type; } - bool isResolve(ExpressionType expr) { return expr == ResolveExpr || expr == ResolveEvalExpr; } + const Identifier& getName(const Property& property) const { ASSERT(property.name); return *property.name; } + PropertyNode::Type getType(const Property& property) const { return property.type; } + bool isResolve(ExpressionType expr) const { return expr == ResolveExpr || expr == ResolveEvalExpr; } private: int m_topBinaryExpr; |
