From 40304f3d611ce9210c29e87c4ea0ad0e042979de Mon Sep 17 00:00:00 2001 From: Mark Lam Date: Mon, 5 May 2014 18:08:53 +0200 Subject: Fix problems with divot and lineStart mismatches. https://bugs.webkit.org/show_bug.cgi?id=118662. Reviewed by Oliver Hunt. Source/JavaScriptCore: r152494 added the recording of lineStart values for divot positions. This is needed for the computation of column numbers. Similarly, it also added the recording of line numbers for the divot positions. One problem with the approach taken was that the line and lineStart values were recorded independently, and hence were not always guaranteed to be sampled at the same place that the divot position is recorded. This resulted in potential mismatches that cause some assertions to fail. The solution is to introduce a JSTextPosition abstraction that records the divot position, line, and lineStart as a single quantity. Wherever we record the divot position as an unsigned int previously, we now record its JSTextPosition which captures all 3 values in one go. This ensures that the captured line and lineStart will always match the captured divot position. * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitCall): (JSC::BytecodeGenerator::emitCallEval): (JSC::BytecodeGenerator::emitCallVarargs): (JSC::BytecodeGenerator::emitConstruct): (JSC::BytecodeGenerator::emitDebugHook): - Use JSTextPosition instead of passing line and lineStart explicitly. * bytecompiler/BytecodeGenerator.h: (JSC::BytecodeGenerator::emitExpressionInfo): - Use JSTextPosition instead of passing line and lineStart explicitly. * bytecompiler/NodesCodegen.cpp: (JSC::ThrowableExpressionData::emitThrowReferenceError): (JSC::ResolveNode::emitBytecode): (JSC::BracketAccessorNode::emitBytecode): (JSC::DotAccessorNode::emitBytecode): (JSC::NewExprNode::emitBytecode): (JSC::EvalFunctionCallNode::emitBytecode): (JSC::FunctionCallValueNode::emitBytecode): (JSC::FunctionCallResolveNode::emitBytecode): (JSC::FunctionCallBracketNode::emitBytecode): (JSC::FunctionCallDotNode::emitBytecode): (JSC::CallFunctionCallDotNode::emitBytecode): (JSC::ApplyFunctionCallDotNode::emitBytecode): (JSC::PostfixNode::emitResolve): (JSC::PostfixNode::emitBracket): (JSC::PostfixNode::emitDot): (JSC::DeleteResolveNode::emitBytecode): (JSC::DeleteBracketNode::emitBytecode): (JSC::DeleteDotNode::emitBytecode): (JSC::PrefixNode::emitResolve): (JSC::PrefixNode::emitBracket): (JSC::PrefixNode::emitDot): (JSC::UnaryOpNode::emitBytecode): (JSC::BinaryOpNode::emitStrcat): (JSC::BinaryOpNode::emitBytecode): (JSC::ThrowableBinaryOpNode::emitBytecode): (JSC::InstanceOfNode::emitBytecode): (JSC::emitReadModifyAssignment): (JSC::ReadModifyResolveNode::emitBytecode): (JSC::AssignResolveNode::emitBytecode): (JSC::AssignDotNode::emitBytecode): (JSC::ReadModifyDotNode::emitBytecode): (JSC::AssignBracketNode::emitBytecode): (JSC::ReadModifyBracketNode::emitBytecode): (JSC::ForInNode::emitBytecode): (JSC::WithNode::emitBytecode): (JSC::ThrowNode::emitBytecode): - Use JSTextPosition instead of passing line and lineStart explicitly. * parser/ASTBuilder.h: - Replaced ASTBuilder::PositionInfo with JSTextPosition. (JSC::ASTBuilder::BinaryOpInfo::BinaryOpInfo): (JSC::ASTBuilder::AssignmentInfo::AssignmentInfo): (JSC::ASTBuilder::createResolve): (JSC::ASTBuilder::createBracketAccess): (JSC::ASTBuilder::createDotAccess): (JSC::ASTBuilder::createRegExp): (JSC::ASTBuilder::createNewExpr): (JSC::ASTBuilder::createAssignResolve): (JSC::ASTBuilder::createExprStatement): (JSC::ASTBuilder::createForInLoop): (JSC::ASTBuilder::createReturnStatement): (JSC::ASTBuilder::createBreakStatement): (JSC::ASTBuilder::createContinueStatement): (JSC::ASTBuilder::createLabelStatement): (JSC::ASTBuilder::createWithStatement): (JSC::ASTBuilder::createThrowStatement): (JSC::ASTBuilder::appendBinaryExpressionInfo): (JSC::ASTBuilder::appendUnaryToken): (JSC::ASTBuilder::unaryTokenStackLastStart): (JSC::ASTBuilder::assignmentStackAppend): (JSC::ASTBuilder::createAssignment): (JSC::ASTBuilder::setExceptionLocation): (JSC::ASTBuilder::makeDeleteNode): (JSC::ASTBuilder::makeFunctionCallNode): (JSC::ASTBuilder::makeBinaryNode): (JSC::ASTBuilder::makeAssignNode): (JSC::ASTBuilder::makePrefixNode): (JSC::ASTBuilder::makePostfixNode): - Use JSTextPosition instead of passing line and lineStart explicitly. * parser/Lexer.cpp: (JSC::::lex): - Added support for capturing the appropriate JSTextPositions instead of just the character offset. * parser/Lexer.h: (JSC::Lexer::currentPosition): (JSC::::lexExpectIdentifier): - Added support for capturing the appropriate JSTextPositions instead of just the character offset. * parser/NodeConstructors.h: (JSC::Node::Node): (JSC::ResolveNode::ResolveNode): (JSC::EvalFunctionCallNode::EvalFunctionCallNode): (JSC::FunctionCallValueNode::FunctionCallValueNode): (JSC::FunctionCallResolveNode::FunctionCallResolveNode): (JSC::FunctionCallBracketNode::FunctionCallBracketNode): (JSC::FunctionCallDotNode::FunctionCallDotNode): (JSC::CallFunctionCallDotNode::CallFunctionCallDotNode): (JSC::ApplyFunctionCallDotNode::ApplyFunctionCallDotNode): (JSC::PostfixNode::PostfixNode): (JSC::DeleteResolveNode::DeleteResolveNode): (JSC::DeleteBracketNode::DeleteBracketNode): (JSC::DeleteDotNode::DeleteDotNode): (JSC::PrefixNode::PrefixNode): (JSC::ReadModifyResolveNode::ReadModifyResolveNode): (JSC::ReadModifyBracketNode::ReadModifyBracketNode): (JSC::AssignBracketNode::AssignBracketNode): (JSC::AssignDotNode::AssignDotNode): (JSC::ReadModifyDotNode::ReadModifyDotNode): (JSC::AssignErrorNode::AssignErrorNode): (JSC::WithNode::WithNode): (JSC::ForInNode::ForInNode): - Use JSTextPosition instead of passing line and lineStart explicitly. * parser/Nodes.cpp: (JSC::StatementNode::setLoc): - Use JSTextPosition instead of passing line and lineStart explicitly. * parser/Nodes.h: (JSC::Node::lineNo): (JSC::Node::startOffset): (JSC::Node::lineStartOffset): (JSC::Node::position): (JSC::ThrowableExpressionData::ThrowableExpressionData): (JSC::ThrowableExpressionData::setExceptionSourceCode): (JSC::ThrowableExpressionData::divot): (JSC::ThrowableExpressionData::divotStart): (JSC::ThrowableExpressionData::divotEnd): (JSC::ThrowableSubExpressionData::ThrowableSubExpressionData): (JSC::ThrowableSubExpressionData::setSubexpressionInfo): (JSC::ThrowableSubExpressionData::subexpressionDivot): (JSC::ThrowableSubExpressionData::subexpressionStart): (JSC::ThrowableSubExpressionData::subexpressionEnd): (JSC::ThrowablePrefixedSubExpressionData::ThrowablePrefixedSubExpressionData): (JSC::ThrowablePrefixedSubExpressionData::setSubexpressionInfo): (JSC::ThrowablePrefixedSubExpressionData::subexpressionDivot): (JSC::ThrowablePrefixedSubExpressionData::subexpressionStart): (JSC::ThrowablePrefixedSubExpressionData::subexpressionEnd): - Use JSTextPosition instead of passing line and lineStart explicitly. * parser/Parser.cpp: (JSC::::Parser): (JSC::::parseInner): - Use JSTextPosition instead of passing line and lineStart explicitly. (JSC::::didFinishParsing): - Remove setting of m_lastLine value. We always pass in the value from m_lastLine anyway. So, this assignment is effectively a nop. (JSC::::parseVarDeclaration): (JSC::::parseVarDeclarationList): (JSC::::parseForStatement): (JSC::::parseBreakStatement): (JSC::::parseContinueStatement): (JSC::::parseReturnStatement): (JSC::::parseThrowStatement): (JSC::::parseWithStatement): (JSC::::parseTryStatement): (JSC::::parseBlockStatement): (JSC::::parseFunctionDeclaration): (JSC::LabelInfo::LabelInfo): (JSC::::parseExpressionOrLabelStatement): (JSC::::parseExpressionStatement): (JSC::::parseAssignmentExpression): (JSC::::parseBinaryExpression): (JSC::::parseProperty): (JSC::::parsePrimaryExpression): (JSC::::parseMemberExpression): (JSC::::parseUnaryExpression): - Use JSTextPosition instead of passing line and lineStart explicitly. * parser/Parser.h: (JSC::Parser::next): (JSC::Parser::nextExpectIdentifier): (JSC::Parser::getToken): (JSC::Parser::tokenStartPosition): (JSC::Parser::tokenEndPosition): (JSC::Parser::lastTokenEndPosition): (JSC::::parse): - Use JSTextPosition instead of passing line and lineStart explicitly. * parser/ParserTokens.h: (JSC::JSTextPosition::JSTextPosition): (JSC::JSTextPosition::operator+): (JSC::JSTextPosition::operator-): (JSC::JSTextPosition::operator int): - Added JSTextPosition. * parser/SyntaxChecker.h: (JSC::SyntaxChecker::makeFunctionCallNode): (JSC::SyntaxChecker::makeAssignNode): (JSC::SyntaxChecker::makePrefixNode): (JSC::SyntaxChecker::makePostfixNode): (JSC::SyntaxChecker::makeDeleteNode): (JSC::SyntaxChecker::createResolve): (JSC::SyntaxChecker::createBracketAccess): (JSC::SyntaxChecker::createDotAccess): (JSC::SyntaxChecker::createRegExp): (JSC::SyntaxChecker::createNewExpr): (JSC::SyntaxChecker::createAssignResolve): (JSC::SyntaxChecker::createForInLoop): (JSC::SyntaxChecker::createReturnStatement): (JSC::SyntaxChecker::createBreakStatement): (JSC::SyntaxChecker::createContinueStatement): (JSC::SyntaxChecker::createWithStatement): (JSC::SyntaxChecker::createLabelStatement): (JSC::SyntaxChecker::createThrowStatement): (JSC::SyntaxChecker::appendBinaryExpressionInfo): (JSC::SyntaxChecker::operatorStackPop): - Use JSTextPosition instead of passing line and lineStart explicitly. git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153477 268f45cc-cd09-0410-ab3c-d52691b4dbfc Task-number: QTBUG-38708 Change-Id: Ic6a65e8915c634dffe76b7181b38d6be0ab4a45d Reviewed-by: Michael Bruning --- Source/JavaScriptCore/parser/Parser.h | 59 +++++++++++++++-------------------- 1 file changed, 26 insertions(+), 33 deletions(-) (limited to 'Source/JavaScriptCore/parser/Parser.h') diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h index e0a56754d..87d523404 100644 --- a/Source/JavaScriptCore/parser/Parser.h +++ b/Source/JavaScriptCore/parser/Parser.h @@ -475,8 +475,7 @@ private: String parseInner(); void didFinishParsing(SourceElements*, ParserArenaData*, - ParserArenaData*, CodeFeatures, - int, int, IdentifierSet&); + ParserArenaData*, CodeFeatures, int, IdentifierSet&); // Used to determine type of error to report. bool isFunctionBodyNode(ScopeNode*) { return false; } @@ -484,20 +483,22 @@ private: ALWAYS_INLINE void next(unsigned lexerFlags = 0) { - m_lastLine = m_token.m_location.line; - m_lastTokenEnd = m_token.m_location.endOffset; - m_lastTokenLineStart = m_token.m_location.lineStartOffset; - m_lexer->setLastLineNumber(m_lastLine); - m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_location, lexerFlags, strictMode()); + int lastLine = m_token.m_location.line; + int lastTokenEnd = m_token.m_location.endOffset; + int lastTokenLineStart = m_token.m_location.lineStartOffset; + m_lastTokenEndPosition = JSTextPosition(lastLine, lastTokenEnd, lastTokenLineStart); + m_lexer->setLastLineNumber(lastLine); + m_token.m_type = m_lexer->lex(&m_token, lexerFlags, strictMode()); } ALWAYS_INLINE void nextExpectIdentifier(unsigned lexerFlags = 0) { - m_lastLine = m_token.m_location.line; - m_lastTokenEnd = m_token.m_location.endOffset; - m_lastTokenLineStart = m_token.m_location.lineStartOffset; - m_lexer->setLastLineNumber(m_lastLine); - m_token.m_type = m_lexer->lexExpectIdentifier(&m_token.m_data, &m_token.m_location, lexerFlags, strictMode()); + int lastLine = m_token.m_location.line; + int lastTokenEnd = m_token.m_location.endOffset; + int lastTokenLineStart = m_token.m_location.lineStartOffset; + m_lastTokenEndPosition = JSTextPosition(lastLine, lastTokenEnd, lastTokenLineStart); + m_lexer->setLastLineNumber(lastLine); + m_token.m_type = m_lexer->lexExpectIdentifier(&m_token, lexerFlags, strictMode()); } ALWAYS_INLINE bool nextTokenIsColon() @@ -515,7 +516,7 @@ private: ALWAYS_INLINE String getToken() { SourceProvider* sourceProvider = m_source->provider(); - return sourceProvider->getRange(tokenStart(), tokenEnd()); + return sourceProvider->getRange(tokenStart(), tokenEndPosition().offset); } ALWAYS_INLINE bool match(JSTokenType expected) @@ -528,6 +529,11 @@ private: return m_token.m_location.startOffset; } + ALWAYS_INLINE const JSTextPosition& tokenStartPosition() + { + return m_token.m_startPosition; + } + ALWAYS_INLINE int tokenLine() { return m_token.m_location.line; @@ -538,9 +544,9 @@ private: return tokenStart() - tokenLineStart(); } - ALWAYS_INLINE unsigned tokenEnd() + ALWAYS_INLINE const JSTextPosition& tokenEndPosition() { - return m_token.m_location.endOffset; + return m_token.m_endPosition; } ALWAYS_INLINE unsigned tokenLineStart() @@ -915,7 +921,7 @@ private: template ALWAYS_INLINE TreeProperty parseProperty(TreeBuilder&); template ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&); template ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&); - template ALWAYS_INLINE TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd); + template ALWAYS_INLINE TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd); template ALWAYS_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder& context); template bool parseFunctionInfo(TreeBuilder&, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, unsigned& openBraceOffset, unsigned& closeBraceOffset, int& bodyStartLine, unsigned& bodyStartColumn); ALWAYS_INLINE int isBinaryOperator(JSTokenType); @@ -935,19 +941,9 @@ private: return m_stack.isSafeToRecurse(); } - int lastTokenEnd() const - { - return m_lastTokenEnd; - } - - unsigned lastTokenLine() const - { - return m_lastLine; - } - - unsigned lastTokenLineStart() const + const JSTextPosition& lastTokenEndPosition() const { - return m_lastTokenLineStart; + return m_lastTokenEndPosition; } bool hasError() const @@ -965,10 +961,7 @@ private: String m_errorMessage; JSToken m_token; bool m_allowsIn; - unsigned m_lastLine; - int m_lastTokenEnd; - unsigned m_lastTokenLine; - unsigned m_lastTokenLineStart; + JSTextPosition m_lastTokenEndPosition; int m_assignmentCount; int m_nonLHSCount; bool m_syntaxAlreadyValidated; @@ -1051,7 +1044,7 @@ PassRefPtr Parser::parse(ParserError& error) *m_source, m_features, m_numConstants); - result->setLoc(m_source->firstLine(), m_lastLine, m_lexer->currentOffset(), m_lexer->currentLineStartOffset()); + result->setLoc(m_source->firstLine(), m_lastTokenEndPosition.line, m_lexer->currentOffset(), m_lexer->currentLineStartOffset()); } else { // We can never see a syntax error when reparsing a function, since we should have // reported the error when parsing the containing program or eval code. So if we're -- cgit v1.2.1