diff options
author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
tree | e367e64a75991c554930278175d403c072de6bb8 /Source/JavaScriptCore/parser | |
parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
download | qtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz |
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit.
Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/JavaScriptCore/parser')
20 files changed, 1564 insertions, 976 deletions
diff --git a/Source/JavaScriptCore/parser/ASTBuilder.h b/Source/JavaScriptCore/parser/ASTBuilder.h index 6e7334f97..43d9b4f1b 100644 --- a/Source/JavaScriptCore/parser/ASTBuilder.h +++ b/Source/JavaScriptCore/parser/ASTBuilder.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,50 +33,68 @@ namespace JSC { class ASTBuilder { + struct PositionInfo { + unsigned startPos; + unsigned line; + unsigned lineStartPos; + }; + struct BinaryOpInfo { BinaryOpInfo() {} - BinaryOpInfo(int s, int d, int e, bool r) - : start(s) - , divot(d) - , end(e) - , hasAssignment(r) + BinaryOpInfo(int otherStart, int otherDivot, int otherEnd, unsigned otherDivotLine, unsigned otherDivotLineStart, bool rhsHasAssignment) + : start(otherStart) + , divot(otherDivot) + , end(otherEnd) + , divotLine(otherDivotLine) + , divotLineStart(otherDivotLineStart) + , hasAssignment(rhsHasAssignment) { } BinaryOpInfo(const BinaryOpInfo& lhs, const BinaryOpInfo& rhs) : start(lhs.start) , divot(rhs.start) , end(rhs.end) + , divotLine(rhs.divotLine) + , divotLineStart(rhs.divotLineStart) , hasAssignment(lhs.hasAssignment || rhs.hasAssignment) { } int start; int divot; int end; + unsigned divotLine; + unsigned divotLineStart; bool hasAssignment; }; struct AssignmentInfo { AssignmentInfo() {} - AssignmentInfo(ExpressionNode* node, int start, int divot, int initAssignments, Operator op) + AssignmentInfo(ExpressionNode* node, unsigned start, unsigned divot, unsigned divotLine, unsigned divotLineStart, int initAssignments, Operator op) : m_node(node) , m_start(start) , m_divot(divot) + , m_divotLine(divotLine) + , m_divotLineStart(divotLineStart) , m_initAssignments(initAssignments) , m_op(op) { + ASSERT(m_divot >= m_divotLineStart); + ASSERT(m_start >= m_divotLineStart); } ExpressionNode* m_node; - int m_start; - int m_divot; + unsigned m_start; + unsigned m_divot; + unsigned m_divotLine; + unsigned m_divotLineStart; int m_initAssignments; Operator m_op; }; public: - ASTBuilder(JSGlobalData* globalData, SourceCode* sourceCode) - : m_globalData(globalData) + ASTBuilder(VM* vm, SourceCode* sourceCode) + : m_vm(vm) , m_sourceCode(sourceCode) - , m_scope(globalData) + , m_scope(vm) , m_evalCount(0) { } @@ -113,9 +131,9 @@ public: static const int DontBuildStrings = 0; ExpressionNode* makeBinaryNode(const JSTokenLocation&, int token, std::pair<ExpressionNode*, BinaryOpInfo>, std::pair<ExpressionNode*, BinaryOpInfo>); - ExpressionNode* makeFunctionCallNode(const JSTokenLocation&, ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end); + ExpressionNode* makeFunctionCallNode(const JSTokenLocation&, ExpressionNode* func, ArgumentsNode* args, int start, unsigned divot, int end, unsigned divotLine, unsigned divotLineStart); - JSC::SourceElements* createSourceElements() { return new (m_globalData) JSC::SourceElements(); } + JSC::SourceElements* createSourceElements() { return new (m_vm) JSC::SourceElements(); } ParserArenaData<DeclarationStacks::VarStack>* varDeclarations() { return m_scope.m_varDeclarations; } ParserArenaData<DeclarationStacks::FunctionStack>* funcDeclarations() { return m_scope.m_funcDeclarations; } @@ -124,13 +142,13 @@ public: void appendToComma(CommaNode* commaNode, ExpressionNode* expr) { commaNode->append(expr); } - CommaNode* createCommaExpr(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* rhs) { return new (m_globalData) CommaNode(location, lhs, rhs); } + CommaNode* createCommaExpr(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* rhs) { return new (m_vm) CommaNode(location, lhs, rhs); } - ExpressionNode* makeAssignNode(const JSTokenLocation&, ExpressionNode* left, Operator, ExpressionNode* right, bool leftHasAssignments, bool rightHasAssignments, int start, int divot, int end); - ExpressionNode* makePrefixNode(const JSTokenLocation&, ExpressionNode*, Operator, int start, int divot, int end); - ExpressionNode* makePostfixNode(const JSTokenLocation&, ExpressionNode*, Operator, int start, int divot, int end); + ExpressionNode* makeAssignNode(const JSTokenLocation&, ExpressionNode* left, Operator, ExpressionNode* right, bool leftHasAssignments, bool rightHasAssignments, int start, int divot, int end, unsigned divotLine, unsigned divotLineStart); + ExpressionNode* makePrefixNode(const JSTokenLocation&, ExpressionNode*, Operator, int start, int divot, int end, unsigned divotLine, unsigned divotLineStart); + ExpressionNode* makePostfixNode(const JSTokenLocation&, ExpressionNode*, Operator, int start, int divot, int end, unsigned divotLine, unsigned divotLineStart); ExpressionNode* makeTypeOfNode(const JSTokenLocation&, ExpressionNode*); - ExpressionNode* makeDeleteNode(const JSTokenLocation&, ExpressionNode*, int start, int divot, int end); + ExpressionNode* makeDeleteNode(const JSTokenLocation&, ExpressionNode*, int start, int divot, int end, unsigned divotLine, unsigned divotLineStart); ExpressionNode* makeNegateNode(const JSTokenLocation&, ExpressionNode*); ExpressionNode* makeBitwiseNotNode(const JSTokenLocation&, ExpressionNode*); ExpressionNode* makeMultNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); @@ -145,355 +163,359 @@ public: ExpressionNode* makeRightShiftNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); ExpressionNode* makeURightShiftNode(const JSTokenLocation&, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments); - ExpressionNode* createLogicalNot(const JSTokenLocation& location, ExpressionNode* expr) { return new (m_globalData) LogicalNotNode(location, expr); } - ExpressionNode* createUnaryPlus(const JSTokenLocation& location, ExpressionNode* expr) { return new (m_globalData) UnaryPlusNode(location, expr); } + ExpressionNode* createLogicalNot(const JSTokenLocation& location, ExpressionNode* expr) + { + if (expr->isNumber()) + return createBoolean(location, isZeroOrUnordered(static_cast<NumberNode*>(expr)->value())); + + return new (m_vm) LogicalNotNode(location, expr); + } + ExpressionNode* createUnaryPlus(const JSTokenLocation& location, ExpressionNode* expr) { return new (m_vm) UnaryPlusNode(location, expr); } ExpressionNode* createVoid(const JSTokenLocation& location, ExpressionNode* expr) { incConstants(); - return new (m_globalData) VoidNode(location, expr); + return new (m_vm) VoidNode(location, expr); } ExpressionNode* thisExpr(const JSTokenLocation& location) { usesThis(); - return new (m_globalData) ThisNode(location); + return new (m_vm) ThisNode(location); } - ExpressionNode* createResolve(const JSTokenLocation& location, const Identifier* ident, int start) + ExpressionNode* createResolve(const JSTokenLocation& location, const Identifier* ident, unsigned start, unsigned divotLine, unsigned divotLineStart) { - if (m_globalData->propertyNames->arguments == *ident) + if (m_vm->propertyNames->arguments == *ident) usesArguments(); - return new (m_globalData) ResolveNode(location, *ident, start); + return new (m_vm) ResolveNode(location, *ident, start, divotLine, divotLineStart); } - ExpressionNode* createObjectLiteral(const JSTokenLocation& location) { return new (m_globalData) ObjectLiteralNode(location); } - ExpressionNode* createObjectLiteral(const JSTokenLocation& location, PropertyListNode* properties) { return new (m_globalData) ObjectLiteralNode(location, properties); } + ExpressionNode* createObjectLiteral(const JSTokenLocation& location) { return new (m_vm) ObjectLiteralNode(location); } + ExpressionNode* createObjectLiteral(const JSTokenLocation& location, PropertyListNode* properties) { return new (m_vm) ObjectLiteralNode(location, properties); } ExpressionNode* createArray(const JSTokenLocation& location, int elisions) { if (elisions) incConstants(); - return new (m_globalData) ArrayNode(location, elisions); + return new (m_vm) ArrayNode(location, elisions); } - ExpressionNode* createArray(const JSTokenLocation& location, ElementNode* elems) { return new (m_globalData) ArrayNode(location, elems); } + ExpressionNode* createArray(const JSTokenLocation& location, ElementNode* elems) { return new (m_vm) ArrayNode(location, elems); } ExpressionNode* createArray(const JSTokenLocation& location, int elisions, ElementNode* elems) { if (elisions) incConstants(); - return new (m_globalData) ArrayNode(location, elisions, elems); + return new (m_vm) ArrayNode(location, elisions, elems); } ExpressionNode* createNumberExpr(const JSTokenLocation& location, double d) { incConstants(); - return new (m_globalData) NumberNode(location, d); + return new (m_vm) NumberNode(location, d); } ExpressionNode* createString(const JSTokenLocation& location, const Identifier* string) { incConstants(); - return new (m_globalData) StringNode(location, *string); + return new (m_vm) StringNode(location, *string); } ExpressionNode* createBoolean(const JSTokenLocation& location, bool b) { incConstants(); - return new (m_globalData) BooleanNode(location, b); + return new (m_vm) BooleanNode(location, b); } ExpressionNode* createNull(const JSTokenLocation& location) { incConstants(); - return new (m_globalData) NullNode(location); + return new (m_vm) NullNode(location); } - ExpressionNode* createBracketAccess(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* property, bool propertyHasAssignments, int start, int divot, int end) + ExpressionNode* createBracketAccess(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* property, bool propertyHasAssignments, int start, int divot, int end, unsigned divotLine, unsigned divotLineStart) { - BracketAccessorNode* node = new (m_globalData) BracketAccessorNode(location, base, property, propertyHasAssignments); - setExceptionLocation(node, start, divot, end); + BracketAccessorNode* node = new (m_vm) BracketAccessorNode(location, base, property, propertyHasAssignments); + setExceptionLocation(node, start, divot, end, divotLine, divotLineStart); return node; } - ExpressionNode* createDotAccess(const JSTokenLocation& location, ExpressionNode* base, const Identifier* property, int start, int divot, int end) + ExpressionNode* createDotAccess(const JSTokenLocation& location, ExpressionNode* base, const Identifier* property, int start, int divot, int end, unsigned divotLine, unsigned divotLineStart) { - DotAccessorNode* node = new (m_globalData) DotAccessorNode(location, base, *property); - setExceptionLocation(node, start, divot, end); + DotAccessorNode* node = new (m_vm) DotAccessorNode(location, base, *property); + setExceptionLocation(node, start, divot, end, divotLine, divotLineStart); return node; } - ExpressionNode* createRegExp(const JSTokenLocation& location, const Identifier& pattern, const Identifier& flags, int start) + ExpressionNode* createRegExp(const JSTokenLocation& location, const Identifier& pattern, const Identifier& flags, int start, unsigned divotLine, unsigned divotLineStart) { if (Yarr::checkSyntax(pattern.string())) return 0; - RegExpNode* node = new (m_globalData) RegExpNode(location, pattern, flags); + RegExpNode* node = new (m_vm) RegExpNode(location, pattern, flags); int size = pattern.length() + 2; // + 2 for the two /'s - setExceptionLocation(node, start, start + size, start + size); + setExceptionLocation(node, start, start + size, start + size, divotLine, divotLineStart); return node; } - ExpressionNode* createNewExpr(const JSTokenLocation& location, ExpressionNode* expr, ArgumentsNode* arguments, int start, int divot, int end) + ExpressionNode* createNewExpr(const JSTokenLocation& location, ExpressionNode* expr, ArgumentsNode* arguments, int start, int divot, int end, unsigned divotLine, unsigned divotLineStart) { - NewExprNode* node = new (m_globalData) NewExprNode(location, expr, arguments); - setExceptionLocation(node, start, divot, end); + NewExprNode* node = new (m_vm) NewExprNode(location, expr, arguments); + setExceptionLocation(node, start, divot, end, divotLine, divotLineStart); return node; } - ExpressionNode* createNewExpr(const JSTokenLocation& location, ExpressionNode* expr, int start, int end) + ExpressionNode* createNewExpr(const JSTokenLocation& location, ExpressionNode* expr, int start, int end, unsigned divotLine, unsigned divotLineStart) { - NewExprNode* node = new (m_globalData) NewExprNode(location, expr); - setExceptionLocation(node, start, end, end); + NewExprNode* node = new (m_vm) NewExprNode(location, expr); + setExceptionLocation(node, start, end, end, divotLine, divotLineStart); return node; } ExpressionNode* createConditionalExpr(const JSTokenLocation& location, ExpressionNode* condition, ExpressionNode* lhs, ExpressionNode* rhs) { - return new (m_globalData) ConditionalNode(location, condition, lhs, rhs); + return new (m_vm) ConditionalNode(location, condition, lhs, rhs); } - ExpressionNode* createAssignResolve(const JSTokenLocation& location, const Identifier& ident, ExpressionNode* rhs, int start, int divot, int end) + ExpressionNode* createAssignResolve(const JSTokenLocation& location, const Identifier& ident, ExpressionNode* rhs, int start, int divot, int end, unsigned divotLine, unsigned divotLineStart) { if (rhs->isFuncExprNode()) static_cast<FuncExprNode*>(rhs)->body()->setInferredName(ident); - AssignResolveNode* node = new (m_globalData) AssignResolveNode(location, ident, rhs); - setExceptionLocation(node, start, divot, end); + AssignResolveNode* node = new (m_vm) AssignResolveNode(location, ident, rhs); + setExceptionLocation(node, start, divot, end, divotLine, divotLineStart); return node; } - ExpressionNode* createFunctionExpr(const JSTokenLocation& location, const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) + ExpressionNode* createFunctionExpr(const JSTokenLocation& location, const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, unsigned openBraceOffset, unsigned closeBraceOffset, int bodyStartLine, int bodyEndLine, unsigned startColumn) { - FuncExprNode* result = new (m_globalData) FuncExprNode(location, *name, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), parameters); - body->setLoc(bodyStartLine, bodyEndLine, location.column); + FuncExprNode* result = new (m_vm) FuncExprNode(location, *name, body, m_sourceCode->subExpression(openBraceOffset, closeBraceOffset, bodyStartLine, startColumn), parameters); + body->setLoc(bodyStartLine, bodyEndLine, location.startOffset, location.lineStartOffset); return result; } - FunctionBodyNode* createFunctionBody(const JSTokenLocation& location, bool inStrictContext) + FunctionBodyNode* createFunctionBody(const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, bool inStrictContext) + { + return FunctionBodyNode::create(m_vm, startLocation, endLocation, startColumn, inStrictContext); + } + + void setFunctionStart(FunctionBodyNode* body, int functionStart) { - return FunctionBodyNode::create(m_globalData, location, inStrictContext); + body->setFunctionStart(functionStart); } - template <bool> PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) + template <bool> PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, unsigned openBraceOffset, unsigned closeBraceOffset, int bodyStartLine, int bodyEndLine, unsigned bodyStartColumn) { ASSERT(name); - body->setLoc(bodyStartLine, bodyEndLine, location.column); + body->setLoc(bodyStartLine, bodyEndLine, location.startOffset, location.lineStartOffset); body->setInferredName(*name); - return new (m_globalData) PropertyNode(m_globalData, *name, new (m_globalData) FuncExprNode(location, m_globalData->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), params), type); + return new (m_vm) PropertyNode(m_vm, *name, new (m_vm) FuncExprNode(location, m_vm->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn), params), type); } - template <bool> PropertyNode* createGetterOrSetterProperty(JSGlobalData*, const JSTokenLocation& location, PropertyNode::Type type, double name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) + template <bool> PropertyNode* createGetterOrSetterProperty(VM*, const JSTokenLocation& location, PropertyNode::Type type, double name, ParameterNode* params, FunctionBodyNode* body, unsigned openBraceOffset, unsigned closeBraceOffset, int bodyStartLine, int bodyEndLine, unsigned bodyStartColumn) { - body->setLoc(bodyStartLine, bodyEndLine, location.column); - return new (m_globalData) PropertyNode(m_globalData, name, new (m_globalData) FuncExprNode(location, m_globalData->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), params), type); + body->setLoc(bodyStartLine, bodyEndLine, location.startOffset, location.lineStartOffset); + return new (m_vm) PropertyNode(m_vm, name, new (m_vm) FuncExprNode(location, m_vm->propertyNames->nullIdentifier, body, m_sourceCode->subExpression(openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn), params), type); } - ArgumentsNode* createArguments() { return new (m_globalData) ArgumentsNode(); } - ArgumentsNode* createArguments(ArgumentListNode* args) { return new (m_globalData) ArgumentsNode(args); } - ArgumentListNode* createArgumentsList(const JSTokenLocation& location, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(location, arg); } - ArgumentListNode* createArgumentsList(const JSTokenLocation& location, ArgumentListNode* args, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(location, args, arg); } + ArgumentsNode* createArguments() { return new (m_vm) ArgumentsNode(); } + ArgumentsNode* createArguments(ArgumentListNode* args) { return new (m_vm) ArgumentsNode(args); } + ArgumentListNode* createArgumentsList(const JSTokenLocation& location, ExpressionNode* arg) { return new (m_vm) ArgumentListNode(location, arg); } + ArgumentListNode* createArgumentsList(const JSTokenLocation& location, ArgumentListNode* args, ExpressionNode* arg) { return new (m_vm) ArgumentListNode(location, args, arg); } template <bool> PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type) { if (node->isFuncExprNode()) static_cast<FuncExprNode*>(node)->body()->setInferredName(*propertyName); - return new (m_globalData) PropertyNode(m_globalData, *propertyName, node, type); + return new (m_vm) PropertyNode(m_vm, *propertyName, node, type); } - template <bool> PropertyNode* createProperty(JSGlobalData*, double propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, propertyName, node, type); } - PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property) { return new (m_globalData) PropertyListNode(location, property); } - PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property, PropertyListNode* tail) { return new (m_globalData) PropertyListNode(location, property, tail); } + template <bool> PropertyNode* createProperty(VM*, double propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_vm) PropertyNode(m_vm, propertyName, node, type); } + PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property) { return new (m_vm) PropertyListNode(location, property); } + PropertyListNode* createPropertyList(const JSTokenLocation& location, PropertyNode* property, PropertyListNode* tail) { return new (m_vm) PropertyListNode(location, property, tail); } - ElementNode* createElementList(int elisions, ExpressionNode* expr) { return new (m_globalData) ElementNode(elisions, expr); } - ElementNode* createElementList(ElementNode* elems, int elisions, ExpressionNode* expr) { return new (m_globalData) ElementNode(elems, elisions, expr); } + ElementNode* createElementList(int elisions, ExpressionNode* expr) { return new (m_vm) ElementNode(elisions, expr); } + ElementNode* createElementList(ElementNode* elems, int elisions, ExpressionNode* expr) { return new (m_vm) ElementNode(elems, elisions, expr); } - ParameterNode* createFormalParameterList(const Identifier& ident) { return new (m_globalData) ParameterNode(ident); } - ParameterNode* createFormalParameterList(ParameterNode* list, const Identifier& ident) { return new (m_globalData) ParameterNode(list, ident); } + ParameterNode* createFormalParameterList(const Identifier& ident) { return new (m_vm) ParameterNode(ident); } + ParameterNode* createFormalParameterList(ParameterNode* list, const Identifier& ident) { return new (m_vm) ParameterNode(list, ident); } - CaseClauseNode* createClause(ExpressionNode* expr, JSC::SourceElements* statements) { return new (m_globalData) CaseClauseNode(expr, statements); } - ClauseListNode* createClauseList(CaseClauseNode* clause) { return new (m_globalData) ClauseListNode(clause); } - ClauseListNode* createClauseList(ClauseListNode* tail, CaseClauseNode* clause) { return new (m_globalData) ClauseListNode(tail, clause); } + CaseClauseNode* createClause(ExpressionNode* expr, JSC::SourceElements* statements) { return new (m_vm) CaseClauseNode(expr, statements); } + ClauseListNode* createClauseList(CaseClauseNode* clause) { return new (m_vm) ClauseListNode(clause); } + ClauseListNode* createClauseList(ClauseListNode* tail, CaseClauseNode* clause) { return new (m_vm) ClauseListNode(tail, clause); } void setUsesArguments(FunctionBodyNode* node) { node->setUsesArguments(); } - StatementNode* createFuncDeclStatement(const JSTokenLocation& location, const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine) + StatementNode* createFuncDeclStatement(const JSTokenLocation& location, const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, unsigned openBraceOffset, unsigned closeBraceOffset, int bodyStartLine, int bodyEndLine, unsigned bodyStartColumn) { - FuncDeclNode* decl = new (m_globalData) FuncDeclNode(location, *name, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), parameters); - if (*name == m_globalData->propertyNames->arguments) + FuncDeclNode* decl = new (m_vm) FuncDeclNode(location, *name, body, m_sourceCode->subExpression(openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn), parameters); + if (*name == m_vm->propertyNames->arguments) usesArguments(); m_scope.m_funcDeclarations->data.append(decl->body()); - body->setLoc(bodyStartLine, bodyEndLine, location.column); + body->setLoc(bodyStartLine, bodyEndLine, location.startOffset, location.lineStartOffset); return decl; } StatementNode* createBlockStatement(const JSTokenLocation& location, JSC::SourceElements* elements, int startLine, int endLine) { - BlockNode* block = new (m_globalData) BlockNode(location, elements); - block->setLoc(startLine, endLine, location.column); + BlockNode* block = new (m_vm) BlockNode(location, elements); + block->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); return block; } StatementNode* createExprStatement(const JSTokenLocation& location, ExpressionNode* expr, int start, int end) { - ExprStatementNode* result = new (m_globalData) ExprStatementNode(location, expr); - result->setLoc(start, end, location.column); - return result; - } - - StatementNode* createIfStatement(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* trueBlock, int start, int end) - { - IfNode* result = new (m_globalData) IfNode(location, condition, trueBlock); - result->setLoc(start, end, location.column); + ExprStatementNode* result = new (m_vm) ExprStatementNode(location, expr); + result->setLoc(start, end, location.startOffset, location.lineStartOffset); return result; } StatementNode* createIfStatement(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* trueBlock, StatementNode* falseBlock, int start, int end) { - IfNode* result = new (m_globalData) IfElseNode(location, condition, trueBlock, falseBlock); - result->setLoc(start, end, location.column); + IfElseNode* result = new (m_vm) IfElseNode(location, condition, trueBlock, falseBlock); + result->setLoc(start, end, location.startOffset, location.lineStartOffset); return result; } StatementNode* createForLoop(const JSTokenLocation& location, ExpressionNode* initializer, ExpressionNode* condition, ExpressionNode* iter, StatementNode* statements, int start, int end) { - ForNode* result = new (m_globalData) ForNode(location, initializer, condition, iter, statements); - result->setLoc(start, end); + ForNode* result = new (m_vm) ForNode(location, initializer, condition, iter, statements); + result->setLoc(start, end, location.startOffset, location.lineStartOffset); return result; } - StatementNode* createForInLoop(const JSTokenLocation& location, const Identifier* ident, ExpressionNode* initializer, ExpressionNode* iter, StatementNode* statements, int start, int divot, int end, int initStart, int initEnd, int startLine, int endLine) + StatementNode* createForInLoop(const JSTokenLocation& location, const Identifier* ident, ExpressionNode* initializer, ExpressionNode* iter, StatementNode* statements, int start, int divot, int end, int initStart, int initEnd, int startLine, int endLine, unsigned divotLine, unsigned divotLineStart) { - ForInNode* result = new (m_globalData) ForInNode(m_globalData, location, *ident, initializer, iter, statements, initStart, initStart - start, initEnd - initStart); - result->setLoc(startLine, endLine, location.column); - setExceptionLocation(result, start, divot + 1, end); + ForInNode* result = new (m_vm) ForInNode(m_vm, location, *ident, initializer, iter, statements, initStart, initStart - start, initEnd - initStart, divotLine, divotLineStart); + result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); + setExceptionLocation(result, start, divot + 1, end, divotLine, divotLineStart); return result; } - StatementNode* createForInLoop(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, int eStart, int eDivot, int eEnd, int start, int end) + StatementNode* createForInLoop(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, int eStart, int eDivot, int eEnd, int start, int end, unsigned divotLine, unsigned divotLineStart) { - ForInNode* result = new (m_globalData) ForInNode(location, lhs, iter, statements); - result->setLoc(start, end, location.column); - setExceptionLocation(result, eStart, eDivot, eEnd); + ForInNode* result = new (m_vm) ForInNode(location, lhs, iter, statements); + result->setLoc(start, end, location.startOffset, location.lineStartOffset); + setExceptionLocation(result, eStart, eDivot, eEnd, divotLine, divotLineStart); return result; } - StatementNode* createEmptyStatement(const JSTokenLocation& location) { return new (m_globalData) EmptyStatementNode(location); } + StatementNode* createEmptyStatement(const JSTokenLocation& location) { return new (m_vm) EmptyStatementNode(location); } StatementNode* createVarStatement(const JSTokenLocation& location, ExpressionNode* expr, int start, int end) { StatementNode* result; if (!expr) - result = new (m_globalData) EmptyStatementNode(location); + result = new (m_vm) EmptyStatementNode(location); else - result = new (m_globalData) VarStatementNode(location, expr); - result->setLoc(start, end, location.column); + result = new (m_vm) VarStatementNode(location, expr); + result->setLoc(start, end, location.startOffset, location.lineStartOffset); return result; } - StatementNode* createReturnStatement(const JSTokenLocation& location, ExpressionNode* expression, int eStart, int eEnd, int startLine, int endLine) + StatementNode* createReturnStatement(const JSTokenLocation& location, ExpressionNode* expression, int eStart, int eEnd, int startLine, int endLine, unsigned divotLine, unsigned divotLineStart) { - ReturnNode* result = new (m_globalData) ReturnNode(location, expression); - setExceptionLocation(result, eStart, eEnd, eEnd); - result->setLoc(startLine, endLine, location.column); + ReturnNode* result = new (m_vm) ReturnNode(location, expression); + setExceptionLocation(result, eStart, eEnd, eEnd, divotLine, divotLineStart); + result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); return result; } - StatementNode* createBreakStatement(const JSTokenLocation& location, int eStart, int eEnd, int startLine, int endLine) + StatementNode* createBreakStatement(const JSTokenLocation& location, int eStart, int eEnd, int startLine, int endLine, unsigned endLineStart) { - BreakNode* result = new (m_globalData) BreakNode(m_globalData, location); - setExceptionLocation(result, eStart, eEnd, eEnd); - result->setLoc(startLine, endLine, location.column); + BreakNode* result = new (m_vm) BreakNode(m_vm, location); + setExceptionLocation(result, eStart, eEnd, eEnd, endLine, endLineStart); + result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); return result; } - StatementNode* createBreakStatement(const JSTokenLocation& location, const Identifier* ident, int eStart, int eEnd, int startLine, int endLine) + StatementNode* createBreakStatement(const JSTokenLocation& location, const Identifier* ident, int eStart, int eEnd, int startLine, int endLine, unsigned endLineStart) { - BreakNode* result = new (m_globalData) BreakNode(location, *ident); - setExceptionLocation(result, eStart, eEnd, eEnd); - result->setLoc(startLine, endLine, location.column); + BreakNode* result = new (m_vm) BreakNode(location, *ident); + setExceptionLocation(result, eStart, eEnd, eEnd, endLine, endLineStart); + result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); return result; } - StatementNode* createContinueStatement(const JSTokenLocation& location, int eStart, int eEnd, int startLine, int endLine) + StatementNode* createContinueStatement(const JSTokenLocation& location, int eStart, int eEnd, int startLine, int endLine, unsigned endLineStart) { - ContinueNode* result = new (m_globalData) ContinueNode(m_globalData, location); - setExceptionLocation(result, eStart, eEnd, eEnd); - result->setLoc(startLine, endLine, location.column); + ContinueNode* result = new (m_vm) ContinueNode(m_vm, location); + setExceptionLocation(result, eStart, eEnd, eEnd, endLine, endLineStart); + result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); return result; } - StatementNode* createContinueStatement(const JSTokenLocation& location, const Identifier* ident, int eStart, int eEnd, int startLine, int endLine) + StatementNode* createContinueStatement(const JSTokenLocation& location, const Identifier* ident, int eStart, int eEnd, int startLine, int endLine, unsigned endLineStart) { - ContinueNode* result = new (m_globalData) ContinueNode(location, *ident); - setExceptionLocation(result, eStart, eEnd, eEnd); - result->setLoc(startLine, endLine, location.column); + ContinueNode* result = new (m_vm) ContinueNode(location, *ident); + setExceptionLocation(result, eStart, eEnd, eEnd, endLine, endLineStart); + result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); return result; } StatementNode* createTryStatement(const JSTokenLocation& location, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine) { - TryNode* result = new (m_globalData) TryNode(location, tryBlock, *ident, catchBlock, finallyBlock); + TryNode* result = new (m_vm) TryNode(location, tryBlock, *ident, catchBlock, finallyBlock); if (catchBlock) usesCatch(); - result->setLoc(startLine, endLine, location.column); + result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); return result; } StatementNode* createSwitchStatement(const JSTokenLocation& location, ExpressionNode* expr, ClauseListNode* firstClauses, CaseClauseNode* defaultClause, ClauseListNode* secondClauses, int startLine, int endLine) { - CaseBlockNode* cases = new (m_globalData) CaseBlockNode(firstClauses, defaultClause, secondClauses); - SwitchNode* result = new (m_globalData) SwitchNode(location, expr, cases); - result->setLoc(startLine, endLine, location.column); + CaseBlockNode* cases = new (m_vm) CaseBlockNode(firstClauses, defaultClause, secondClauses); + SwitchNode* result = new (m_vm) SwitchNode(location, expr, cases); + result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); return result; } StatementNode* createWhileStatement(const JSTokenLocation& location, ExpressionNode* expr, StatementNode* statement, int startLine, int endLine) { - WhileNode* result = new (m_globalData) WhileNode(location, expr, statement); - result->setLoc(startLine, endLine, location.column); + WhileNode* result = new (m_vm) WhileNode(location, expr, statement); + result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); return result; } StatementNode* createDoWhileStatement(const JSTokenLocation& location, StatementNode* statement, ExpressionNode* expr, int startLine, int endLine) { - DoWhileNode* result = new (m_globalData) DoWhileNode(location, statement, expr); - result->setLoc(startLine, endLine, location.column); + DoWhileNode* result = new (m_vm) DoWhileNode(location, statement, expr); + result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); return result; } - StatementNode* createLabelStatement(const JSTokenLocation& location, const Identifier* ident, StatementNode* statement, int start, int end) + StatementNode* createLabelStatement(const JSTokenLocation& location, const Identifier* ident, StatementNode* statement, unsigned start, unsigned end, unsigned divotLine, unsigned divotLineStart) { - LabelNode* result = new (m_globalData) LabelNode(location, *ident, statement); - setExceptionLocation(result, start, end, end); + LabelNode* result = new (m_vm) LabelNode(location, *ident, statement); + setExceptionLocation(result, start, end, end, divotLine, divotLineStart); return result; } - StatementNode* createWithStatement(const JSTokenLocation& location, ExpressionNode* expr, StatementNode* statement, int start, int end, int startLine, int endLine) + StatementNode* createWithStatement(const JSTokenLocation& location, ExpressionNode* expr, StatementNode* statement, unsigned start, unsigned end, unsigned startLine, unsigned endLine, unsigned divotLine, unsigned divotLineStart) { usesWith(); - WithNode* result = new (m_globalData) WithNode(location, expr, statement, end, end - start); - result->setLoc(startLine, endLine, location.column); + WithNode* result = new (m_vm) WithNode(location, expr, statement, end, divotLine, divotLineStart, end - start); + result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); return result; } - StatementNode* createThrowStatement(const JSTokenLocation& location, ExpressionNode* expr, int start, int end, int startLine, int endLine) + StatementNode* createThrowStatement(const JSTokenLocation& location, ExpressionNode* expr, int start, int end, int startLine, int endLine, unsigned divotLine, unsigned divotLineStart) { - ThrowNode* result = new (m_globalData) ThrowNode(location, expr); - result->setLoc(startLine, endLine, location.column); - setExceptionLocation(result, start, end, end); + ThrowNode* result = new (m_vm) ThrowNode(location, expr); + result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); + setExceptionLocation(result, start, end, end, divotLine, divotLineStart); return result; } StatementNode* createDebugger(const JSTokenLocation& location, int startLine, int endLine) { - DebuggerStatementNode* result = new (m_globalData) DebuggerStatementNode(location); - result->setLoc(startLine, endLine, location.column); + DebuggerStatementNode* result = new (m_vm) DebuggerStatementNode(location); + result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); return result; } StatementNode* createConstStatement(const JSTokenLocation& location, ConstDeclNode* decls, int startLine, int endLine) { - ConstStatementNode* result = new (m_globalData) ConstStatementNode(location, decls); - result->setLoc(startLine, endLine, location.column); + ConstStatementNode* result = new (m_vm) ConstStatementNode(location, decls); + result->setLoc(startLine, endLine, location.startOffset, location.lineStartOffset); return result; } ConstDeclNode* appendConstDecl(const JSTokenLocation& location, ConstDeclNode* tail, const Identifier* name, ExpressionNode* initializer) { - ConstDeclNode* result = new (m_globalData) ConstDeclNode(location, *name, initializer); + ConstDeclNode* result = new (m_vm) ConstDeclNode(location, *name, initializer); if (tail) tail->m_next = result; return result; @@ -506,7 +528,7 @@ public: void addVar(const Identifier* ident, int attrs) { - if (m_globalData->propertyNames->arguments == *ident) + if (m_vm->propertyNames->arguments == *ident) usesArguments(); m_scope.m_varDeclarations->data.append(std::make_pair(ident, attrs)); } @@ -519,15 +541,15 @@ public: static_cast<CommaNode*>(list)->append(init); return list; } - return new (m_globalData) CommaNode(location, list, init); + return new (m_vm) CommaNode(location, list, init); } int evalCount() const { return m_evalCount; } - void appendBinaryExpressionInfo(int& operandStackDepth, ExpressionNode* current, int exprStart, int lhs, int rhs, bool hasAssignments) + void appendBinaryExpressionInfo(int& operandStackDepth, ExpressionNode* current, int exprStart, int lhs, int rhs, unsigned divotLine, unsigned divotLineStart, bool hasAssignments) { operandStackDepth++; - m_binaryOperandStack.append(std::make_pair(current, BinaryOpInfo(exprStart, lhs, rhs, hasAssignments))); + m_binaryOperandStack.append(std::make_pair(current, BinaryOpInfo(exprStart, lhs, rhs, divotLine, divotLineStart, hasAssignments))); } // Logic to handle datastructures used during parsing of binary expressions @@ -564,10 +586,11 @@ public: return result; } - void appendUnaryToken(int& tokenStackDepth, int type, int start) + void appendUnaryToken(int& tokenStackDepth, int type, unsigned start, unsigned divotLine, unsigned divotLineStart) { tokenStackDepth++; - m_unaryTokenStack.append(std::make_pair(type, start)); + PositionInfo position = { start, divotLine, divotLineStart }; + m_unaryTokenStack.append(std::make_pair(type, position)); } int unaryTokenStackLastType(int&) @@ -575,26 +598,34 @@ public: return m_unaryTokenStack.last().first; } - int unaryTokenStackLastStart(int&) + unsigned unaryTokenStackLastStart(int&) { - return m_unaryTokenStack.last().second; + return m_unaryTokenStack.last().second.startPos; } + unsigned unaryTokenStackLastLineStartPosition(int&) + { + return m_unaryTokenStack.last().second.lineStartPos; + } + void unaryTokenStackRemoveLast(int& tokenStackDepth) { tokenStackDepth--; m_unaryTokenStack.removeLast(); } - void assignmentStackAppend(int& assignmentStackDepth, ExpressionNode* node, int start, int divot, int assignmentCount, Operator op) + void assignmentStackAppend(int& assignmentStackDepth, ExpressionNode* node, unsigned start, unsigned divot, unsigned divotLine, unsigned divotLineStart, int assignmentCount, Operator op) { assignmentStackDepth++; - m_assignmentInfoStack.append(AssignmentInfo(node, start, divot, assignmentCount, op)); + ASSERT(start >= divotLineStart); + ASSERT(divot >= divotLineStart); + m_assignmentInfoStack.append(AssignmentInfo(node, start, divot, divotLine, divotLineStart, assignmentCount, op)); } ExpressionNode* createAssignment(const JSTokenLocation& location, int& assignmentStackDepth, ExpressionNode* rhs, int initialAssignmentCount, int currentAssignmentCount, int lastTokenEnd) { - ExpressionNode* result = makeAssignNode(location, m_assignmentInfoStack.last().m_node, m_assignmentInfoStack.last().m_op, rhs, m_assignmentInfoStack.last().m_initAssignments != initialAssignmentCount, m_assignmentInfoStack.last().m_initAssignments != currentAssignmentCount, m_assignmentInfoStack.last().m_start, m_assignmentInfoStack.last().m_divot + 1, lastTokenEnd); + AssignmentInfo& info = m_assignmentInfoStack.last(); + ExpressionNode* result = makeAssignNode(location, info.m_node, info.m_op, rhs, info.m_initAssignments != initialAssignmentCount, info.m_initAssignments != currentAssignmentCount, info.m_start, info.m_divot + 1, lastTokenEnd, info.m_divotLine, info.m_divotLineStart); m_assignmentInfoStack.removeLast(); assignmentStackDepth--; return result; @@ -607,9 +638,9 @@ public: private: struct Scope { - Scope(JSGlobalData* globalData) - : m_varDeclarations(new (globalData) ParserArenaData<DeclarationStacks::VarStack>) - , m_funcDeclarations(new (globalData) ParserArenaData<DeclarationStacks::FunctionStack>) + Scope(VM* vm) + : m_varDeclarations(new (vm) ParserArenaData<DeclarationStacks::VarStack>) + , m_funcDeclarations(new (vm) ParserArenaData<DeclarationStacks::FunctionStack>) , m_features(0) , m_numConstants(0) { @@ -620,9 +651,10 @@ private: int m_numConstants; }; - static void setExceptionLocation(ThrowableExpressionData* node, unsigned start, unsigned divot, unsigned end) + static void setExceptionLocation(ThrowableExpressionData* node, unsigned start, unsigned divot, unsigned end, unsigned divotLine, unsigned divotLineStart) { - node->setExceptionSourceCode(divot, divot - start, end - divot); + ASSERT(divot >= divotLineStart); + node->setExceptionSourceCode(divot, divot - start, end - divot, divotLine, divotLineStart); } void incConstants() { m_scope.m_numConstants++; } @@ -637,16 +669,16 @@ private: } ExpressionNode* createNumber(const JSTokenLocation& location, double d) { - return new (m_globalData) NumberNode(location, d); + return new (m_vm) NumberNode(location, d); } - JSGlobalData* m_globalData; + VM* m_vm; SourceCode* m_sourceCode; Scope m_scope; - Vector<BinaryOperand, 10> m_binaryOperandStack; - Vector<AssignmentInfo, 10> m_assignmentInfoStack; - Vector<pair<int, int>, 10> m_binaryOperatorStack; - Vector<pair<int, int>, 10> m_unaryTokenStack; + Vector<BinaryOperand, 10, UnsafeVectorOverflow> m_binaryOperandStack; + Vector<AssignmentInfo, 10, UnsafeVectorOverflow> m_assignmentInfoStack; + Vector<pair<int, int>, 10, UnsafeVectorOverflow> m_binaryOperatorStack; + Vector<pair<int, PositionInfo>, 10, UnsafeVectorOverflow> m_unaryTokenStack; int m_evalCount; }; @@ -654,26 +686,26 @@ ExpressionNode* ASTBuilder::makeTypeOfNode(const JSTokenLocation& location, Expr { if (expr->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(expr); - return new (m_globalData) TypeOfResolveNode(location, resolve->identifier()); + return new (m_vm) TypeOfResolveNode(location, resolve->identifier()); } - return new (m_globalData) TypeOfValueNode(location, expr); + return new (m_vm) TypeOfValueNode(location, expr); } -ExpressionNode* ASTBuilder::makeDeleteNode(const JSTokenLocation& location, ExpressionNode* expr, int start, int divot, int end) +ExpressionNode* ASTBuilder::makeDeleteNode(const JSTokenLocation& location, ExpressionNode* expr, int start, int divot, int end, unsigned divotLine, unsigned divotLineStart) { if (!expr->isLocation()) - return new (m_globalData) DeleteValueNode(location, expr); + return new (m_vm) DeleteValueNode(location, expr); if (expr->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(expr); - return new (m_globalData) DeleteResolveNode(location, resolve->identifier(), divot, divot - start, end - divot); + return new (m_vm) DeleteResolveNode(location, resolve->identifier(), divot, divot - start, end - divot, divotLine, divotLineStart); } if (expr->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr); - return new (m_globalData) DeleteBracketNode(location, bracket->base(), bracket->subscript(), divot, divot - start, end - divot); + return new (m_vm) DeleteBracketNode(location, bracket->base(), bracket->subscript(), divot, divot - start, end - divot, divotLine, divotLineStart); } ASSERT(expr->isDotAccessorNode()); DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr); - return new (m_globalData) DeleteDotNode(location, dot->base(), dot->identifier(), divot, divot - start, end - divot); + return new (m_vm) DeleteDotNode(location, dot->base(), dot->identifier(), divot, divot - start, end - divot, divotLine, divotLineStart); } ExpressionNode* ASTBuilder::makeNegateNode(const JSTokenLocation& location, ExpressionNode* n) @@ -684,14 +716,14 @@ ExpressionNode* ASTBuilder::makeNegateNode(const JSTokenLocation& location, Expr return numberNode; } - return new (m_globalData) NegateNode(location, n); + return new (m_vm) NegateNode(location, n); } ExpressionNode* ASTBuilder::makeBitwiseNotNode(const JSTokenLocation& location, ExpressionNode* expr) { if (expr->isNumber()) return createNumber(location, ~toInt32(static_cast<NumberNode*>(expr)->value())); - return new (m_globalData) BitwiseNotNode(location, expr); + return new (m_vm) BitwiseNotNode(location, expr); } ExpressionNode* ASTBuilder::makeMultNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) @@ -703,12 +735,12 @@ ExpressionNode* ASTBuilder::makeMultNode(const JSTokenLocation& location, Expres return createNumber(location, static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value()); if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1) - return new (m_globalData) UnaryPlusNode(location, expr2); + return new (m_vm) UnaryPlusNode(location, expr2); if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1) - return new (m_globalData) UnaryPlusNode(location, expr1); + return new (m_vm) UnaryPlusNode(location, expr1); - return new (m_globalData) MultNode(location, expr1, expr2, rightHasAssignments); + return new (m_vm) MultNode(location, expr1, expr2, rightHasAssignments); } ExpressionNode* ASTBuilder::makeDivNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) @@ -718,7 +750,7 @@ ExpressionNode* ASTBuilder::makeDivNode(const JSTokenLocation& location, Express if (expr1->isNumber() && expr2->isNumber()) return createNumber(location, static_cast<NumberNode*>(expr1)->value() / static_cast<NumberNode*>(expr2)->value()); - return new (m_globalData) DivNode(location, expr1, expr2, rightHasAssignments); + return new (m_vm) DivNode(location, expr1, expr2, rightHasAssignments); } ExpressionNode* ASTBuilder::makeModNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) @@ -728,14 +760,14 @@ ExpressionNode* ASTBuilder::makeModNode(const JSTokenLocation& location, Express if (expr1->isNumber() && expr2->isNumber()) return createNumber(location, fmod(static_cast<NumberNode*>(expr1)->value(), static_cast<NumberNode*>(expr2)->value())); - return new (m_globalData) ModNode(location, expr1, expr2, rightHasAssignments); + return new (m_vm) ModNode(location, expr1, expr2, rightHasAssignments); } ExpressionNode* ASTBuilder::makeAddNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) return createNumber(location, static_cast<NumberNode*>(expr1)->value() + static_cast<NumberNode*>(expr2)->value()); - return new (m_globalData) AddNode(location, expr1, expr2, rightHasAssignments); + return new (m_vm) AddNode(location, expr1, expr2, rightHasAssignments); } ExpressionNode* ASTBuilder::makeSubNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) @@ -745,80 +777,81 @@ ExpressionNode* ASTBuilder::makeSubNode(const JSTokenLocation& location, Express if (expr1->isNumber() && expr2->isNumber()) return createNumber(location, static_cast<NumberNode*>(expr1)->value() - static_cast<NumberNode*>(expr2)->value()); - return new (m_globalData) SubNode(location, expr1, expr2, rightHasAssignments); + return new (m_vm) SubNode(location, expr1, expr2, rightHasAssignments); } ExpressionNode* ASTBuilder::makeLeftShiftNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) return createNumber(location, toInt32(static_cast<NumberNode*>(expr1)->value()) << (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); - return new (m_globalData) LeftShiftNode(location, expr1, expr2, rightHasAssignments); + return new (m_vm) LeftShiftNode(location, expr1, expr2, rightHasAssignments); } ExpressionNode* ASTBuilder::makeRightShiftNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) return createNumber(location, toInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); - return new (m_globalData) RightShiftNode(location, expr1, expr2, rightHasAssignments); + return new (m_vm) RightShiftNode(location, expr1, expr2, rightHasAssignments); } ExpressionNode* ASTBuilder::makeURightShiftNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) return createNumber(location, toUInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f)); - return new (m_globalData) UnsignedRightShiftNode(location, expr1, expr2, rightHasAssignments); + return new (m_vm) UnsignedRightShiftNode(location, expr1, expr2, rightHasAssignments); } ExpressionNode* ASTBuilder::makeBitOrNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) return createNumber(location, toInt32(static_cast<NumberNode*>(expr1)->value()) | toInt32(static_cast<NumberNode*>(expr2)->value())); - return new (m_globalData) BitOrNode(location, expr1, expr2, rightHasAssignments); + return new (m_vm) BitOrNode(location, expr1, expr2, rightHasAssignments); } ExpressionNode* ASTBuilder::makeBitAndNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) return createNumber(location, toInt32(static_cast<NumberNode*>(expr1)->value()) & toInt32(static_cast<NumberNode*>(expr2)->value())); - return new (m_globalData) BitAndNode(location, expr1, expr2, rightHasAssignments); + return new (m_vm) BitAndNode(location, expr1, expr2, rightHasAssignments); } ExpressionNode* ASTBuilder::makeBitXOrNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments) { if (expr1->isNumber() && expr2->isNumber()) return createNumber(location, toInt32(static_cast<NumberNode*>(expr1)->value()) ^ toInt32(static_cast<NumberNode*>(expr2)->value())); - return new (m_globalData) BitXOrNode(location, expr1, expr2, rightHasAssignments); + return new (m_vm) BitXOrNode(location, expr1, expr2, rightHasAssignments); } -ExpressionNode* ASTBuilder::makeFunctionCallNode(const JSTokenLocation& location, ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end) +ExpressionNode* ASTBuilder::makeFunctionCallNode(const JSTokenLocation& location, ExpressionNode* func, ArgumentsNode* args, int start, unsigned divot, int end, unsigned divotLine, unsigned divotLineStart) { + ASSERT(divot >= divotLineStart); if (!func->isLocation()) - return new (m_globalData) FunctionCallValueNode(location, func, args, divot, divot - start, end - divot); + return new (m_vm) FunctionCallValueNode(location, func, args, divot, divot - start, end - divot, divotLine, divotLineStart); if (func->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(func); const Identifier& identifier = resolve->identifier(); - if (identifier == m_globalData->propertyNames->eval) { + if (identifier == m_vm->propertyNames->eval) { usesEval(); - return new (m_globalData) EvalFunctionCallNode(location, args, divot, divot - start, end - divot); + return new (m_vm) EvalFunctionCallNode(location, args, divot, divot - start, end - divot, divotLine, divotLineStart); } - return new (m_globalData) FunctionCallResolveNode(location, identifier, args, divot, divot - start, end - divot); + return new (m_vm) FunctionCallResolveNode(location, identifier, args, divot, divot - start, end - divot, divotLine, divotLineStart); } if (func->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func); - FunctionCallBracketNode* node = new (m_globalData) FunctionCallBracketNode(location, bracket->base(), bracket->subscript(), args, divot, divot - start, end - divot); - node->setSubexpressionInfo(bracket->divot(), bracket->endOffset()); + FunctionCallBracketNode* node = new (m_vm) FunctionCallBracketNode(location, bracket->base(), bracket->subscript(), args, divot, divot - start, end - divot, divotLine, divotLineStart); + node->setSubexpressionInfo(bracket->divot(), bracket->divotEndOffset(), bracket->divotLine(), bracket->divotLineStart()); return node; } ASSERT(func->isDotAccessorNode()); DotAccessorNode* dot = static_cast<DotAccessorNode*>(func); FunctionCallDotNode* node; - if (dot->identifier() == m_globalData->propertyNames->call) - node = new (m_globalData) CallFunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divot - start, end - divot); - else if (dot->identifier() == m_globalData->propertyNames->apply) - node = new (m_globalData) ApplyFunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divot - start, end - divot); + if (dot->identifier() == m_vm->propertyNames->call) + node = new (m_vm) CallFunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divot - start, end - divot, divotLine, divotLineStart); + else if (dot->identifier() == m_vm->propertyNames->apply) + node = new (m_vm) ApplyFunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divot - start, end - divot, divotLine, divotLineStart); else - node = new (m_globalData) FunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divot - start, end - divot); - node->setSubexpressionInfo(dot->divot(), dot->endOffset()); + node = new (m_vm) FunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divot - start, end - divot, divotLine, divotLineStart); + node->setSubexpressionInfo(dot->divot(), dot->divotEndOffset(), dot->divotLine(), dot->divotLineStart()); return node; } @@ -826,10 +859,10 @@ ExpressionNode* ASTBuilder::makeBinaryNode(const JSTokenLocation& location, int { switch (token) { case OR: - return new (m_globalData) LogicalOpNode(location, lhs.first, rhs.first, OpLogicalOr); + return new (m_vm) LogicalOpNode(location, lhs.first, rhs.first, OpLogicalOr); case AND: - return new (m_globalData) LogicalOpNode(location, lhs.first, rhs.first, OpLogicalAnd); + return new (m_vm) LogicalOpNode(location, lhs.first, rhs.first, OpLogicalAnd); case BITOR: return makeBitOrNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); @@ -841,38 +874,38 @@ ExpressionNode* ASTBuilder::makeBinaryNode(const JSTokenLocation& location, int return makeBitAndNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case EQEQ: - return new (m_globalData) EqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_vm) EqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case NE: - return new (m_globalData) NotEqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_vm) NotEqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case STREQ: - return new (m_globalData) StrictEqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_vm) StrictEqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case STRNEQ: - return new (m_globalData) NotStrictEqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_vm) NotStrictEqualNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case LT: - return new (m_globalData) LessNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_vm) LessNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case GT: - return new (m_globalData) GreaterNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_vm) GreaterNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case LE: - return new (m_globalData) LessEqNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_vm) LessEqNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case GE: - return new (m_globalData) GreaterEqNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); + return new (m_vm) GreaterEqNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); case INSTANCEOF: { - InstanceOfNode* node = new (m_globalData) InstanceOfNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); - setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end); + InstanceOfNode* node = new (m_vm) InstanceOfNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); + setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end, rhs.second.divotLine, rhs.second.divotLineStart); return node; } case INTOKEN: { - InNode* node = new (m_globalData) InNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); - setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end); + InNode* node = new (m_vm) InNode(location, lhs.first, rhs.first, rhs.second.hasAssignment); + setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end, rhs.second.divotLine, rhs.second.divotLineStart); return node; } @@ -904,28 +937,28 @@ ExpressionNode* ASTBuilder::makeBinaryNode(const JSTokenLocation& location, int return 0; } -ExpressionNode* ASTBuilder::makeAssignNode(const JSTokenLocation& location, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end) +ExpressionNode* ASTBuilder::makeAssignNode(const JSTokenLocation& location, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end, unsigned divotLine, unsigned divotLineStart) { if (!loc->isLocation()) - return new (m_globalData) AssignErrorNode(location, divot, divot - start, end - divot); + return new (m_vm) AssignErrorNode(location, divot, divot - start, end - divot, divotLine, divotLineStart); if (loc->isResolveNode()) { ResolveNode* resolve = static_cast<ResolveNode*>(loc); if (op == OpEqual) { if (expr->isFuncExprNode()) static_cast<FuncExprNode*>(expr)->body()->setInferredName(resolve->identifier()); - AssignResolveNode* node = new (m_globalData) AssignResolveNode(location, resolve->identifier(), expr); - setExceptionLocation(node, start, divot, end); + AssignResolveNode* node = new (m_vm) AssignResolveNode(location, resolve->identifier(), expr); + setExceptionLocation(node, start, divot, end, divotLine, divotLineStart); return node; } - return new (m_globalData) ReadModifyResolveNode(location, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot); + return new (m_vm) ReadModifyResolveNode(location, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot, divotLine, divotLineStart); } if (loc->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc); if (op == OpEqual) - return new (m_globalData) AssignBracketNode(location, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot()); - ReadModifyBracketNode* node = new (m_globalData) ReadModifyBracketNode(location, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, divot - start, end - divot); - node->setSubexpressionInfo(bracket->divot(), bracket->endOffset()); + return new (m_vm) AssignBracketNode(location, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot(), bracket->divotLine(), bracket->divotLineStart()); + ReadModifyBracketNode* node = new (m_vm) ReadModifyBracketNode(location, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, divot - start, end - divot, divotLine, divotLineStart); + node->setSubexpressionInfo(bracket->divot(), bracket->divotEndOffset(), bracket->divotLine(), bracket->divotLineStart()); return node; } ASSERT(loc->isDotAccessorNode()); @@ -933,22 +966,22 @@ ExpressionNode* ASTBuilder::makeAssignNode(const JSTokenLocation& location, Expr if (op == OpEqual) { if (expr->isFuncExprNode()) static_cast<FuncExprNode*>(expr)->body()->setInferredName(dot->identifier()); - return new (m_globalData) AssignDotNode(location, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot()); + return new (m_vm) AssignDotNode(location, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot(), dot->divotLine(), dot->divotLineStart()); } - ReadModifyDotNode* node = new (m_globalData) ReadModifyDotNode(location, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot); - node->setSubexpressionInfo(dot->divot(), dot->endOffset()); + ReadModifyDotNode* node = new (m_vm) ReadModifyDotNode(location, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot, divotLine, divotLineStart); + node->setSubexpressionInfo(dot->divot(), dot->divotEndOffset(), dot->divotLine(), dot->divotLineStart()); return node; } -ExpressionNode* ASTBuilder::makePrefixNode(const JSTokenLocation& location, ExpressionNode* expr, Operator op, int start, int divot, int end) +ExpressionNode* ASTBuilder::makePrefixNode(const JSTokenLocation& location, ExpressionNode* expr, Operator op, int start, int divot, int end, unsigned divotLine, unsigned divotLineStart) { - return new (m_globalData) PrefixNode(location, expr, op, divot, divot - start, end - divot); + return new (m_vm) PrefixNode(location, expr, op, divot, divot - start, end - divot, divotLine, divotLineStart); } -ExpressionNode* ASTBuilder::makePostfixNode(const JSTokenLocation& location, ExpressionNode* expr, Operator op, int start, int divot, int end) +ExpressionNode* ASTBuilder::makePostfixNode(const JSTokenLocation& location, ExpressionNode* expr, Operator op, int start, int divot, int end, unsigned divotLine, unsigned divotLineStart) { - return new (m_globalData) PostfixNode(location, expr, op, divot, divot - start, end - divot); + return new (m_vm) PostfixNode(location, expr, op, divot, divot - start, end - divot, divotLine, divotLineStart); } } diff --git a/Source/JavaScriptCore/parser/Lexer.cpp b/Source/JavaScriptCore/parser/Lexer.cpp index 477d403c1..4925656a7 100644 --- a/Source/JavaScriptCore/parser/Lexer.cpp +++ b/Source/JavaScriptCore/parser/Lexer.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All Rights Reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012, 2013 Apple Inc. All Rights Reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2010 Zoltan Herczeg (zherczeg@inf.u-szeged.hu) * Copyright (C) 2012 Mathias Bynens (mathias@qiwi.be) @@ -46,8 +46,8 @@ using namespace Unicode; namespace JSC { -Keywords::Keywords(JSGlobalData* globalData) - : m_globalData(globalData) +Keywords::Keywords(VM* vm) + : m_vm(vm) , m_keywordTable(JSC::mainTable) { } @@ -489,9 +489,9 @@ static const LChar singleCharacterEscapeValuesForASCII[128] = { }; template <typename T> -Lexer<T>::Lexer(JSGlobalData* globalData) +Lexer<T>::Lexer(VM* vm) : m_isReparsing(false) - , m_globalData(globalData) + , m_vm(vm) { } @@ -524,7 +524,7 @@ String Lexer<T>::invalidCharacterMessage() const } template <typename T> -ALWAYS_INLINE const T* Lexer<T>::currentCharacter() const +ALWAYS_INLINE const T* Lexer<T>::currentSourcePtr() const { ASSERT(m_code <= m_codeEnd); return m_code; @@ -546,11 +546,13 @@ void Lexer<T>::setCode(const SourceCode& source, ParserArena* arena) m_codeStart = 0; m_source = &source; - m_code = m_codeStart + source.startOffset(); + m_sourceOffset = source.startOffset(); + m_codeStartPlusOffset = m_codeStart + source.startOffset(); + m_code = m_codeStartPlusOffset; m_codeEnd = m_codeStart + source.endOffset(); m_error = false; m_atLineStart = true; - m_columnNumber = 0; + m_lineStart = m_code; m_lexErrorMessage = String(); m_buffer8.reserveInitialCapacity(initialReadBufferCapacity); @@ -567,7 +569,7 @@ template <typename T> template <int shiftAmount> ALWAYS_INLINE void Lexer<T>::internalShift() { m_code += shiftAmount; - m_columnNumber += shiftAmount; + ASSERT(currentOffset() >= currentLineStartOffset()); m_current = *m_code; } @@ -579,7 +581,6 @@ ALWAYS_INLINE void Lexer<T>::shift() ++m_code; if (LIKELY(m_code < m_codeEnd)) m_current = *m_code; - ++m_columnNumber; } template <typename T> @@ -598,21 +599,21 @@ ALWAYS_INLINE T Lexer<T>::peek(int offset) const } template <typename T> -int Lexer<T>::parseFourDigitUnicodeHex() +typename Lexer<T>::UnicodeHexValue Lexer<T>::parseFourDigitUnicodeHex() { T char1 = peek(1); T char2 = peek(2); T char3 = peek(3); if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(char1) || !isASCIIHexDigit(char2) || !isASCIIHexDigit(char3))) - return -1; + return UnicodeHexValue((m_code + 4) >= m_codeEnd ? UnicodeHexValue::IncompleteHex : UnicodeHexValue::InvalidHex); int result = convertUnicode(m_current, char1, char2, char3); shift(); shift(); shift(); shift(); - return result; + return UnicodeHexValue(result); } template <typename T> @@ -768,20 +769,21 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<LChar>::p } } - const LChar* identifierStart = currentCharacter(); + const LChar* identifierStart = currentSourcePtr(); + unsigned identifierLineStart = currentLineStartOffset(); while (isIdentPart(m_current)) shift(); if (UNLIKELY(m_current == '\\')) { - setOffsetFromCharOffset(identifierStart); + setOffsetFromSourcePtr(identifierStart, identifierLineStart); return parseIdentifierSlowCase<shouldCreateIdentifier>(tokenData, lexerFlags, strictMode); } const Identifier* ident = 0; if (shouldCreateIdentifier) { - int identifierLength = currentCharacter() - identifierStart; + int identifierLength = currentSourcePtr() - identifierStart; ident = makeIdentifier(identifierStart, identifierLength); tokenData->ident = ident; @@ -791,7 +793,7 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<LChar>::p if (UNLIKELY((remaining < maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords))) { ASSERT(shouldCreateIdentifier); if (remaining < maxTokenLength) { - const HashEntry* entry = m_globalData->keywords->getKeyword(*ident); + const HashEntry* entry = m_vm->keywords->getKeyword(*ident); ASSERT((remaining < maxTokenLength) || !entry); if (!entry) return IDENT; @@ -816,7 +818,8 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<UChar>::p } } - const UChar* identifierStart = currentCharacter(); + const UChar* identifierStart = currentSourcePtr(); + int identifierLineStart = currentLineStartOffset(); UChar orAllChars = 0; @@ -826,7 +829,7 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<UChar>::p } if (UNLIKELY(m_current == '\\')) { - setOffsetFromCharOffset(identifierStart); + setOffsetFromSourcePtr(identifierStart, identifierLineStart); return parseIdentifierSlowCase<shouldCreateIdentifier>(tokenData, lexerFlags, strictMode); } @@ -838,7 +841,7 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<UChar>::p const Identifier* ident = 0; if (shouldCreateIdentifier) { - int identifierLength = currentCharacter() - identifierStart; + int identifierLength = currentSourcePtr() - identifierStart; if (isAll8Bit) ident = makeIdentifierLCharFromUChar(identifierStart, identifierLength); else @@ -851,7 +854,7 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<UChar>::p if (UNLIKELY((remaining < maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords))) { ASSERT(shouldCreateIdentifier); if (remaining < maxTokenLength) { - const HashEntry* entry = m_globalData->keywords->getKeyword(*ident); + const HashEntry* entry = m_vm->keywords->getKeyword(*ident); ASSERT((remaining < maxTokenLength) || !entry); if (!entry) return IDENT; @@ -868,7 +871,7 @@ template <typename T> template <bool shouldCreateIdentifier> JSTokenType Lexer<T>::parseIdentifierSlowCase(JSTokenData* tokenData, unsigned lexerFlags, bool strictMode) { const ptrdiff_t remaining = m_codeEnd - m_code; - const T* identifierStart = currentCharacter(); + const T* identifierStart = currentSourcePtr(); bool bufferRequired = false; while (true) { @@ -881,32 +884,32 @@ template <bool shouldCreateIdentifier> JSTokenType Lexer<T>::parseIdentifierSlow // \uXXXX unicode characters. bufferRequired = true; - if (identifierStart != currentCharacter()) - m_buffer16.append(identifierStart, currentCharacter() - identifierStart); + if (identifierStart != currentSourcePtr()) + m_buffer16.append(identifierStart, currentSourcePtr() - identifierStart); shift(); if (UNLIKELY(m_current != 'u')) - return ERRORTOK; + return atEnd() ? UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK : INVALID_IDENTIFIER_ESCAPE_ERRORTOK; shift(); - int character = parseFourDigitUnicodeHex(); - if (UNLIKELY(character == -1)) - return ERRORTOK; - UChar ucharacter = static_cast<UChar>(character); + UnicodeHexValue character = parseFourDigitUnicodeHex(); + if (UNLIKELY(!character.isValid())) + return character.valueType() == UnicodeHexValue::IncompleteHex ? UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK : INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK; + UChar ucharacter = static_cast<UChar>(character.value()); if (UNLIKELY(m_buffer16.size() ? !isIdentPart(ucharacter) : !isIdentStart(ucharacter))) - return ERRORTOK; + return INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK; if (shouldCreateIdentifier) record16(ucharacter); - identifierStart = currentCharacter(); + identifierStart = currentSourcePtr(); } int identifierLength; const Identifier* ident = 0; if (shouldCreateIdentifier) { if (!bufferRequired) { - identifierLength = currentCharacter() - identifierStart; + identifierLength = currentSourcePtr() - identifierStart; ident = makeIdentifier(identifierStart, identifierLength); } else { - if (identifierStart != currentCharacter()) - m_buffer16.append(identifierStart, currentCharacter() - identifierStart); + if (identifierStart != currentSourcePtr()) + m_buffer16.append(identifierStart, currentSourcePtr() - identifierStart); ident = makeIdentifier(m_buffer16.data(), m_buffer16.size()); } @@ -918,7 +921,7 @@ template <bool shouldCreateIdentifier> JSTokenType Lexer<T>::parseIdentifierSlow ASSERT(shouldCreateIdentifier); // Keywords must not be recognized if there was an \uXXXX in the identifier. if (remaining < maxTokenLength) { - const HashEntry* entry = m_globalData->keywords->getKeyword(*ident); + const HashEntry* entry = m_vm->keywords->getKeyword(*ident); ASSERT((remaining < maxTokenLength) || !entry); if (!entry) return IDENT; @@ -943,19 +946,20 @@ static ALWAYS_INLINE bool characterRequiresParseStringSlowCase(UChar character) } template <typename T> -template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer<T>::parseString(JSTokenData* tokenData, bool strictMode) +template <bool shouldBuildStrings> ALWAYS_INLINE typename Lexer<T>::StringParseResult Lexer<T>::parseString(JSTokenData* tokenData, bool strictMode) { int startingOffset = currentOffset(); + int startingLineStartOffset = currentLineStartOffset(); int startingLineNumber = lineNumber(); T stringQuoteCharacter = m_current; shift(); - const T* stringStart = currentCharacter(); + const T* stringStart = currentSourcePtr(); while (m_current != stringQuoteCharacter) { if (UNLIKELY(m_current == '\\')) { - if (stringStart != currentCharacter() && shouldBuildStrings) - append8(stringStart, currentCharacter() - stringStart); + if (stringStart != currentSourcePtr() && shouldBuildStrings) + append8(stringStart, currentSourcePtr() - stringStart); shift(); LChar escape = singleEscape(m_current); @@ -971,7 +975,7 @@ template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer<T>::parseString(JSTo shift(); if (!isASCIIHexDigit(m_current) || !isASCIIHexDigit(peek(1))) { m_lexErrorMessage = "\\x can only be followed by a hex character sequence"; - return false; + return (atEnd() || (isASCIIHexDigit(m_current) && (m_code + 1 == m_codeEnd))) ? StringUnterminated : StringCannotBeParsed; } T prev = m_current; shift(); @@ -979,17 +983,17 @@ template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer<T>::parseString(JSTo record8(convertHex(prev, m_current)); shift(); } else { - setOffset(startingOffset); + setOffset(startingOffset, startingLineStartOffset); setLineNumber(startingLineNumber); m_buffer8.resize(0); return parseStringSlowCase<shouldBuildStrings>(tokenData, strictMode); } - stringStart = currentCharacter(); + stringStart = currentSourcePtr(); continue; } if (UNLIKELY(characterRequiresParseStringSlowCase(m_current))) { - setOffset(startingOffset); + setOffset(startingOffset, startingLineStartOffset); setLineNumber(startingLineNumber); m_buffer8.resize(0); return parseStringSlowCase<shouldBuildStrings>(tokenData, strictMode); @@ -998,29 +1002,29 @@ template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer<T>::parseString(JSTo shift(); } - if (currentCharacter() != stringStart && shouldBuildStrings) - append8(stringStart, currentCharacter() - stringStart); + if (currentSourcePtr() != stringStart && shouldBuildStrings) + append8(stringStart, currentSourcePtr() - stringStart); if (shouldBuildStrings) { tokenData->ident = makeIdentifier(m_buffer8.data(), m_buffer8.size()); m_buffer8.resize(0); } else tokenData->ident = 0; - return true; + return StringParsedSuccessfully; } template <typename T> -template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenData* tokenData, bool strictMode) +template <bool shouldBuildStrings> typename Lexer<T>::StringParseResult Lexer<T>::parseStringSlowCase(JSTokenData* tokenData, bool strictMode) { T stringQuoteCharacter = m_current; shift(); - const T* stringStart = currentCharacter(); + const T* stringStart = currentSourcePtr(); while (m_current != stringQuoteCharacter) { if (UNLIKELY(m_current == '\\')) { - if (stringStart != currentCharacter() && shouldBuildStrings) - append16(stringStart, currentCharacter() - stringStart); + if (stringStart != currentSourcePtr() && shouldBuildStrings) + append16(stringStart, currentSourcePtr() - stringStart); shift(); LChar escape = singleEscape(m_current); @@ -1036,7 +1040,7 @@ template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenDat shift(); if (!isASCIIHexDigit(m_current) || !isASCIIHexDigit(peek(1))) { m_lexErrorMessage = "\\x can only be followed by a hex character sequence"; - return false; + return StringCannotBeParsed; } T prev = m_current; shift(); @@ -1045,16 +1049,16 @@ template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenDat shift(); } else if (m_current == 'u') { shift(); - int character = parseFourDigitUnicodeHex(); - if (character != -1) { + UnicodeHexValue character = parseFourDigitUnicodeHex(); + if (character.isValid()) { if (shouldBuildStrings) - record16(character); + record16(character.value()); } else if (m_current == stringQuoteCharacter) { if (shouldBuildStrings) record16('u'); } else { m_lexErrorMessage = "\\u can only be followed by a Unicode character sequence"; - return false; + return character.valueType() == UnicodeHexValue::IncompleteHex ? StringUnterminated : StringCannotBeParsed; } } else if (strictMode && isASCIIDigit(m_current)) { // The only valid numeric escape in strict mode is '\0', and this must not be followed by a decimal digit. @@ -1062,7 +1066,7 @@ template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenDat shift(); if (character1 != '0' || isASCIIDigit(m_current)) { m_lexErrorMessage = "The only valid numeric escape in strict mode is '\\0'"; - return false; + return StringCannotBeParsed; } if (shouldBuildStrings) record16(0); @@ -1092,10 +1096,10 @@ template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenDat shift(); } else { m_lexErrorMessage = "Unterminated string constant"; - return false; + return StringUnterminated; } - stringStart = currentCharacter(); + stringStart = currentSourcePtr(); continue; } // Fast check for characters that require special handling. @@ -1105,22 +1109,22 @@ template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenDat // New-line or end of input is not allowed if (atEnd() || isLineTerminator(m_current)) { m_lexErrorMessage = "Unexpected EOF"; - return false; + return atEnd() ? StringUnterminated : StringCannotBeParsed; } // Anything else is just a normal character } shift(); } - if (currentCharacter() != stringStart && shouldBuildStrings) - append16(stringStart, currentCharacter() - stringStart); + if (currentSourcePtr() != stringStart && shouldBuildStrings) + append16(stringStart, currentSourcePtr() - stringStart); if (shouldBuildStrings) tokenData->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size()); else tokenData->ident = 0; m_buffer16.resize(0); - return true; + return StringParsedSuccessfully; } template <typename T> @@ -1319,7 +1323,7 @@ start: return EOFTOK; tokenLocation->startOffset = currentOffset(); - tokenLocation->column = m_columnNumber; + ASSERT(currentOffset() >= currentLineStartOffset()); CharacterType type; if (LIKELY(isLatin1(m_current))) @@ -1464,6 +1468,7 @@ start: if (parseMultilineComment()) goto start; m_lexErrorMessage = "Multiline comment was not closed properly"; + token = UNTERMINATED_MULTILINE_COMMENT_ERRORTOK; goto returnError; } if (m_current == '=') { @@ -1556,12 +1561,18 @@ start: token = SEMICOLON; break; case CharacterOpenBrace: - tokenData->intValue = currentOffset(); + tokenData->line = lineNumber(); + tokenData->offset = currentOffset(); + tokenData->lineStartOffset = currentLineStartOffset(); + ASSERT(tokenData->offset >= tokenData->lineStartOffset); shift(); token = OPENBRACE; break; case CharacterCloseBrace: - tokenData->intValue = currentOffset(); + tokenData->line = lineNumber(); + tokenData->offset = currentOffset(); + tokenData->lineStartOffset = currentLineStartOffset(); + ASSERT(tokenData->offset >= tokenData->lineStartOffset); shift(); token = CLOSEBRACE; break; @@ -1583,6 +1594,7 @@ start: if (parseOctal(tokenData->doubleValue)) { if (strictMode) { m_lexErrorMessage = "Octal escapes are forbidden in strict mode"; + token = INVALID_OCTAL_NUMBER_ERRORTOK; goto returnError; } token = NUMBER; @@ -1601,6 +1613,7 @@ inNumberAfterDecimalPoint: if ((m_current | 0x20) == 'e') { if (!parseNumberAfterExponentIndicator()) { m_lexErrorMessage = "Non-number found after exponent indicator"; + token = atEnd() ? UNTERMINATED_NUMERIC_LITERAL_ERRORTOK : INVALID_NUMERIC_LITERAL_ERRORTOK; goto returnError; } } @@ -1613,17 +1626,24 @@ inNumberAfterDecimalPoint: // No identifiers allowed directly after numeric literal, e.g. "3in" is bad. if (UNLIKELY(isIdentStart(m_current))) { m_lexErrorMessage = "At least one digit must occur after a decimal point"; + token = atEnd() ? UNTERMINATED_NUMERIC_LITERAL_ERRORTOK : INVALID_NUMERIC_LITERAL_ERRORTOK; goto returnError; } m_buffer8.resize(0); break; case CharacterQuote: if (lexerFlags & LexerFlagsDontBuildStrings) { - if (UNLIKELY(!parseString<false>(tokenData, strictMode))) + StringParseResult result = parseString<false>(tokenData, strictMode); + if (UNLIKELY(result != StringParsedSuccessfully)) { + token = result == StringUnterminated ? UNTERMINATED_STRING_LITERAL_ERRORTOK : INVALID_STRING_LITERAL_ERRORTOK; goto returnError; + } } else { - if (UNLIKELY(!parseString<true>(tokenData, strictMode))) + StringParseResult result = parseString<true>(tokenData, strictMode); + if (UNLIKELY(result != StringParsedSuccessfully)) { + token = result == StringUnterminated ? UNTERMINATED_STRING_LITERAL_ERRORTOK : INVALID_STRING_LITERAL_ERRORTOK; goto returnError; + } } shift(); token = STRING; @@ -1642,14 +1662,16 @@ inNumberAfterDecimalPoint: shiftLineTerminator(); m_atLineStart = true; m_terminator = true; - m_columnNumber = 0; + m_lineStart = m_code; goto start; case CharacterInvalid: m_lexErrorMessage = invalidCharacterMessage(); + token = ERRORTOK; goto returnError; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); m_lexErrorMessage = "Internal Error"; + token = ERRORTOK; goto returnError; } @@ -1665,7 +1687,7 @@ inSingleLineComment: shiftLineTerminator(); m_atLineStart = true; m_terminator = true; - m_columnNumber = 0; + m_lineStart = m_code; if (!lastTokenWasRestrKeyword()) goto start; @@ -1675,6 +1697,8 @@ inSingleLineComment: returnToken: tokenLocation->line = m_lineNumber; tokenLocation->endOffset = currentOffset(); + tokenLocation->lineStartOffset = currentLineStartOffset(); + ASSERT(tokenLocation->endOffset >= tokenLocation->lineStartOffset); m_lastToken = token; return token; @@ -1682,7 +1706,10 @@ returnError: m_error = true; tokenLocation->line = m_lineNumber; tokenLocation->endOffset = currentOffset(); - return ERRORTOK; + tokenLocation->lineStartOffset = currentLineStartOffset(); + ASSERT(tokenLocation->endOffset >= tokenLocation->lineStartOffset); + RELEASE_ASSERT(token & ErrorTokenFlag); + return token; } template <typename T> @@ -1820,11 +1847,11 @@ void Lexer<T>::clear() } template <typename T> -SourceCode Lexer<T>::sourceCode(int openBrace, int closeBrace, int firstLine) +SourceCode Lexer<T>::sourceCode(int openBrace, int closeBrace, int firstLine, unsigned startColumn) { ASSERT(m_source->provider()->source()[openBrace] == '{'); ASSERT(m_source->provider()->source()[closeBrace] == '}'); - return SourceCode(m_source->provider(), openBrace, closeBrace + 1, firstLine); + return SourceCode(m_source->provider(), openBrace, closeBrace + 1, firstLine, startColumn); } // Instantiate the two flavors of Lexer we need instead of putting most of this file in Lexer.h diff --git a/Source/JavaScriptCore/parser/Lexer.h b/Source/JavaScriptCore/parser/Lexer.h index 78c8c8cbd..5ecdcc650 100644 --- a/Source/JavaScriptCore/parser/Lexer.h +++ b/Source/JavaScriptCore/parser/Lexer.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012, 2013 Apple Inc. All rights reserved. * Copyright (C) 2010 Zoltan Herczeg (zherczeg@inf.u-szeged.hu) * * This library is free software; you can redistribute it and/or @@ -28,7 +28,6 @@ #include "ParserTokens.h" #include "SourceCode.h" #include <wtf/ASCIICType.h> -#include <wtf/AlwaysInline.h> #include <wtf/SegmentedVector.h> #include <wtf/Vector.h> #include <wtf/unicode/Unicode.h> @@ -39,12 +38,12 @@ class Keywords { public: bool isKeyword(const Identifier& ident) const { - return m_keywordTable.entry(m_globalData, ident); + return m_keywordTable.entry(m_vm, ident); } const HashEntry* getKeyword(const Identifier& ident) const { - return m_keywordTable.entry(m_globalData, ident); + return m_keywordTable.entry(m_vm, ident); } ~Keywords() @@ -53,11 +52,11 @@ public: } private: - friend class JSGlobalData; + friend class VM; - Keywords(JSGlobalData*); + Keywords(VM*); - JSGlobalData* m_globalData; + VM* m_vm; const HashTable m_keywordTable; }; @@ -73,7 +72,7 @@ class Lexer { WTF_MAKE_FAST_ALLOCATED; public: - Lexer(JSGlobalData*); + Lexer(VM*); ~Lexer(); // Character manipulation functions. @@ -90,11 +89,12 @@ public: JSTokenType lex(JSTokenData*, JSTokenLocation*, unsigned, bool strictMode); bool nextTokenIsColon(); int lineNumber() const { return m_lineNumber; } - int currentColumnNumber() const { return m_columnNumber; } + ALWAYS_INLINE int currentOffset() const { return offsetFromSourcePtr(m_code); } + ALWAYS_INLINE int currentLineStartOffset() const { return offsetFromSourcePtr(m_lineStart); } void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; } int lastLineNumber() const { return m_lastLineNumber; } bool prevTerminator() const { return m_terminator; } - SourceCode sourceCode(int openBrace, int closeBrace, int firstLine); + SourceCode sourceCode(int openBrace, int closeBrace, int firstLine, unsigned startColumn); bool scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix = 0); bool skipRegExp(); @@ -102,11 +102,15 @@ public: bool sawError() const { return m_error; } String getErrorMessage() const { return m_lexErrorMessage; } void clear(); - void setOffset(int offset) + void setOffset(int offset, int lineStartOffset) { m_error = 0; m_lexErrorMessage = String(); - m_code = m_codeStart + offset; + + m_code = sourcePtrFromOffset(offset); + m_lineStart = sourcePtrFromOffset(lineStartOffset); + ASSERT(currentOffset() >= currentLineStartOffset()); + m_buffer8.resize(0); m_buffer16.resize(0); if (LIKELY(m_code < m_codeEnd)) @@ -134,13 +138,44 @@ private: ALWAYS_INLINE void shift(); ALWAYS_INLINE bool atEnd() const; ALWAYS_INLINE T peek(int offset) const; - int parseFourDigitUnicodeHex(); + struct UnicodeHexValue { + + enum ValueType { ValidHex, IncompleteHex, InvalidHex }; + + explicit UnicodeHexValue(int value) + : m_value(value) + { + } + explicit UnicodeHexValue(ValueType type) + : m_value(type == IncompleteHex ? -2 : -1) + { + } + + ValueType valueType() const + { + if (m_value >= 0) + return ValidHex; + return m_value == -2 ? IncompleteHex : InvalidHex; + } + bool isValid() const { return m_value >= 0; } + int value() const + { + ASSERT(m_value >= 0); + return m_value; + } + + private: + int m_value; + }; + UnicodeHexValue parseFourDigitUnicodeHex(); void shiftLineTerminator(); + ALWAYS_INLINE int offsetFromSourcePtr(const T* ptr) const { return ptr - m_codeStart; } + ALWAYS_INLINE const T* sourcePtrFromOffset(int offset) const { return m_codeStart + offset; } + String invalidCharacterMessage() const; - ALWAYS_INLINE const T* currentCharacter() const; - ALWAYS_INLINE int currentOffset() const { return m_code - m_codeStart; } - ALWAYS_INLINE void setOffsetFromCharOffset(const T* charOffset) { setOffset(charOffset - m_codeStart); } + ALWAYS_INLINE const T* currentSourcePtr() const; + ALWAYS_INLINE void setOffsetFromSourcePtr(const T* sourcePtr, unsigned lineStartOffset) { setOffset(offsetFromSourcePtr(sourcePtr), lineStartOffset); } ALWAYS_INLINE void setCodeStart(const StringImpl*); @@ -157,8 +192,13 @@ private: template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType parseKeyword(JSTokenData*); template <bool shouldBuildIdentifiers> ALWAYS_INLINE JSTokenType parseIdentifier(JSTokenData*, unsigned lexerFlags, bool strictMode); template <bool shouldBuildIdentifiers> NEVER_INLINE JSTokenType parseIdentifierSlowCase(JSTokenData*, unsigned lexerFlags, bool strictMode); - template <bool shouldBuildStrings> ALWAYS_INLINE bool parseString(JSTokenData*, bool strictMode); - template <bool shouldBuildStrings> NEVER_INLINE bool parseStringSlowCase(JSTokenData*, bool strictMode); + enum StringParseResult { + StringParsedSuccessfully, + StringUnterminated, + StringCannotBeParsed + }; + template <bool shouldBuildStrings> ALWAYS_INLINE StringParseResult parseString(JSTokenData*, bool strictMode); + template <bool shouldBuildStrings> NEVER_INLINE StringParseResult parseStringSlowCase(JSTokenData*, bool strictMode); ALWAYS_INLINE void parseHex(double& returnValue); ALWAYS_INLINE bool parseOctal(double& returnValue); ALWAYS_INLINE bool parseDecimal(double& returnValue); @@ -170,7 +210,6 @@ private: int m_lineNumber; int m_lastLineNumber; - int m_columnNumber; Vector<LChar> m_buffer8; Vector<UChar> m_buffer16; @@ -178,9 +217,12 @@ private: int m_lastToken; const SourceCode* m_source; + unsigned m_sourceOffset; const T* m_code; const T* m_codeStart; const T* m_codeEnd; + const T* m_codeStartPlusOffset; + const T* m_lineStart; bool m_isReparsing; bool m_atLineStart; bool m_error; @@ -190,7 +232,7 @@ private: IdentifierArena* m_arena; - JSGlobalData* m_globalData; + VM* m_vm; }; template <> @@ -232,28 +274,28 @@ inline UChar Lexer<T>::convertUnicode(int c1, int c2, int c3, int c4) template <typename T> ALWAYS_INLINE const Identifier* Lexer<T>::makeIdentifier(const LChar* characters, size_t length) { - return &m_arena->makeIdentifier(m_globalData, characters, length); + return &m_arena->makeIdentifier(m_vm, characters, length); } template <typename T> ALWAYS_INLINE const Identifier* Lexer<T>::makeIdentifier(const UChar* characters, size_t length) { - return &m_arena->makeIdentifier(m_globalData, characters, length); + return &m_arena->makeIdentifier(m_vm, characters, length); } template <> ALWAYS_INLINE const Identifier* Lexer<LChar>::makeRightSizedIdentifier(const UChar* characters, size_t length, UChar) { - return &m_arena->makeIdentifierLCharFromUChar(m_globalData, characters, length); + return &m_arena->makeIdentifierLCharFromUChar(m_vm, characters, length); } template <> ALWAYS_INLINE const Identifier* Lexer<UChar>::makeRightSizedIdentifier(const UChar* characters, size_t length, UChar orAllChars) { if (!(orAllChars & ~0xff)) - return &m_arena->makeIdentifierLCharFromUChar(m_globalData, characters, length); + return &m_arena->makeIdentifierLCharFromUChar(m_vm, characters, length); - return &m_arena->makeIdentifier(m_globalData, characters, length); + return &m_arena->makeIdentifier(m_vm, characters, length); } template <> @@ -273,19 +315,19 @@ ALWAYS_INLINE void Lexer<UChar>::setCodeStart(const StringImpl* sourceString) template <typename T> ALWAYS_INLINE const Identifier* Lexer<T>::makeIdentifierLCharFromUChar(const UChar* characters, size_t length) { - return &m_arena->makeIdentifierLCharFromUChar(m_globalData, characters, length); + return &m_arena->makeIdentifierLCharFromUChar(m_vm, characters, length); } template <typename T> ALWAYS_INLINE const Identifier* Lexer<T>::makeLCharIdentifier(const LChar* characters, size_t length) { - return &m_arena->makeIdentifier(m_globalData, characters, length); + return &m_arena->makeIdentifier(m_vm, characters, length); } template <typename T> ALWAYS_INLINE const Identifier* Lexer<T>::makeLCharIdentifier(const UChar* characters, size_t length) { - return &m_arena->makeIdentifierLCharFromUChar(m_globalData, characters, length); + return &m_arena->makeIdentifierLCharFromUChar(m_vm, characters, length); } template <typename T> @@ -317,7 +359,7 @@ ALWAYS_INLINE JSTokenType Lexer<T>::lexExpectIdentifier(JSTokenData* tokenData, m_current = 0; m_code = ptr; - m_columnNumber = m_columnNumber + (m_code - start); + ASSERT(currentOffset() >= currentLineStartOffset()); // Create the identifier if needed if (lexerFlags & LexexFlagsDontBuildKeywords) @@ -325,9 +367,10 @@ ALWAYS_INLINE JSTokenType Lexer<T>::lexExpectIdentifier(JSTokenData* tokenData, else tokenData->ident = makeLCharIdentifier(start, ptr - start); tokenLocation->line = m_lineNumber; - tokenLocation->startOffset = start - m_codeStart; + tokenLocation->lineStartOffset = currentLineStartOffset(); + tokenLocation->startOffset = offsetFromSourcePtr(start); tokenLocation->endOffset = currentOffset(); - tokenLocation->column = m_columnNumber; + ASSERT(tokenLocation->startOffset >= tokenLocation->lineStartOffset); m_lastToken = IDENT; return IDENT; diff --git a/Source/JavaScriptCore/parser/NodeConstructors.h b/Source/JavaScriptCore/parser/NodeConstructors.h index 274491960..47f6eea09 100644 --- a/Source/JavaScriptCore/parser/NodeConstructors.h +++ b/Source/JavaScriptCore/parser/NodeConstructors.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2013 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -27,25 +27,27 @@ namespace JSC { - inline void* ParserArenaFreeable::operator new(size_t size, JSGlobalData* globalData) + inline void* ParserArenaFreeable::operator new(size_t size, VM* vm) { - return globalData->parserArena->allocateFreeable(size); + return vm->parserArena->allocateFreeable(size); } - inline void* ParserArenaDeletable::operator new(size_t size, JSGlobalData* globalData) + inline void* ParserArenaDeletable::operator new(size_t size, VM* vm) { - return globalData->parserArena->allocateDeletable(size); + return vm->parserArena->allocateDeletable(size); } - inline ParserArenaRefCounted::ParserArenaRefCounted(JSGlobalData* globalData) + inline ParserArenaRefCounted::ParserArenaRefCounted(VM* vm) { - globalData->parserArena->derefWithArena(adoptRef(this)); + vm->parserArena->derefWithArena(adoptRef(this)); } inline Node::Node(const JSTokenLocation& location) : m_lineNumber(location.line) - , m_columnNumber(location.column) + , m_startOffset(location.startOffset) + , m_lineStartOffset(location.lineStartOffset) { + ASSERT(location.startOffset >= location.lineStartOffset); } inline ExpressionNode::ExpressionNode(const JSTokenLocation& location, ResultType resultType) @@ -60,25 +62,30 @@ namespace JSC { { } + inline ConstantNode::ConstantNode(const JSTokenLocation& location, ResultType resultType) + : ExpressionNode(location, resultType) + { + } + inline NullNode::NullNode(const JSTokenLocation& location) - : ExpressionNode(location, ResultType::nullType()) + : ConstantNode(location, ResultType::nullType()) { } inline BooleanNode::BooleanNode(const JSTokenLocation& location, bool value) - : ExpressionNode(location, ResultType::booleanType()) + : ConstantNode(location, ResultType::booleanType()) , m_value(value) { } inline NumberNode::NumberNode(const JSTokenLocation& location, double value) - : ExpressionNode(location, ResultType::numberType()) + : ConstantNode(location, JSValue(value).isInt32() ? ResultType::numberTypeIsInt32() : ResultType::numberType()) , m_value(value) { } inline StringNode::StringNode(const JSTokenLocation& location, const Identifier& value) - : ExpressionNode(location, ResultType::stringType()) + : ConstantNode(location, ResultType::stringType()) , m_value(value) { } @@ -95,11 +102,14 @@ namespace JSC { { } - inline ResolveNode::ResolveNode(const JSTokenLocation& location, const Identifier& ident, int startOffset) +inline ResolveNode::ResolveNode(const JSTokenLocation& location, const Identifier& ident, unsigned startOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) , m_ident(ident) , m_startOffset(startOffset) + , m_divotLine(divotLine) + , m_divotLineStart(divotLineStart) { + ASSERT(m_startOffset >= m_divotLineStart); } inline ElementNode::ElementNode(int elision, ExpressionNode* node) @@ -141,29 +151,29 @@ namespace JSC { { } - inline PropertyNode::PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* assign, Type type) + inline PropertyNode::PropertyNode(VM*, const Identifier& name, ExpressionNode* assign, Type type) : m_name(name) , m_assign(assign) , m_type(type) { } - inline PropertyNode::PropertyNode(JSGlobalData* globalData, double name, ExpressionNode* assign, Type type) - : m_name(globalData->parserArena->identifierArena().makeNumericIdentifier(globalData, name)) + inline PropertyNode::PropertyNode(VM* vm, double name, ExpressionNode* assign, Type type) + : m_name(vm->parserArena->identifierArena().makeNumericIdentifier(vm, name)) , m_assign(assign) , m_type(type) { } inline PropertyListNode::PropertyListNode(const JSTokenLocation& location, PropertyNode* node) - : Node(location) + : ExpressionNode(location) , m_node(node) , m_next(0) { } inline PropertyListNode::PropertyListNode(const JSTokenLocation& location, PropertyNode* node, PropertyListNode* list) - : Node(location) + : ExpressionNode(location) , m_node(node) , m_next(0) { @@ -198,14 +208,14 @@ namespace JSC { } inline ArgumentListNode::ArgumentListNode(const JSTokenLocation& location, ExpressionNode* expr) - : Node(location) + : ExpressionNode(location) , m_next(0) , m_expr(expr) { } inline ArgumentListNode::ArgumentListNode(const JSTokenLocation& location, ArgumentListNode* listNode, ExpressionNode* expr) - : Node(location) + : ExpressionNode(location) , m_next(0) , m_expr(expr) { @@ -236,83 +246,81 @@ namespace JSC { { } - inline EvalFunctionCallNode::EvalFunctionCallNode(const JSTokenLocation& location, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + inline EvalFunctionCallNode::EvalFunctionCallNode(const JSTokenLocation& location, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) - , ThrowableExpressionData(divot, startOffset, endOffset) + , ThrowableExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_args(args) { + ASSERT(divot >= divotLineStart); } - inline FunctionCallValueNode::FunctionCallValueNode(const JSTokenLocation& location, ExpressionNode* expr, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + inline FunctionCallValueNode::FunctionCallValueNode(const JSTokenLocation& location, ExpressionNode* expr, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) - , ThrowableExpressionData(divot, startOffset, endOffset) + , ThrowableExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_expr(expr) , m_args(args) { } - inline FunctionCallResolveNode::FunctionCallResolveNode(const JSTokenLocation& location, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + inline FunctionCallResolveNode::FunctionCallResolveNode(const JSTokenLocation& location, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) - , ThrowableExpressionData(divot, startOffset, endOffset) + , ThrowableExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_ident(ident) , m_args(args) { } - inline FunctionCallBracketNode::FunctionCallBracketNode(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + inline FunctionCallBracketNode::FunctionCallBracketNode(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) - , ThrowableSubExpressionData(divot, startOffset, endOffset) + , ThrowableSubExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_base(base) , m_subscript(subscript) , m_args(args) { } - inline FunctionCallDotNode::FunctionCallDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) + inline FunctionCallDotNode::FunctionCallDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) - , ThrowableSubExpressionData(divot, startOffset, endOffset) + , ThrowableSubExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_base(base) , m_ident(ident) , m_args(args) { } - inline CallFunctionCallDotNode::CallFunctionCallDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) - : FunctionCallDotNode(location, base, ident, args, divot, startOffset, endOffset) + inline CallFunctionCallDotNode::CallFunctionCallDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) + : FunctionCallDotNode(location, base, ident, args, divot, startOffset, endOffset, divotLine, divotLineStart) { } - inline ApplyFunctionCallDotNode::ApplyFunctionCallDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset) - : FunctionCallDotNode(location, base, ident, args, divot, startOffset, endOffset) + inline ApplyFunctionCallDotNode::ApplyFunctionCallDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, ArgumentsNode* args, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) + : FunctionCallDotNode(location, base, ident, args, divot, startOffset, endOffset, divotLine, divotLineStart) { } - inline PostfixNode::PostfixNode(const JSTokenLocation& location, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) - : ExpressionNode(location) - , ThrowableExpressionData(divot, startOffset, endOffset) - , m_expr(expr) - , m_operator(oper) + inline PostfixNode::PostfixNode(const JSTokenLocation& location, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) + : PrefixNode(location, expr, oper, divot, startOffset, endOffset, divotLine, divotLineStart) { } - inline DeleteResolveNode::DeleteResolveNode(const JSTokenLocation& location, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) + inline DeleteResolveNode::DeleteResolveNode(const JSTokenLocation& location, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) - , ThrowableExpressionData(divot, startOffset, endOffset) + , ThrowableExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_ident(ident) { } - inline DeleteBracketNode::DeleteBracketNode(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset) + inline DeleteBracketNode::DeleteBracketNode(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) - , ThrowableExpressionData(divot, startOffset, endOffset) + , ThrowableExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_base(base) , m_subscript(subscript) { } - inline DeleteDotNode::DeleteDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset) + inline DeleteDotNode::DeleteDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) - , ThrowableExpressionData(divot, startOffset, endOffset) + , ThrowableExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_base(base) , m_ident(ident) { @@ -342,9 +350,9 @@ namespace JSC { { } - inline PrefixNode::PrefixNode(const JSTokenLocation& location, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset) + inline PrefixNode::PrefixNode(const JSTokenLocation& location, ExpressionNode* expr, Operator oper, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) - , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset) + , ThrowablePrefixedSubExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_expr(expr) , m_operator(oper) { @@ -358,7 +366,7 @@ namespace JSC { } inline UnaryPlusNode::UnaryPlusNode(const JSTokenLocation& location, ExpressionNode* expr) - : UnaryOpNode(location, ResultType::numberType(), expr, op_to_jsnumber) + : UnaryOpNode(location, ResultType::numberType(), expr, op_to_number) { } @@ -528,14 +536,16 @@ namespace JSC { { } - inline ReadModifyResolveNode::ReadModifyResolveNode(const JSTokenLocation& location, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) + inline ReadModifyResolveNode::ReadModifyResolveNode(const JSTokenLocation& location, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) - , ThrowableExpressionData(divot, startOffset, endOffset) + , ThrowableExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_ident(ident) , m_right(right) , m_operator(oper) , m_rightHasAssignments(rightHasAssignments) { + ASSERT(divot >= divotLineStart); + ASSERT(divot - startOffset >= divotLineStart); } inline AssignResolveNode::AssignResolveNode(const JSTokenLocation& location, const Identifier& ident, ExpressionNode* right) @@ -545,9 +555,9 @@ namespace JSC { { } - inline ReadModifyBracketNode::ReadModifyBracketNode(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) + inline ReadModifyBracketNode::ReadModifyBracketNode(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* subscript, Operator oper, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) - , ThrowableSubExpressionData(divot, startOffset, endOffset) + , ThrowableSubExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_base(base) , m_subscript(subscript) , m_right(right) @@ -557,9 +567,9 @@ namespace JSC { { } - inline AssignBracketNode::AssignBracketNode(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) + inline AssignBracketNode::AssignBracketNode(const JSTokenLocation& location, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) - , ThrowableExpressionData(divot, startOffset, endOffset) + , ThrowableExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_base(base) , m_subscript(subscript) , m_right(right) @@ -568,9 +578,9 @@ namespace JSC { { } - inline AssignDotNode::AssignDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) + inline AssignDotNode::AssignDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) - , ThrowableExpressionData(divot, startOffset, endOffset) + , ThrowableExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_base(base) , m_ident(ident) , m_right(right) @@ -578,9 +588,9 @@ namespace JSC { { } - inline ReadModifyDotNode::ReadModifyDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset) + inline ReadModifyDotNode::ReadModifyDotNode(const JSTokenLocation& location, ExpressionNode* base, const Identifier& ident, Operator oper, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) - , ThrowableSubExpressionData(divot, startOffset, endOffset) + , ThrowableSubExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_base(base) , m_ident(ident) , m_right(right) @@ -589,9 +599,9 @@ namespace JSC { { } - inline AssignErrorNode::AssignErrorNode(const JSTokenLocation& location, unsigned divot, unsigned startOffset, unsigned endOffset) + inline AssignErrorNode::AssignErrorNode(const JSTokenLocation& location, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : ExpressionNode(location) - , ThrowableExpressionData(divot, startOffset, endOffset) + , ThrowableExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) { } @@ -634,15 +644,10 @@ namespace JSC { { } - inline IfNode::IfNode(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* ifBlock) + inline IfElseNode::IfElseNode(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock) : StatementNode(location) , m_condition(condition) , m_ifBlock(ifBlock) - { - } - - inline IfElseNode::IfElseNode(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock) - : IfNode(location, condition, ifBlock) , m_elseBlock(elseBlock) { } @@ -671,9 +676,9 @@ namespace JSC { ASSERT(statement); } - inline ContinueNode::ContinueNode(JSGlobalData* globalData, const JSTokenLocation& location) + inline ContinueNode::ContinueNode(VM* vm, const JSTokenLocation& location) : StatementNode(location) - , m_ident(globalData->propertyNames->nullIdentifier) + , m_ident(vm->propertyNames->nullIdentifier) { } @@ -683,9 +688,9 @@ namespace JSC { { } - inline BreakNode::BreakNode(JSGlobalData* globalData, const JSTokenLocation& location) + inline BreakNode::BreakNode(VM* vm, const JSTokenLocation& location) : StatementNode(location) - , m_ident(globalData->propertyNames->nullIdentifier) + , m_ident(vm->propertyNames->nullIdentifier) { } @@ -701,11 +706,13 @@ namespace JSC { { } - inline WithNode::WithNode(const JSTokenLocation& location, ExpressionNode* expr, StatementNode* statement, uint32_t divot, uint32_t expressionLength) + inline WithNode::WithNode(const JSTokenLocation& location, ExpressionNode* expr, StatementNode* statement, uint32_t divot, unsigned divotLine, unsigned divotLineStart, uint32_t expressionLength) : StatementNode(location) , m_expr(expr) , m_statement(statement) , m_divot(divot) + , m_divotLine(divotLine) + , m_divotLineStart(divotLineStart) , m_expressionLength(expressionLength) { } @@ -815,16 +822,17 @@ namespace JSC { { } - inline ForInNode::ForInNode(JSGlobalData* globalData, const JSTokenLocation& location, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset) + inline ForInNode::ForInNode(VM* vm, const JSTokenLocation& location, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, unsigned divot, int startOffset, int endOffset, unsigned divotLine, unsigned divotLineStart) : StatementNode(location) , m_init(0) - , m_lexpr(new (globalData) ResolveNode(location, ident, divot - startOffset)) + , m_lexpr(new (vm) ResolveNode(location, ident, divot - startOffset, divotLine, divotLineStart)) , m_expr(expr) , m_statement(statement) { if (in) { - AssignResolveNode* node = new (globalData) AssignResolveNode(location, ident, in); - node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot); + AssignResolveNode* node = new (vm) AssignResolveNode(location, ident, in); + ASSERT(divot >= divotLineStart); + node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot, divotLine, divotLineStart); m_init = node; } // for( var foo = bar in baz ) diff --git a/Source/JavaScriptCore/parser/Nodes.cpp b/Source/JavaScriptCore/parser/Nodes.cpp index 03ee8ee12..97ffaa163 100644 --- a/Source/JavaScriptCore/parser/Nodes.cpp +++ b/Source/JavaScriptCore/parser/Nodes.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) -* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. +* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * Copyright (C) 2007 Eric Seidel <eric@webkit.org> @@ -52,18 +52,13 @@ namespace JSC { // ------------------------------ StatementNode -------------------------------- -void StatementNode::setLoc(int firstLine, int lastLine, int column) +void StatementNode::setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset) { m_lineNumber = firstLine; m_lastLine = lastLine; - m_columnNumber = column; -} - -void StatementNode::setLoc(int firstLine, int lastLine) -{ - m_lineNumber = firstLine; - m_lastLine = lastLine; - m_columnNumber = 0; + m_startOffset = startOffset; + m_lineStartOffset = lineStartOffset; + ASSERT(m_startOffset >= m_lineStartOffset); } // ------------------------------ SourceElements -------------------------------- @@ -83,24 +78,30 @@ StatementNode* SourceElements::singleStatement() const // ------------------------------ ScopeNode ----------------------------- -ScopeNode::ScopeNode(JSGlobalData* globalData, const JSTokenLocation& location, bool inStrictContext) - : StatementNode(location) - , ParserArenaRefCounted(globalData) +ScopeNode::ScopeNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, bool inStrictContext) + : StatementNode(endLocation) + , ParserArenaRefCounted(vm) + , m_startLineNumber(startLocation.line) + , m_startStartOffset(startLocation.startOffset) + , m_startLineStartOffset(startLocation.lineStartOffset) , m_features(inStrictContext ? StrictModeFeature : NoFeatures) , m_numConstants(0) , m_statements(0) { } -ScopeNode::ScopeNode(JSGlobalData* globalData, const JSTokenLocation& location, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants) - : StatementNode(location) - , ParserArenaRefCounted(globalData) +ScopeNode::ScopeNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants) + : StatementNode(endLocation) + , ParserArenaRefCounted(vm) + , m_startLineNumber(startLocation.line) + , m_startStartOffset(startLocation.startOffset) + , m_startLineStartOffset(startLocation.lineStartOffset) , m_features(features) , m_source(source) , m_numConstants(numConstants) , m_statements(children) { - m_arena.swap(*globalData->parserArena); + m_arena.swap(*vm->parserArena); if (varStack) m_varStack.swap(*varStack); if (funcStack) @@ -115,14 +116,15 @@ StatementNode* ScopeNode::singleStatement() const // ------------------------------ ProgramNode ----------------------------- -inline ProgramNode::ProgramNode(JSGlobalData* globalData, const JSTokenLocation& location, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) - : ScopeNode(globalData, location, source, children, varStack, funcStack, capturedVariables, features, numConstants) +inline ProgramNode::ProgramNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) + : ScopeNode(vm, startLocation, endLocation, source, children, varStack, funcStack, capturedVariables, features, numConstants) + , m_startColumn(startColumn) { } -PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, const JSTokenLocation& location, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) +PassRefPtr<ProgramNode> ProgramNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) { - RefPtr<ProgramNode> node = new ProgramNode(globalData, location, children, varStack, funcStack, capturedVariables, source, features, numConstants); + RefPtr<ProgramNode> node = new ProgramNode(vm, startLocation, endLocation, startColumn, children, varStack, funcStack, capturedVariables, source, features, numConstants); ASSERT(node->m_arena.last() == node); node->m_arena.removeLast(); @@ -133,14 +135,14 @@ PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, const JSTo // ------------------------------ EvalNode ----------------------------- -inline EvalNode::EvalNode(JSGlobalData* globalData, const JSTokenLocation& location, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) - : ScopeNode(globalData, location, source, children, varStack, funcStack, capturedVariables, features, numConstants) +inline EvalNode::EvalNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) + : ScopeNode(vm, startLocation, endLocation, source, children, varStack, funcStack, capturedVariables, features, numConstants) { } -PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, const JSTokenLocation& location, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) +PassRefPtr<EvalNode> EvalNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants) { - RefPtr<EvalNode> node = new EvalNode(globalData, location, children, varStack, funcStack, capturedVariables, source, features, numConstants); + RefPtr<EvalNode> node = new EvalNode(vm, startLocation, endLocation, children, varStack, funcStack, capturedVariables, source, features, numConstants); ASSERT(node->m_arena.last() == node); node->m_arena.removeLast(); @@ -151,25 +153,40 @@ PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, const JSTokenLoc // ------------------------------ FunctionBodyNode ----------------------------- -FunctionParameters::FunctionParameters(ParameterNode* firstParameter) +PassRefPtr<FunctionParameters> FunctionParameters::create(ParameterNode* firstParameter) { unsigned parameterCount = 0; for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam()) ++parameterCount; - reserveInitialCapacity(parameterCount); + size_t objectSize = sizeof(FunctionParameters) - sizeof(void*) + sizeof(StringImpl*) * parameterCount; + void* slot = fastMalloc(objectSize); + return adoptRef(new (slot) FunctionParameters(firstParameter, parameterCount)); +} +FunctionParameters::FunctionParameters(ParameterNode* firstParameter, unsigned size) + : m_size(size) +{ + unsigned i = 0; for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam()) - uncheckedAppend(parameter->ident()); + new (&identifiers()[i++]) Identifier(parameter->ident()); +} + +FunctionParameters::~FunctionParameters() +{ + for (unsigned i = 0; i < m_size; ++i) + identifiers()[i].~Identifier(); } -inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, const JSTokenLocation& location, bool inStrictContext) - : ScopeNode(globalData, location, inStrictContext) +inline FunctionBodyNode::FunctionBodyNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, bool inStrictContext) + : ScopeNode(vm, startLocation, endLocation, inStrictContext) + , m_startColumn(startColumn) { } -inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, const JSTokenLocation& location, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) - : ScopeNode(globalData, location, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants) +inline FunctionBodyNode::FunctionBodyNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) + : ScopeNode(vm, startLocation, endLocation, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants) + , m_startColumn(startColumn) { } @@ -187,14 +204,14 @@ void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters, m_functionNameIsInScopeToggle = functionNameIsInScopeToggle; } -FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, const JSTokenLocation& location, bool inStrictContext) +FunctionBodyNode* FunctionBodyNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, bool inStrictContext) { - return new FunctionBodyNode(globalData, location, inStrictContext); + return new FunctionBodyNode(vm, startLocation, endLocation, startColumn, inStrictContext); } -PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, const JSTokenLocation& location, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) +PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants) { - RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, location, children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants); + RefPtr<FunctionBodyNode> node = new FunctionBodyNode(vm, startLocation, endLocation, startColumn, 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 509d36d1a..2eeaae9d9 100644 --- a/Source/JavaScriptCore/parser/Nodes.h +++ b/Source/JavaScriptCore/parser/Nodes.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * Copyright (C) 2007 Eric Seidel <eric@webkit.org> @@ -30,6 +30,7 @@ #include "JITCode.h" #include "Opcode.h" #include "ParserArena.h" +#include "ParserTokens.h" #include "ResultType.h" #include "SourceCode.h" #include "SymbolTable.h" @@ -47,19 +48,6 @@ namespace JSC { class JSScope; 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; - - const CodeFeatures AllFeatures = EvalFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature; - enum Operator { OpEqual, OpPlusEq, @@ -82,6 +70,12 @@ namespace JSC { OpLogicalOr }; + enum FallThroughMode { + FallThroughMeansTrue = 0, + FallThroughMeansFalse = 1 + }; + inline FallThroughMode invert(FallThroughMode fallThroughMode) { return static_cast<FallThroughMode>(!fallThroughMode); } + typedef HashSet<RefPtr<StringImpl>, IdentifierRepHash> IdentifierSet; namespace DeclarationStacks { @@ -100,7 +94,7 @@ namespace JSC { public: // ParserArenaFreeable objects are are freed when the arena is deleted. // Destructors are not called. Clients must not call delete on such objects. - void* operator new(size_t, JSGlobalData*); + void* operator new(size_t, VM*); }; class ParserArenaDeletable { @@ -109,7 +103,7 @@ namespace JSC { // ParserArenaDeletable objects are deleted when the arena is deleted. // Clients must not call delete directly on such objects. - void* operator new(size_t, JSGlobalData*); + void* operator new(size_t, VM*); }; template <typename T> @@ -119,7 +113,7 @@ namespace JSC { class ParserArenaRefCounted : public RefCounted<ParserArenaRefCounted> { protected: - ParserArenaRefCounted(JSGlobalData*); + ParserArenaRefCounted(VM*); public: virtual ~ParserArenaRefCounted() @@ -135,15 +129,14 @@ namespace JSC { public: virtual ~Node() { } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0; - int lineNo() const { return m_lineNumber; } - - int columnNo() const { return m_columnNumber; } + int startOffset() const { return m_startOffset; } + int lineStartOffset() const { return m_lineStartOffset; } protected: int m_lineNumber; - int m_columnNumber; + int m_startOffset; + int m_lineStartOffset; }; class ExpressionNode : public Node { @@ -151,10 +144,13 @@ namespace JSC { ExpressionNode(const JSTokenLocation&, ResultType = ResultType::unknownType()); public: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0; + virtual bool isNumber() const { return false; } virtual bool isString() const { return false; } virtual bool isNull() const { return false; } virtual bool isPure(BytecodeGenerator&) const { return false; } + virtual bool isConstant() const { return false; } virtual bool isLocation() const { return false; } virtual bool isResolveNode() const { return false; } virtual bool isBracketAccessorNode() const { return false; } @@ -164,9 +160,9 @@ namespace JSC { virtual bool isSimpleArray() const { return false; } virtual bool isAdd() const { return false; } virtual bool isSubtract() const { return false; } - virtual bool hasConditionContextCodegen() const { return false; } + virtual bool isBoolean() const { return false; } - virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, bool) { ASSERT_NOT_REACHED(); } + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, FallThroughMode); virtual ExpressionNode* stripUnaryPlus() { return this; } @@ -181,72 +177,76 @@ namespace JSC { StatementNode(const JSTokenLocation&); public: - JS_EXPORT_PRIVATE void setLoc(int firstLine, int lastLine); - void setLoc(int firstLine, int lastLine, int column); - int firstLine() const { return lineNo(); } - int lastLine() const { return m_lastLine; } - int column() const { return columnNo();} + virtual void emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0; + + void setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset); + unsigned firstLine() const { return lineNo(); } + unsigned lastLine() const { return m_lastLine; } virtual bool isEmptyStatement() const { return false; } virtual bool isReturnNode() const { return false; } virtual bool isExprStatement() const { return false; } - + virtual bool isBreak() const { return false; } + virtual bool isContinue() const { return false; } virtual bool isBlock() const { return false; } private: int m_lastLine; }; - class NullNode : public ExpressionNode { + class ConstantNode : public ExpressionNode { public: - NullNode(const JSTokenLocation&); - + ConstantNode(const JSTokenLocation&, ResultType); + virtual bool isPure(BytecodeGenerator&) const { return true; } + virtual bool isConstant() const { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const = 0; private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode); + }; + class NullNode : public ConstantNode { + public: + NullNode(const JSTokenLocation&); + + private: virtual bool isNull() const { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const { return jsNull(); } }; - class BooleanNode : public ExpressionNode { + class BooleanNode : public ConstantNode { public: BooleanNode(const JSTokenLocation&, bool value); + bool value() { return m_value; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - - virtual bool isPure(BytecodeGenerator&) const { return true; } + virtual bool isBoolean() const { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const { return jsBoolean(m_value); } bool m_value; }; - class NumberNode : public ExpressionNode { + class NumberNode : public ConstantNode { public: NumberNode(const JSTokenLocation&, double value); - - double value() const { return m_value; } + double value() { return m_value; } void setValue(double value) { m_value = value; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - virtual bool isNumber() const { return true; } - virtual bool isPure(BytecodeGenerator&) const { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const { return jsNumber(m_value); } double m_value; }; - class StringNode : public ExpressionNode { + class StringNode : public ConstantNode { public: StringNode(const JSTokenLocation&, const Identifier&); - const Identifier& value() { return m_value; } private: - virtual bool isPure(BytecodeGenerator&) const { return true; } - - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - virtual bool isString() const { return true; } + virtual JSValue jsValue(BytecodeGenerator&) const; const Identifier& m_value; }; @@ -255,36 +255,48 @@ namespace JSC { public: ThrowableExpressionData() : m_divot(static_cast<uint32_t>(-1)) - , m_startOffset(static_cast<uint16_t>(-1)) - , m_endOffset(static_cast<uint16_t>(-1)) + , m_divotStartOffset(static_cast<uint16_t>(-1)) + , m_divotEndOffset(static_cast<uint16_t>(-1)) + , m_divotLine(static_cast<uint32_t>(-1)) + , m_divotLineStart(static_cast<uint32_t>(-1)) { } - ThrowableExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset) + ThrowableExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) : m_divot(divot) - , m_startOffset(startOffset) - , m_endOffset(endOffset) + , m_divotStartOffset(startOffset) + , m_divotEndOffset(endOffset) + , m_divotLine(divotLine) + , m_divotLineStart(divotLineStart) { + ASSERT(m_divot >= m_divotLineStart); } - void setExceptionSourceCode(unsigned divot, unsigned startOffset, unsigned endOffset) + void setExceptionSourceCode(unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) { + ASSERT(divot >= divotLineStart); m_divot = divot; - m_startOffset = startOffset; - m_endOffset = endOffset; + m_divotStartOffset = startOffset; + m_divotEndOffset = endOffset; + m_divotLine = divotLine; + m_divotLineStart = divotLineStart; } uint32_t divot() const { return m_divot; } - uint16_t startOffset() const { return m_startOffset; } - uint16_t endOffset() const { return m_endOffset; } + uint16_t divotStartOffset() const { return m_divotStartOffset; } + uint16_t divotEndOffset() const { return m_divotEndOffset; } + uint32_t divotLine() const { return m_divotLine; } + uint32_t divotLineStart() const { return m_divotLineStart; } protected: RegisterID* emitThrowReferenceError(BytecodeGenerator&, const String& message); private: uint32_t m_divot; - uint16_t m_startOffset; - uint16_t m_endOffset; + uint16_t m_divotStartOffset; + uint16_t m_divotEndOffset; + uint32_t m_divotLine; + uint32_t m_divotLineStart; }; class ThrowableSubExpressionData : public ThrowableExpressionData { @@ -292,28 +304,48 @@ namespace JSC { ThrowableSubExpressionData() : m_subexpressionDivotOffset(0) , m_subexpressionEndOffset(0) + , m_subexpressionLineOffset(0) + , m_subexpressionLineStartOffset(0) { } - ThrowableSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset) - : ThrowableExpressionData(divot, startOffset, endOffset) + ThrowableSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) + : ThrowableExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_subexpressionDivotOffset(0) , m_subexpressionEndOffset(0) + , m_subexpressionLineOffset(0) + , m_subexpressionLineStartOffset(0) { } - void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) + void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset, uint32_t subexpressionLine, uint32_t subexpressionLineStart) { ASSERT(subexpressionDivot <= divot()); - if ((divot() - subexpressionDivot) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot + // Overflow means we can't do this safely, so just point at the primary divot, + // divotLine, or divotLineStart. + if ((divot() - subexpressionDivot) & ~0xFFFF) + return; + if ((divotLine() - subexpressionLine) & ~0xFFFF) + return; + if ((divotLineStart() - subexpressionLineStart) & ~0xFFFF) return; m_subexpressionDivotOffset = divot() - subexpressionDivot; m_subexpressionEndOffset = subexpressionOffset; + m_subexpressionLineOffset = divotLine() - subexpressionLine; + m_subexpressionLineStartOffset = divotLineStart() - subexpressionLineStart; } + unsigned subexpressionDivot() { return divot() - m_subexpressionDivotOffset; } + unsigned subexpressionStartOffset() { return divotStartOffset() - m_subexpressionDivotOffset; } + unsigned subexpressionEndOffset() { return m_subexpressionEndOffset; } + unsigned subexpressionLine() { return divotLine() - m_subexpressionLineOffset; } + unsigned subexpressionLineStart() { return divotLineStart() - m_subexpressionLineStartOffset; } + protected: uint16_t m_subexpressionDivotOffset; uint16_t m_subexpressionEndOffset; + uint16_t m_subexpressionLineOffset; + uint16_t m_subexpressionLineStartOffset; }; class ThrowablePrefixedSubExpressionData : public ThrowableExpressionData { @@ -321,28 +353,48 @@ namespace JSC { ThrowablePrefixedSubExpressionData() : m_subexpressionDivotOffset(0) , m_subexpressionStartOffset(0) + , m_subexpressionLineOffset(0) + , m_subexpressionLineStartOffset(0) { } - ThrowablePrefixedSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset) - : ThrowableExpressionData(divot, startOffset, endOffset) + ThrowablePrefixedSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart) + : ThrowableExpressionData(divot, startOffset, endOffset, divotLine, divotLineStart) , m_subexpressionDivotOffset(0) , m_subexpressionStartOffset(0) + , m_subexpressionLineOffset(0) + , m_subexpressionLineStartOffset(0) { } - void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) + void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset, uint32_t subexpressionLine, uint32_t subexpressionLineStart) { ASSERT(subexpressionDivot >= divot()); - if ((subexpressionDivot - divot()) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot + // Overflow means we can't do this safely, so just point at the primary divot, + // divotLine, or divotLineStart. + if ((subexpressionDivot - divot()) & ~0xFFFF) + return; + if ((subexpressionLine - divotLine()) & ~0xFFFF) + return; + if ((subexpressionLineStart - divotLineStart()) & ~0xFFFF) return; m_subexpressionDivotOffset = subexpressionDivot - divot(); m_subexpressionStartOffset = subexpressionOffset; + m_subexpressionLineOffset = subexpressionLine - divotLine(); + m_subexpressionLineStartOffset = subexpressionLineStart - divotLineStart(); } + unsigned subexpressionDivot() { return divot() + m_subexpressionDivotOffset; } + unsigned subexpressionStartOffset() { return m_subexpressionStartOffset; } + unsigned subexpressionEndOffset() { return divotEndOffset() + m_subexpressionDivotOffset; } + unsigned subexpressionLine() { return divotLine() + m_subexpressionLineOffset; } + unsigned subexpressionLineStart() { return divotLineStart() + m_subexpressionLineStartOffset; } + protected: uint16_t m_subexpressionDivotOffset; uint16_t m_subexpressionStartOffset; + uint16_t m_subexpressionLineOffset; + uint16_t m_subexpressionLineStartOffset; }; class RegExpNode : public ExpressionNode, public ThrowableExpressionData { @@ -366,7 +418,7 @@ namespace JSC { class ResolveNode : public ExpressionNode { public: - ResolveNode(const JSTokenLocation&, const Identifier&, int startOffset); + ResolveNode(const JSTokenLocation&, const Identifier&, unsigned startOffset, unsigned divotLine, unsigned divotLineStart); const Identifier& identifier() const { return m_ident; } @@ -378,7 +430,9 @@ namespace JSC { virtual bool isResolveNode() const { return true; } const Identifier& m_ident; - int32_t m_startOffset; + uint32_t m_startOffset; + uint32_t m_divotLine; + uint32_t m_divotLineStart; }; class ElementNode : public ParserArenaFreeable { @@ -402,7 +456,7 @@ namespace JSC { ArrayNode(const JSTokenLocation&, ElementNode*); ArrayNode(const JSTokenLocation&, int elision, ElementNode*); - ArgumentListNode* toArgumentList(JSGlobalData*, int, int) const; + ArgumentListNode* toArgumentList(VM*, int, int) const; private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -418,8 +472,8 @@ namespace JSC { public: enum Type { Constant = 1, Getter = 2, Setter = 4 }; - PropertyNode(JSGlobalData*, const Identifier&, ExpressionNode*, Type); - PropertyNode(JSGlobalData*, double, ExpressionNode*, Type); + PropertyNode(VM*, const Identifier&, ExpressionNode*, Type); + PropertyNode(VM*, double, ExpressionNode*, Type); const Identifier& name() const { return m_name; } Type type() const { return m_type; } @@ -431,7 +485,7 @@ namespace JSC { Type m_type; }; - class PropertyListNode : public Node { + class PropertyListNode : public ExpressionNode { public: PropertyListNode(const JSTokenLocation&, PropertyNode*); PropertyListNode(const JSTokenLocation&, PropertyNode*, PropertyListNode*); @@ -491,7 +545,7 @@ namespace JSC { const Identifier& m_ident; }; - class ArgumentListNode : public Node { + class ArgumentListNode : public ExpressionNode { public: ArgumentListNode(const JSTokenLocation&, ExpressionNode*); ArgumentListNode(const JSTokenLocation&, ArgumentListNode*, ExpressionNode*); @@ -525,7 +579,7 @@ namespace JSC { class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData { public: - EvalFunctionCallNode(const JSTokenLocation&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + EvalFunctionCallNode(const JSTokenLocation&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -535,7 +589,7 @@ namespace JSC { class FunctionCallValueNode : public ExpressionNode, public ThrowableExpressionData { public: - FunctionCallValueNode(const JSTokenLocation&, ExpressionNode*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + FunctionCallValueNode(const JSTokenLocation&, ExpressionNode*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -546,7 +600,7 @@ namespace JSC { class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - FunctionCallResolveNode(const JSTokenLocation&, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + FunctionCallResolveNode(const JSTokenLocation&, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -557,7 +611,7 @@ namespace JSC { class FunctionCallBracketNode : public ExpressionNode, public ThrowableSubExpressionData { public: - FunctionCallBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + FunctionCallBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -569,7 +623,7 @@ namespace JSC { class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData { public: - FunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + FunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -582,7 +636,7 @@ namespace JSC { class CallFunctionCallDotNode : public FunctionCallDotNode { public: - CallFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + CallFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -590,29 +644,15 @@ namespace JSC { class ApplyFunctionCallDotNode : public FunctionCallDotNode { public: - ApplyFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); - - private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - }; - - class PostfixNode : public ExpressionNode, public ThrowableExpressionData { - public: - PostfixNode(const JSTokenLocation&, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + ApplyFunctionCallDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - virtual RegisterID* emitResolve(BytecodeGenerator&, RegisterID* = 0); - virtual RegisterID* emitBracket(BytecodeGenerator&, RegisterID* = 0); - virtual RegisterID* emitDot(BytecodeGenerator&, RegisterID* = 0); - - ExpressionNode* m_expr; - Operator m_operator; }; class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteResolveNode(const JSTokenLocation&, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); + DeleteResolveNode(const JSTokenLocation&, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -622,7 +662,7 @@ namespace JSC { class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset); + DeleteBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -633,7 +673,7 @@ namespace JSC { class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData { public: - DeleteDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); + DeleteDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -686,9 +726,9 @@ namespace JSC { class PrefixNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { public: - PrefixNode(const JSTokenLocation&, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + PrefixNode(const JSTokenLocation&, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); - private: + protected: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); virtual RegisterID* emitResolve(BytecodeGenerator&, RegisterID* = 0); virtual RegisterID* emitBracket(BytecodeGenerator&, RegisterID* = 0); @@ -698,6 +738,17 @@ namespace JSC { Operator m_operator; }; + class PostfixNode : public PrefixNode { + public: + PostfixNode(const JSTokenLocation&, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitResolve(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitBracket(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitDot(BytecodeGenerator&, RegisterID* = 0); + }; + class UnaryOpNode : public ExpressionNode { public: UnaryOpNode(const JSTokenLocation&, ResultType, ExpressionNode*, OpcodeID); @@ -746,8 +797,7 @@ namespace JSC { public: LogicalNotNode(const JSTokenLocation&, ExpressionNode*); private: - void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue); - virtual bool hasConditionContextCodegen() const { return expr()->hasConditionContextCodegen(); } + void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode); }; class BinaryOpNode : public ExpressionNode { @@ -756,11 +806,13 @@ namespace JSC { BinaryOpNode(const JSTokenLocation&, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0); + void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode); ExpressionNode* lhs() { return m_expr1; }; ExpressionNode* rhs() { return m_expr2; }; private: + void tryFoldToBranch(BytecodeGenerator&, TriState& branchCondition, ExpressionNode*& branchExpression); virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); protected: @@ -909,8 +961,7 @@ namespace JSC { private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue); - virtual bool hasConditionContextCodegen() const { return true; } + void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode); ExpressionNode* m_expr1; ExpressionNode* m_expr2; @@ -932,7 +983,7 @@ namespace JSC { class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData { public: - ReadModifyResolveNode(const JSTokenLocation&, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + ReadModifyResolveNode(const JSTokenLocation&, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned line, unsigned lineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -956,7 +1007,7 @@ namespace JSC { class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData { public: - ReadModifyBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + ReadModifyBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -971,7 +1022,7 @@ namespace JSC { class AssignBracketNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + AssignBracketNode(const JSTokenLocation&, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -985,7 +1036,7 @@ namespace JSC { class AssignDotNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + AssignDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -998,7 +1049,7 @@ namespace JSC { class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData { public: - ReadModifyDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + ReadModifyDotNode(const JSTokenLocation&, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1012,7 +1063,7 @@ namespace JSC { class AssignErrorNode : public ExpressionNode, public ThrowableExpressionData { public: - AssignErrorNode(const JSTokenLocation&, unsigned divot, unsigned startOffset, unsigned endOffset); + AssignErrorNode(const JSTokenLocation&, unsigned divot, unsigned startOffset, unsigned endOffset, unsigned divotLine, unsigned divotLineStart); private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -1060,7 +1111,7 @@ namespace JSC { ConstStatementNode(const JSTokenLocation&, ConstDeclNode* next); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); ConstDeclNode* m_next; }; @@ -1088,7 +1139,7 @@ namespace JSC { StatementNode* lastStatement() const; private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); virtual bool isBlock() const { return true; } @@ -1100,7 +1151,7 @@ namespace JSC { EmptyStatementNode(const JSTokenLocation&); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); virtual bool isEmptyStatement() const { return true; } }; @@ -1110,7 +1161,7 @@ namespace JSC { DebuggerStatementNode(const JSTokenLocation&); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; class ExprStatementNode : public StatementNode { @@ -1122,7 +1173,7 @@ namespace JSC { private: virtual bool isExprStatement() const { return true; } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); ExpressionNode* m_expr; }; @@ -1131,29 +1182,22 @@ namespace JSC { public: VarStatementNode(const JSTokenLocation&, ExpressionNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); ExpressionNode* m_expr; }; - class IfNode : public StatementNode { - public: - IfNode(const JSTokenLocation&, ExpressionNode* condition, StatementNode* ifBlock); - - protected: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); - - ExpressionNode* m_condition; - StatementNode* m_ifBlock; - }; - - class IfElseNode : public IfNode { + class IfElseNode : public StatementNode { public: IfElseNode(const JSTokenLocation&, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + bool tryFoldBreakAndContinue(BytecodeGenerator&, StatementNode* ifBlock, + Label*& trueTarget, FallThroughMode&); + ExpressionNode* m_condition; + StatementNode* m_ifBlock; StatementNode* m_elseBlock; }; @@ -1162,7 +1206,7 @@ namespace JSC { DoWhileNode(const JSTokenLocation&, StatementNode*, ExpressionNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); StatementNode* m_statement; ExpressionNode* m_expr; @@ -1173,7 +1217,7 @@ namespace JSC { WhileNode(const JSTokenLocation&, ExpressionNode*, StatementNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); ExpressionNode* m_expr; StatementNode* m_statement; @@ -1184,7 +1228,7 @@ namespace JSC { ForNode(const JSTokenLocation&, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); ExpressionNode* m_expr1; ExpressionNode* m_expr2; @@ -1195,10 +1239,10 @@ namespace JSC { class ForInNode : public StatementNode, public ThrowableExpressionData { public: ForInNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*); - ForInNode(JSGlobalData*, const JSTokenLocation&, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset); + ForInNode(VM*, const JSTokenLocation&, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, unsigned divot, int startOffset, int endOffset, unsigned divotLine, unsigned divotLineStart); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); ExpressionNode* m_init; ExpressionNode* m_lexpr; @@ -1208,22 +1252,26 @@ namespace JSC { class ContinueNode : public StatementNode, public ThrowableExpressionData { public: - ContinueNode(JSGlobalData*, const JSTokenLocation&); + ContinueNode(VM*, const JSTokenLocation&); ContinueNode(const JSTokenLocation&, const Identifier&); + Label* trivialTarget(BytecodeGenerator&); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual bool isContinue() const { return true; } + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); const Identifier& m_ident; }; class BreakNode : public StatementNode, public ThrowableExpressionData { public: - BreakNode(JSGlobalData*, const JSTokenLocation&); + BreakNode(VM*, const JSTokenLocation&); BreakNode(const JSTokenLocation&, const Identifier&); + Label* trivialTarget(BytecodeGenerator&); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual bool isBreak() const { return true; } + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); const Identifier& m_ident; }; @@ -1235,7 +1283,7 @@ namespace JSC { ExpressionNode* value() { return m_value; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); virtual bool isReturnNode() const { return true; } @@ -1244,14 +1292,16 @@ namespace JSC { class WithNode : public StatementNode { public: - WithNode(const JSTokenLocation&, ExpressionNode*, StatementNode*, uint32_t divot, uint32_t expressionLength); + WithNode(const JSTokenLocation&, ExpressionNode*, StatementNode*, uint32_t divot, unsigned divotLine, unsigned divotLineStart, uint32_t expressionLength); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); ExpressionNode* m_expr; StatementNode* m_statement; uint32_t m_divot; + uint32_t m_divotLine; + uint32_t m_divotLineStart; uint32_t m_expressionLength; }; @@ -1260,7 +1310,7 @@ namespace JSC { LabelNode(const JSTokenLocation&, const Identifier& name, StatementNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); const Identifier& m_name; StatementNode* m_statement; @@ -1271,7 +1321,7 @@ namespace JSC { ThrowNode(const JSTokenLocation&, ExpressionNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); ExpressionNode* m_expr; }; @@ -1281,7 +1331,7 @@ namespace JSC { TryNode(const JSTokenLocation&, StatementNode* tryBlock, const Identifier& exceptionIdent, StatementNode* catchBlock, StatementNode* finallyBlock); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); StatementNode* m_tryBlock; const Identifier& m_exceptionIdent; @@ -1307,8 +1357,8 @@ namespace JSC { typedef DeclarationStacks::VarStack VarStack; typedef DeclarationStacks::FunctionStack FunctionStack; - ScopeNode(JSGlobalData*, const JSTokenLocation&, bool inStrictContext); - ScopeNode(JSGlobalData*, const JSTokenLocation&, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants); + ScopeNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, bool inStrictContext); + ScopeNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants); using ParserArenaRefCounted::operator new; @@ -1325,6 +1375,10 @@ namespace JSC { const String& sourceURL() const { return m_source.provider()->url(); } intptr_t sourceID() const { return m_source.providerID(); } + int startLine() const { return m_startLineNumber; } + int startStartOffset() const { return m_startStartOffset; } + int startLineStartOffset() const { return m_startLineStartOffset; } + void setFeatures(CodeFeatures features) { m_features = features; } CodeFeatures features() { return m_features; } @@ -1357,6 +1411,10 @@ namespace JSC { void setSource(const SourceCode& source) { m_source = source; } ParserArena m_arena; + int m_startLineNumber; + unsigned m_startStartOffset; + unsigned m_startLineStartOffset; + private: CodeFeatures m_features; SourceCode m_source; @@ -1370,49 +1428,64 @@ namespace JSC { class ProgramNode : public ScopeNode { public: static const bool isFunctionNode = false; - static PassRefPtr<ProgramNode> create(JSGlobalData*, const JSTokenLocation&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + static PassRefPtr<ProgramNode> create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + unsigned startColumn() { return m_startColumn; } static const bool scopeIsFunction = false; private: - ProgramNode(JSGlobalData*, const JSTokenLocation&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + ProgramNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + unsigned m_startColumn; }; class EvalNode : public ScopeNode { public: static const bool isFunctionNode = false; - static PassRefPtr<EvalNode> create(JSGlobalData*, const JSTokenLocation&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + static PassRefPtr<EvalNode> create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + unsigned startColumn() { return 1; } static const bool scopeIsFunction = false; private: - EvalNode(JSGlobalData*, const JSTokenLocation&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + EvalNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); }; - class FunctionParameters : public Vector<Identifier>, public RefCounted<FunctionParameters> { + class FunctionParameters : public RefCounted<FunctionParameters> { WTF_MAKE_FAST_ALLOCATED; public: - static PassRefPtr<FunctionParameters> create(ParameterNode* firstParameter) { return adoptRef(new FunctionParameters(firstParameter)); } + static PassRefPtr<FunctionParameters> create(ParameterNode*); + ~FunctionParameters(); + + unsigned size() const { return m_size; } + const Identifier& at(unsigned index) const { ASSERT(index < m_size); return identifiers()[index]; } private: - FunctionParameters(ParameterNode*); + FunctionParameters(ParameterNode*, unsigned size); + + Identifier* identifiers() { return reinterpret_cast<Identifier*>(&m_storage); } + const Identifier* identifiers() const { return reinterpret_cast<const Identifier*>(&m_storage); } + + unsigned m_size; + void* m_storage; }; - enum FunctionNameIsInScopeToggle { FunctionNameIsNotInScope, FunctionNameIsInScope }; class FunctionBodyNode : public ScopeNode { public: static const bool isFunctionNode = true; - static FunctionBodyNode* create(JSGlobalData*, const JSTokenLocation&, bool isStrictMode); - static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, const JSTokenLocation&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + static FunctionBodyNode* create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, bool isStrictMode); + static PassRefPtr<FunctionBodyNode> create(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); FunctionParameters* parameters() const { return m_parameters.get(); } size_t parameterCount() const { return m_parameters->size(); } - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); void finishParsing(const SourceCode&, ParameterNode*, const Identifier&, FunctionNameIsInScopeToggle); void finishParsing(PassRefPtr<FunctionParameters>, const Identifier&, FunctionNameIsInScopeToggle); @@ -1424,16 +1497,22 @@ namespace JSC { bool functionNameIsInScope() { return m_functionNameIsInScopeToggle == FunctionNameIsInScope; } FunctionNameIsInScopeToggle functionNameIsInScopeToggle() { return m_functionNameIsInScopeToggle; } + void setFunctionStart(int functionStart) { m_functionStart = functionStart; } + int functionStart() const { return m_functionStart; } + unsigned startColumn() const { return m_startColumn; } + static const bool scopeIsFunction = true; private: - FunctionBodyNode(JSGlobalData*, const JSTokenLocation&, bool inStrictContext); - FunctionBodyNode(JSGlobalData*, const JSTokenLocation&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + FunctionBodyNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, bool inStrictContext); + FunctionBodyNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); Identifier m_ident; Identifier m_inferredName; FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle; RefPtr<FunctionParameters> m_parameters; + int m_functionStart; + unsigned m_startColumn; }; class FuncExprNode : public ExpressionNode { @@ -1457,7 +1536,7 @@ namespace JSC { FunctionBodyNode* body() { return m_body; } private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); FunctionBodyNode* m_body; }; @@ -1492,10 +1571,11 @@ namespace JSC { public: CaseBlockNode(ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2); - RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* destination); + void emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* destination); private: - SwitchInfo::SwitchType tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num); + SwitchInfo::SwitchType tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num); + static const size_t s_tableSwitchMinimum = 10; ClauseListNode* m_list1; CaseClauseNode* m_defaultClause; ClauseListNode* m_list2; @@ -1506,7 +1586,7 @@ namespace JSC { SwitchNode(const JSTokenLocation&, ExpressionNode*, CaseBlockNode*); private: - virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0); ExpressionNode* m_expr; CaseBlockNode* m_block; diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp index cf3cb4e4f..aefba302f 100644 --- a/Source/JavaScriptCore/parser/Parser.cpp +++ b/Source/JavaScriptCore/parser/Parser.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -26,20 +26,21 @@ #include "ASTBuilder.h" #include "CodeBlock.h" #include "Debugger.h" -#include "JSGlobalData.h" +#include "JSCJSValueInlines.h" #include "Lexer.h" #include "NodeInfo.h" #include "SourceProvider.h" +#include "VM.h" #include <utility> #include <wtf/HashFunctions.h> #include <wtf/OwnPtr.h> #include <wtf/WTFThreadData.h> -#define fail() do { if (!m_error) updateErrorMessage(); return 0; } while (0) -#define failWithToken(tok) do { if (!m_error) updateErrorMessage(tok); return 0; } while (0) -#define failWithMessage(msg) do { if (!m_error) updateErrorMessage(msg); return 0; } while (0) -#define failWithNameAndMessage(before, name, after) do { if (!m_error) updateErrorWithNameAndMessage(before, name, after); return 0; } while (0) -#define failWithStackOverflow() do { m_error = true; m_hasStackOverflow = true; return 0; } while (0) +#define fail() do { if (!hasError()) updateErrorMessage(); return 0; } while (0) +#define failWithToken(tok) do { if (!hasError()) updateErrorMessage(tok); return 0; } while (0) +#define failWithMessage(msg) do { if (!hasError()) updateErrorMessage(msg); return 0; } while (0) +#define failWithNameAndMessage(before, name, after) do { if (!hasError()) updateErrorWithNameAndMessage(before, name, after); return 0; } while (0) +#define failWithStackOverflow() do { updateErrorMessage("Stack exhausted"); m_hasStackOverflow = true; return 0; } while (0) #define failIfFalse(cond) do { if (!(cond)) fail(); } while (0) #define failIfFalseWithMessage(cond, msg) do { if (!(cond)) failWithMessage(msg); } while (0) #define failIfFalseWithNameAndMessage(cond, before, name, msg) do { if (!(cond)) failWithNameAndMessage(before, name, msg); } while (0) @@ -62,13 +63,11 @@ using namespace std; namespace JSC { template <typename LexerType> -Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode) - : m_globalData(globalData) +Parser<LexerType>::Parser(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode) + : m_vm(vm) , m_source(&source) - , m_stack(wtfThreadData().stack()) + , m_stack(*vm, wtfThreadData().stack()) , m_hasStackOverflow(false) - , m_error(false) - , m_errorMessage("Parse error") , m_allowsIn(true) , m_lastLine(0) , m_lastTokenEnd(0) @@ -80,11 +79,13 @@ Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, Fu , m_lastIdentifier(0) , m_sourceElements(0) { - m_lexer = adoptPtr(new LexerType(globalData)); - m_arena = m_globalData->parserArena.get(); + m_lexer = adoptPtr(new LexerType(vm)); + m_arena = m_vm->parserArena.get(); m_lexer->setCode(source, m_arena); + m_token.m_location.endOffset = source.startOffset(); + m_token.m_location.lineStartOffset = source.startOffset(); - m_functionCache = source.provider()->cache(); + m_functionCache = vm->addSourceProviderCache(source.provider()); ScopeRef scope = pushScope(); if (parserMode == JSParseFunctionCode) scope->setIsFunction(); @@ -97,7 +98,6 @@ Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, Fu if (!name.isNull()) scope->declareCallee(&name); next(); - m_lexer->setLastLineNumber(tokenLine()); } template <typename LexerType> @@ -110,14 +110,17 @@ String Parser<LexerType>::parseInner() { String parseError = String(); - unsigned oldFunctionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0; - ASTBuilder context(const_cast<JSGlobalData*>(m_globalData), const_cast<SourceCode*>(m_source)); + ASTBuilder context(const_cast<VM*>(m_vm), const_cast<SourceCode*>(m_source)); if (m_lexer->isReparsing()) m_statementDepth--; ScopeRef scope = currentScope(); SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context); - if (!sourceElements || !consume(EOFTOK)) - parseError = m_errorMessage; + if (!sourceElements || !consume(EOFTOK)) { + if (hasError()) + parseError = m_errorMessage; + else + parseError = ASCIILiteral("Parser error"); + } IdentifierSet capturedVariables; scope->getCapturedVariables(capturedVariables); @@ -126,9 +129,6 @@ String Parser<LexerType>::parseInner() 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(), features, m_lastLine, context.numConstants(), capturedVariables); @@ -164,6 +164,7 @@ template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements Parser< const Identifier* directive = 0; unsigned directiveLiteralLength = 0; unsigned startOffset = m_token.m_location.startOffset; + unsigned startLineStartOffset = m_token.m_location.lineStartOffset; unsigned oldLastLineNumber = m_lexer->lastLineNumber(); unsigned oldLineNumber = m_lexer->lineNumber(); bool hasSetStrict = false; @@ -171,15 +172,15 @@ template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements Parser< if (mode == CheckForStrictMode && !seenNonDirective) { if (directive) { // "use strict" must be the exact literal without escape sequences or line continuation. - if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_globalData->propertyNames->useStrictIdentifier == *directive) { + if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_vm->propertyNames->useStrictIdentifier == *directive) { setStrictMode(); hasSetStrict = true; failIfFalse(isValidStrictMode()); - m_lexer->setOffset(startOffset); + m_lexer->setOffset(startOffset, startLineStartOffset); next(); m_lexer->setLastLineNumber(oldLastLineNumber); m_lexer->setLineNumber(oldLineNumber); - failIfTrue(m_error); + failIfTrue(hasError()); continue; } } else @@ -187,9 +188,8 @@ template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements Parser< } context.appendStatement(sourceElements, statement); } - - if (m_error) - fail(); + + failIfTrue(hasError()); return sourceElements; } @@ -205,7 +205,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseVarDeclaratio TreeExpression scratch2 = 0; int scratch3 = 0; TreeExpression varDecls = parseVarDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3); - failIfTrue(m_error); + failIfTrue(hasError()); failIfFalse(autoSemiColon()); return context.createVarStatement(location, varDecls, start, end); @@ -219,7 +219,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseConstDeclarat int start = tokenLine(); int end = 0; TreeConstDeclList constDecls = parseConstDeclarationList(context); - failIfTrue(m_error); + failIfTrue(hasError()); failIfFalse(autoSemiColon()); return context.createConstStatement(location, constDecls, start, end); @@ -288,6 +288,8 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarati context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0); if (hasInitializer) { int varDivot = tokenStart() + 1; + unsigned varLine = tokenLine(); + unsigned varLineStart = tokenLineStart(); initStart = tokenStart(); next(TreeBuilder::DontBuildStrings); // consume '=' TreeExpression initializer = parseAssignmentExpression(context); @@ -295,7 +297,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarati lastInitializer = initializer; failIfFalse(initializer); - TreeExpression node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEnd()); + TreeExpression node = context.createAssignResolve(location, *name, initializer, varStart, varDivot, lastTokenEnd(), varLine, varLineStart); if (!varDecls) varDecls = node; else @@ -320,6 +322,7 @@ template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDecl bool hasInitializer = match(EQUAL); declareVariable(name); context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0)); + TreeExpression initializer = 0; if (hasInitializer) { next(TreeBuilder::DontBuildStrings); // consume '=' @@ -344,6 +347,8 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement( int declarations = 0; int declsStart = 0; int declsEnd = 0; + unsigned declsLine = 0; + unsigned declsLineStart = 0; TreeExpression decls = 0; if (match(VAR)) { /* @@ -358,9 +363,8 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement( int initEnd = 0; decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd); m_allowsIn = true; - if (m_error) - fail(); - + failIfTrue(hasError()); + // Remainder of a standard for loop is handled identically if (match(SEMICOLON)) goto standardForLoop; @@ -369,6 +373,8 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement( // Handle for-in with var declaration int inLocation = tokenStart(); + unsigned inLine = tokenLine(); + unsigned inLineStart = tokenLineStart(); consumeOrFail(INTOKEN); TreeExpression expr = parseExpression(context); @@ -384,7 +390,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement( endLoop(); failIfFalse(statement); - return context.createForInLoop(location, forInTarget, forInInitializer, expr, statement, declsStart, inLocation, exprEnd, initStart, initEnd, startLine, endLine); + return context.createForInLoop(location, forInTarget, forInInitializer, expr, statement, declsStart, inLocation, exprEnd, initStart, initEnd, startLine, endLine, inLine, inLineStart); } if (!match(SEMICOLON)) { @@ -392,6 +398,8 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement( declsStart = tokenStart(); decls = parseExpression(context); declsEnd = lastTokenEnd(); + declsLine = lastTokenLine(); + declsLineStart = lastTokenLineStart(); m_allowsIn = true; failIfFalse(decls); } @@ -437,7 +445,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseForStatement( endLoop(); failIfFalse(statement); - return context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine); + return context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine, declsLine, declsLineStart); } template <typename LexerType> @@ -449,20 +457,22 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseBreakStatemen int endCol = tokenEnd(); int startLine = tokenLine(); int endLine = tokenLine(); + unsigned endLineStart = tokenLineStart(); next(); if (autoSemiColon()) { failIfFalseWithMessage(breakIsValid(), "'break' is only valid inside a switch or loop statement"); - return context.createBreakStatement(location, startCol, endCol, startLine, endLine); + return context.createBreakStatement(location, startCol, endCol, startLine, endLine, endLineStart); } matchOrFail(IDENT); const Identifier* ident = m_token.m_data.ident; failIfFalseWithNameAndMessage(getLabel(ident), "Label", ident->impl(), "is not defined"); endCol = tokenEnd(); endLine = tokenLine(); + endLineStart = tokenLineStart(); next(); failIfFalse(autoSemiColon()); - return context.createBreakStatement(location, ident, startCol, endCol, startLine, endLine); + return context.createBreakStatement(location, ident, startCol, endCol, startLine, endLine, endLineStart); } template <typename LexerType> @@ -474,11 +484,12 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueState int endCol = tokenEnd(); int startLine = tokenLine(); int endLine = tokenLine(); + unsigned endLineStart = tokenLineStart(); next(); if (autoSemiColon()) { failIfFalseWithMessage(continueIsValid(), "'continue' is only valid inside a loop statement"); - return context.createContinueStatement(location, startCol, endCol, startLine, endLine); + return context.createContinueStatement(location, startCol, endCol, startLine, endLine, endLineStart); } matchOrFail(IDENT); const Identifier* ident = m_token.m_data.ident; @@ -487,9 +498,10 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseContinueState failIfFalseWithMessage(label->m_isLoop, "'continue' is only valid inside a loop statement"); endCol = tokenEnd(); endLine = tokenLine(); + endLineStart = tokenLineStart(); next(); failIfFalse(autoSemiColon()); - return context.createContinueStatement(location, ident, startCol, endCol, startLine, endLine); + return context.createContinueStatement(location, ident, startCol, endCol, startLine, endLine, endLineStart); } template <typename LexerType> @@ -502,6 +514,8 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStateme int endLine = startLine; int start = tokenStart(); int end = tokenEnd(); + unsigned divotLine = tokenLine(); + unsigned divotLineStart = tokenLineStart(); next(); // We do the auto semicolon check before attempting to parse an expression // as we need to ensure the a line break after the return correctly terminates @@ -509,14 +523,16 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseReturnStateme if (match(SEMICOLON)) endLine = tokenLine(); if (autoSemiColon()) - return context.createReturnStatement(location, 0, start, end, startLine, endLine); + return context.createReturnStatement(location, 0, start, end, startLine, endLine, divotLine, divotLineStart); TreeExpression expr = parseExpression(context); failIfFalse(expr); end = lastTokenEnd(); + divotLine = lastTokenLine(); + divotLineStart = lastTokenLineStart(); if (match(SEMICOLON)) endLine = tokenLine(); failIfFalse(autoSemiColon()); - return context.createReturnStatement(location, expr, start, end, startLine, endLine); + return context.createReturnStatement(location, expr, start, end, startLine, endLine, divotLine, divotLineStart); } template <typename LexerType> @@ -533,10 +549,12 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseThrowStatemen TreeExpression expr = parseExpression(context); failIfFalse(expr); int eEnd = lastTokenEnd(); + unsigned divotLine = lastTokenLine(); + unsigned divotLineStart = lastTokenLineStart(); int endLine = tokenLine(); failIfFalse(autoSemiColon()); - return context.createThrowStatement(location, expr, eStart, eEnd, startLine, endLine); + return context.createThrowStatement(location, expr, eStart, eEnd, startLine, endLine, divotLine, divotLineStart); } template <typename LexerType> @@ -553,14 +571,15 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement TreeExpression expr = parseExpression(context); failIfFalse(expr); int end = lastTokenEnd(); - + unsigned divotLine = lastTokenLine(); + unsigned divotLineStart = lastTokenLineStart(); int endLine = tokenLine(); consumeOrFail(CLOSEPAREN); const Identifier* unused = 0; TreeStatement statement = parseStatement(context, unused); failIfFalse(statement); - return context.createWithStatement(location, expr, statement, start, end, startLine, endLine); + return context.createWithStatement(location, expr, statement, start, end, startLine, endLine, divotLine, divotLineStart); } template <typename LexerType> @@ -578,13 +597,13 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseSwitchStateme consumeOrFail(OPENBRACE); startSwitch(); TreeClauseList firstClauses = parseSwitchClauses(context); - failIfTrue(m_error); + failIfTrue(hasError()); TreeClause defaultClause = parseSwitchDefaultClause(context); - failIfTrue(m_error); + failIfTrue(hasError()); TreeClauseList secondClauses = parseSwitchClauses(context); - failIfTrue(m_error); + failIfTrue(hasError()); endSwitch(); consumeOrFail(CLOSEBRACE); @@ -638,7 +657,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement( ASSERT(match(TRY)); JSTokenLocation location(tokenLocation()); TreeStatement tryBlock = 0; - const Identifier* ident = &m_globalData->propertyNames->nullIdentifier; + const Identifier* ident = &m_vm->propertyNames->nullIdentifier; TreeStatement catchBlock = 0; TreeStatement finallyBlock = 0; int firstLine = tokenLine(); @@ -798,17 +817,21 @@ template <class TreeBuilder> TreeFormalParameterList Parser<LexerType>::parseFor template <typename LexerType> template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(TreeBuilder& context) { + JSTokenLocation startLocation(tokenLocation()); + unsigned startColumn = tokenColumn(); + next(); + if (match(CLOSEBRACE)) - return context.createFunctionBody(tokenLocation(), strictMode()); + return context.createFunctionBody(startLocation, tokenLocation(), startColumn, strictMode()); DepthManager statementDepth(&m_statementDepth); m_statementDepth = 0; - typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<JSGlobalData*>(m_globalData), m_lexer.get()); + typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<VM*>(m_vm), m_lexer.get()); failIfFalse(parseSourceElements<CheckForStrictMode>(bodyBuilder)); - return context.createFunctionBody(tokenLocation(), strictMode()); + return context.createFunctionBody(startLocation, tokenLocation(), startColumn, strictMode()); } 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) +template <FunctionRequirements requirements, bool nameIsInContainingScope, class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, unsigned& openBraceOffset, unsigned& closeBraceOffset, int& bodyStartLine, unsigned& bodyStartColumn) { AutoPopScopeRef functionScope(this, pushScope()); functionScope->setIsFunction(); @@ -828,55 +851,71 @@ template <FunctionRequirements requirements, bool nameIsInContainingScope, class consumeOrFail(CLOSEPAREN); matchOrFail(OPENBRACE); - openBracePos = m_token.m_data.intValue; + openBraceOffset = m_token.m_data.offset; bodyStartLine = tokenLine(); - JSTokenLocation location(tokenLocation()); + bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset; + JSTokenLocation startLocation(tokenLocation()); // 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 (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBraceOffset) : 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(location, cachedInfo->strictMode); + JSTokenLocation endLocation; + + endLocation.line = cachedInfo->closeBraceLine; + endLocation.startOffset = cachedInfo->closeBraceOffset; + endLocation.lineStartOffset = cachedInfo->closeBraceLineStartOffset; + ASSERT(endLocation.startOffset >= endLocation.lineStartOffset); + + body = context.createFunctionBody(startLocation, endLocation, bodyStartColumn, cachedInfo->strictMode); - functionScope->restoreFunctionInfo(cachedInfo); + functionScope->restoreFromSourceProviderCache(cachedInfo); failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo)); - closeBracePos = cachedInfo->closeBracePos; + closeBraceOffset = cachedInfo->closeBraceOffset; + + context.setFunctionStart(body, functionStart); m_token = cachedInfo->closeBraceToken(); - m_lexer->setOffset(m_token.m_location.endOffset); + + m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset); m_lexer->setLineNumber(m_token.m_location.line); next(); return true; } - next(); - body = parseFunctionBody(context); failIfFalse(body); if (functionScope->strictMode() && name) { - failIfTrueWithNameAndMessage(m_globalData->propertyNames->arguments == *name, "Function name", name->impl(), "is not valid in strict mode"); - failIfTrueWithNameAndMessage(m_globalData->propertyNames->eval == *name, "Function name", name->impl(), "is not valid in strict mode"); + failIfTrueWithNameAndMessage(m_vm->propertyNames->arguments == *name, "Function name", name->impl(), "is not valid in strict mode"); + failIfTrueWithNameAndMessage(m_vm->propertyNames->eval == *name, "Function name", name->impl(), "is not valid in strict mode"); } - closeBracePos = m_token.m_data.intValue; + closeBraceOffset = m_token.m_data.offset; + unsigned closeBraceLine = m_token.m_data.line; + unsigned closeBraceLineStartOffset = m_token.m_data.lineStartOffset; // Cache the tokenizer state and the function scope the first time the function is parsed. // Any future reparsing can then skip the function. - static const int minimumFunctionLengthToCache = 64; + static const int minimumFunctionLengthToCache = 16; OwnPtr<SourceProviderCacheItem> newInfo; - int functionLength = closeBracePos - openBracePos; + int functionLength = closeBraceOffset - openBraceOffset; if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) { - newInfo = adoptPtr(new SourceProviderCacheItem(functionStart, m_token.m_location.line, closeBracePos)); - functionScope->saveFunctionInfo(newInfo.get()); + SourceProviderCacheItemCreationParameters parameters; + parameters.functionStart = functionStart; + parameters.closeBraceLine = closeBraceLine; + parameters.closeBraceOffset = closeBraceOffset; + parameters.closeBraceLineStartOffset = closeBraceLineStartOffset; + functionScope->fillParametersForSourceProviderCache(parameters); + newInfo = SourceProviderCacheItem::create(parameters); + } + context.setFunctionStart(body, functionStart); failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo)); matchOrFail(CLOSEBRACE); - if (newInfo) { - unsigned approximateByteSize = newInfo->approximateByteSize(); - m_functionCache->add(openBracePos, newInfo.release(), approximateByteSize); - } + if (newInfo) + m_functionCache->add(openBraceOffset, newInfo.release()); next(); return true; @@ -891,26 +930,31 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDecla const Identifier* name = 0; TreeFormalParameterList parameters = 0; TreeFunctionBody body = 0; - int openBracePos = 0; - int closeBracePos = 0; + unsigned openBraceOffset = 0; + unsigned closeBraceOffset = 0; int bodyStartLine = 0; - failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine))); + unsigned bodyStartColumn = 0; + failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn))); failIfFalse(name); failIfFalseIfStrict(declareVariable(name)); - return context.createFuncDeclStatement(location, name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine); + return context.createFuncDeclStatement(location, name, body, parameters, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastLine, bodyStartColumn); } struct LabelInfo { - LabelInfo(const Identifier* ident, int start, int end) + LabelInfo(const Identifier* ident, unsigned start, unsigned end, unsigned divotLine, unsigned divotLineStart) : m_ident(ident) , m_start(start) , m_end(end) + , m_divotLine(divotLine) + , m_divotLineStart(divotLineStart) { } const Identifier* m_ident; - int m_start; - int m_end; + unsigned m_start; + unsigned m_end; + unsigned m_divotLine; + unsigned m_divotLineStart; }; template <typename LexerType> @@ -924,7 +968,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrL JSTokenLocation location; do { int start = tokenStart(); - int startLine = tokenLine(); + int startingLine = tokenLine(); location = tokenLocation(); if (!nextTokenIsColon()) { // If we hit this path we're making a expression statement, which @@ -933,10 +977,12 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrL TreeExpression expression = parseExpression(context); failIfFalse(expression); failIfFalse(autoSemiColon()); - return context.createExprStatement(location, expression, startLine, m_lastLine); + return context.createExprStatement(location, expression, startingLine, m_lastLine); } const Identifier* ident = m_token.m_data.ident; int end = tokenEnd(); + unsigned divotLine = tokenLine(); + unsigned divotLineStart = tokenLineStart(); next(); consumeOrFail(COLON); if (!m_syntaxAlreadyValidated) { @@ -945,7 +991,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrL for (size_t i = 0; i < labels.size(); i++) failIfTrue(ident->impl() == labels[i].m_ident->impl()); failIfTrue(getLabel(ident)); - labels.append(LabelInfo(ident, start, end)); + labels.append(LabelInfo(ident, start, end, divotLine, divotLineStart)); } } while (match(IDENT)); bool isLoop = false; @@ -972,7 +1018,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseExpressionOrL failIfFalse(statement); for (size_t i = 0; i < labels.size(); i++) { const LabelInfo& info = labels[labels.size() - i - 1]; - statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end); + statement = context.createLabelStatement(location, info.m_ident, statement, info.m_start, info.m_end, info.m_divotLine, info.m_divotLineStart); } return statement; } @@ -1008,7 +1054,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(T failIfFalse(trueBlock); if (!match(ELSE)) - return context.createIfStatement(ifLocation, condition, trueBlock, start, end); + return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end); Vector<TreeExpression> exprStack; Vector<pair<int, int> > posStack; @@ -1053,7 +1099,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseIfStatement(T posStack.removeLast(); JSTokenLocation elseLocation = tokenLocationStack.last(); tokenLocationStack.removeLast(); - statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, pos.first, pos.second)); + statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second)); } while (!exprStack.isEmpty()) { @@ -1102,6 +1148,8 @@ template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmen { failIfStackOverflow(); int start = tokenStart(); + unsigned line = tokenLine(); + unsigned lineStart = tokenLineStart(); JSTokenLocation location(tokenLocation()); int initialAssignmentCount = m_assignmentCount; int initialNonLHSCount = m_nonLHSCount; @@ -1132,13 +1180,15 @@ template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmen } m_nonTrivialExpressionCount++; hadAssignment = true; - context.assignmentStackAppend(assignmentStack, lhs, start, tokenStart(), m_assignmentCount, op); + context.assignmentStackAppend(assignmentStack, lhs, start, tokenStart(), line, lineStart, m_assignmentCount, op); start = tokenStart(); + line = tokenLine(); + lineStart = tokenLineStart(); m_assignmentCount++; next(TreeBuilder::DontBuildStrings); if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) { - failIfTrueIfStrictWithMessage(m_globalData->propertyNames->eval == *m_lastIdentifier, "'eval' cannot be modified in strict mode"); - failIfTrueIfStrictWithMessage(m_globalData->propertyNames->arguments == *m_lastIdentifier, "'arguments' cannot be modified in strict mode"); + failIfTrueIfStrictWithMessage(m_vm->propertyNames->eval == *m_lastIdentifier, "'eval' cannot be modified in strict mode"); + failIfTrueIfStrictWithMessage(m_vm->propertyNames->arguments == *m_lastIdentifier, "'arguments' cannot be modified in strict mode"); declareWrite(m_lastIdentifier); m_lastIdentifier = 0; } @@ -1206,7 +1256,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseBinaryExpres TreeExpression current = parseUnaryExpression(context); failIfFalse(current); - context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEnd(), lastTokenEnd(), initialAssignments != m_assignmentCount); + context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEnd(), lastTokenEnd(), lastTokenLine(), lastTokenLineStart(), initialAssignments != m_assignmentCount); int precedence = isBinaryOperator(m_token.m_type); if (!precedence) break; @@ -1248,7 +1298,7 @@ template <bool complete, class TreeBuilder> TreeProperty Parser<LexerType>::pars wasIdent = true; case STRING: { const Identifier* ident = m_token.m_data.ident; - if (complete || (wasIdent && (*ident == m_globalData->propertyNames->get || *ident == m_globalData->propertyNames->set))) + if (complete || (wasIdent && (*ident == m_vm->propertyNames->get || *ident == m_vm->propertyNames->set))) nextExpectIdentifier(LexerFlagsIgnoreReservedWords); else nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords); @@ -1263,13 +1313,14 @@ template <bool complete, class TreeBuilder> TreeProperty Parser<LexerType>::pars const Identifier* accessorName = 0; TreeFormalParameterList parameters = 0; TreeFunctionBody body = 0; - int openBracePos = 0; - int closeBracePos = 0; + unsigned openBraceOffset = 0; + unsigned closeBraceOffset = 0; int bodyStartLine = 0; + unsigned bodyStartColumn = 0; PropertyNode::Type type; - if (*ident == m_globalData->propertyNames->get) + if (*ident == m_vm->propertyNames->get) type = PropertyNode::Getter; - else if (*ident == m_globalData->propertyNames->set) + else if (*ident == m_vm->propertyNames->set) type = PropertyNode::Setter; else fail(); @@ -1283,10 +1334,10 @@ template <bool complete, class TreeBuilder> TreeProperty Parser<LexerType>::pars fail(); JSTokenLocation location(tokenLocation()); next(); - failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine))); + failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, accessorName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn))); if (stringPropertyName) - return context.template createGetterOrSetterProperty<complete>(location, type, stringPropertyName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine); - return context.template createGetterOrSetterProperty<complete>(const_cast<JSGlobalData*>(m_globalData), location, type, numericPropertyName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine); + return context.template createGetterOrSetterProperty<complete>(location, type, stringPropertyName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastLine, bodyStartColumn); + return context.template createGetterOrSetterProperty<complete>(const_cast<VM*>(m_vm), location, type, numericPropertyName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastLine, bodyStartColumn); } case NUMBER: { double propertyName = m_token.m_data.doubleValue; @@ -1294,7 +1345,7 @@ template <bool complete, class TreeBuilder> TreeProperty Parser<LexerType>::pars consumeOrFail(COLON); TreeExpression node = parseAssignmentExpression(context); failIfFalse(node); - return context.template createProperty<complete>(const_cast<JSGlobalData*>(m_globalData), propertyName, node, PropertyNode::Constant); + return context.template createProperty<complete>(const_cast<VM*>(m_vm), propertyName, node, PropertyNode::Constant); } default: failIfFalse(m_token.m_type & KeywordTokenFlag); @@ -1305,7 +1356,8 @@ template <bool complete, class TreeBuilder> TreeProperty Parser<LexerType>::pars template <typename LexerType> template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLiteral(TreeBuilder& context) { - int startOffset = m_token.m_data.intValue; + int startOffset = m_token.m_data.offset; + unsigned oldLineStartOffset = m_lexer->currentLineStartOffset(); unsigned oldLastLineNumber = m_lexer->lastLineNumber(); unsigned oldLineNumber = m_lexer->lineNumber(); consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings); @@ -1321,7 +1373,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLitera TreeProperty property = parseProperty<false>(context); failIfFalse(property); if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) { - m_lexer->setOffset(startOffset); + m_lexer->setOffset(startOffset, oldLineStartOffset); next(); m_lexer->setLastLineNumber(oldLastLineNumber); m_lexer->setLineNumber(oldLineNumber); @@ -1338,7 +1390,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLitera property = parseProperty<false>(context); failIfFalse(property); if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) { - m_lexer->setOffset(startOffset); + m_lexer->setOffset(startOffset, oldLineStartOffset); next(); m_lexer->setLastLineNumber(oldLastLineNumber); m_lexer->setLineNumber(oldLineNumber); @@ -1484,12 +1536,14 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpre } case IDENT: { int start = tokenStart(); + int line = tokenLine(); + int lineStart = tokenLineStart(); const Identifier* ident = m_token.m_data.ident; JSTokenLocation location(tokenLocation()); next(); - currentScope()->useVariable(ident, m_globalData->propertyNames->eval == *ident); + currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident); m_lastIdentifier = ident; - return context.createResolve(location, ident, start); + return context.createResolve(location, ident, start, line, lineStart); } case STRING: { const Identifier* ident = m_token.m_data.ident; @@ -1529,12 +1583,13 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpre failIfFalse(m_lexer->scanRegExp(pattern, flags)); int start = tokenStart(); + int line = tokenLine(); + int lineStart = tokenLineStart(); JSTokenLocation location(tokenLocation()); next(); - TreeExpression re = context.createRegExp(location, *pattern, *flags, start); + TreeExpression re = context.createRegExp(location, *pattern, *flags, start, line, lineStart); if (!re) { const char* yarrErrorMsg = Yarr::checkSyntax(pattern->string()); - ASSERT(!m_errorMessage.isNull()); failWithMessage(yarrErrorMsg); } return re; @@ -1575,6 +1630,8 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres TreeExpression base = 0; int start = tokenStart(); int expressionStart = start; + int expressionLine = tokenLine(); + int expressionLineStart = tokenLineStart(); int newCount = 0; JSTokenLocation location; while (match(NEW)) { @@ -1583,16 +1640,17 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres } if (match(FUNCTION)) { - const Identifier* name = &m_globalData->propertyNames->nullIdentifier; + const Identifier* name = &m_vm->propertyNames->nullIdentifier; TreeFormalParameterList parameters = 0; TreeFunctionBody body = 0; - int openBracePos = 0; - int closeBracePos = 0; + unsigned openBraceOffset = 0; + unsigned closeBraceOffset = 0; int bodyStartLine = 0; + unsigned bodyStartColumn = 0; location = tokenLocation(); next(); - failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine))); - base = context.createFunctionExpr(location, name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine); + failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, name, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn))); + base = context.createFunctionExpr(location, name, body, parameters, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastLine, bodyStartColumn); } else base = parsePrimaryExpression(context); @@ -1603,12 +1661,14 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres case OPENBRACKET: { m_nonTrivialExpressionCount++; int expressionEnd = lastTokenEnd(); + int expressionLine = lastTokenLine(); + int expressionLineStart = lastTokenLineStart(); next(); int nonLHSCount = m_nonLHSCount; int initialAssignments = m_assignmentCount; TreeExpression property = parseExpression(context); failIfFalse(property); - base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEnd()); + base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEnd(), expressionLine, expressionLineStart); consumeOrFail(CLOSEBRACKET); m_nonLHSCount = nonLHSCount; break; @@ -1619,14 +1679,18 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres if (newCount) { newCount--; int exprEnd = lastTokenEnd(); + unsigned expressionLine = lastTokenLine(); + unsigned expressionLineStart = lastTokenLineStart(); TreeArguments arguments = parseArguments(context); failIfFalse(arguments); - base = context.createNewExpr(location, base, arguments, start, exprEnd, lastTokenEnd()); + base = context.createNewExpr(location, base, arguments, start, exprEnd, lastTokenEnd(), expressionLine, expressionLineStart); } else { int expressionEnd = lastTokenEnd(); + unsigned expressionLine = lastTokenLine(); + int expressionLineStart = lastTokenLineStart(); TreeArguments arguments = parseArguments(context); failIfFalse(arguments); - base = context.makeFunctionCallNode(location, base, arguments, expressionStart, expressionEnd, lastTokenEnd()); + base = context.makeFunctionCallNode(location, base, arguments, expressionStart, expressionEnd, lastTokenEnd(), expressionLine, expressionLineStart); } m_nonLHSCount = nonLHSCount; break; @@ -1634,9 +1698,10 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres case DOT: { m_nonTrivialExpressionCount++; int expressionEnd = lastTokenEnd(); + expressionLineStart = lastTokenLineStart(); nextExpectIdentifier(LexerFlagsIgnoreReservedWords | TreeBuilder::DontBuildKeywords); matchOrFail(IDENT); - base = context.createDotAccess(location, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEnd()); + base = context.createDotAccess(location, base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEnd(), expressionLine, expressionLineStart); next(); break; } @@ -1646,7 +1711,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres } endMemberExpression: while (newCount--) - base = context.createNewExpr(location, base, start, lastTokenEnd()); + base = context.createNewExpr(location, base, start, lastTokenEnd(), expressionLine, expressionLineStart); return base; } @@ -1679,25 +1744,28 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpress } } m_nonLHSCount++; - context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStart()); + context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStart(), tokenLine(), tokenLineStart()); next(); m_nonTrivialExpressionCount++; } int subExprStart = tokenStart(); + int subExprLine = tokenLine(); + int subExprLineStartPosition = tokenLineStart(); + ASSERT(subExprStart >= subExprLineStartPosition); JSTokenLocation location(tokenLocation()); TreeExpression expr = parseMemberExpression(context); failIfFalse(expr); bool isEvalOrArguments = false; if (strictMode() && !m_syntaxAlreadyValidated) { if (context.isResolve(expr)) - isEvalOrArguments = *m_lastIdentifier == m_globalData->propertyNames->eval || *m_lastIdentifier == m_globalData->propertyNames->arguments; + isEvalOrArguments = *m_lastIdentifier == m_vm->propertyNames->eval || *m_lastIdentifier == m_vm->propertyNames->arguments; } failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments && modifiesExpr, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode"); switch (m_token.m_type) { case PLUSPLUS: m_nonTrivialExpressionCount++; m_nonLHSCount++; - expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEnd(), tokenEnd()); + expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEnd(), tokenEnd(), tokenLine(), tokenLineStart()); m_assignmentCount++; failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode"); failIfTrueIfStrict(requiresLExpr); @@ -1706,7 +1774,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpress case MINUSMINUS: m_nonTrivialExpressionCount++; m_nonLHSCount++; - expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEnd(), tokenEnd()); + expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEnd(), tokenEnd(), tokenLine(), tokenLineStart()); m_assignmentCount++; failIfTrueIfStrictWithNameAndMessage(isEvalOrArguments, "'", m_lastIdentifier->impl(), "' cannot be modified in strict mode"); failIfTrueIfStrict(requiresLExpr); @@ -1717,7 +1785,9 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpress } int end = lastTokenEnd(); - + int endLine = lastTokenLine(); + int endLineStartPosition = lastTokenLineStart(); + if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode())) return expr; @@ -1739,12 +1809,12 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpress break; case PLUSPLUS: case AUTOPLUSPLUS: - expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end); + expr = context.makePrefixNode(location, expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end, subExprLine, subExprLineStartPosition); m_assignmentCount++; break; case MINUSMINUS: case AUTOMINUSMINUS: - expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end); + expr = context.makePrefixNode(location, expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end, subExprLine, subExprLineStartPosition); m_assignmentCount++; break; case TYPEOF: @@ -1755,13 +1825,14 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpress break; case DELETETOKEN: failIfTrueIfStrictWithNameAndMessage(context.isResolve(expr), "Cannot delete unqualified property", m_lastIdentifier->impl(), "in strict mode"); - expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end); + expr = context.makeDeleteNode(location, expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end, endLine, endLineStartPosition); break; default: // If we get here something has gone horribly horribly wrong CRASH(); } subExprStart = context.unaryTokenStackLastStart(tokenStackDepth); + subExprLineStartPosition = context.unaryTokenStackLastLineStartPosition(tokenStackDepth); context.unaryTokenStackRemoveLast(tokenStackDepth); } return expr; diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h index 615d09eb7..e0a56754d 100644 --- a/Source/JavaScriptCore/parser/Parser.h +++ b/Source/JavaScriptCore/parser/Parser.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2011, 2013 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -30,9 +30,12 @@ #include "Lexer.h" #include "Nodes.h" #include "ParserArena.h" +#include "ParserError.h" #include "ParserTokens.h" #include "SourceProvider.h" +#include "SourceProviderCache.h" #include "SourceProviderCacheItem.h" +#include "VMStackBounds.h" #include <wtf/Forward.h> #include <wtf/Noncopyable.h> #include <wtf/OwnPtr.h> @@ -53,7 +56,7 @@ class ExecState; class FunctionBodyNode; class FunctionParameters; class Identifier; -class JSGlobalData; +class VM; class ProgramNode; class SourceCode; @@ -76,49 +79,6 @@ COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens); enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode }; enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName }; -struct ParserError { - enum ErrorType { ErrorNone, StackOverflow, SyntaxError, EvalError, OutOfMemory } m_type; - String m_message; - int m_line; - ParserError() - : m_type(ErrorNone) - , m_line(-1) - { - } - - ParserError(ErrorType type) - : m_type(type) - , m_line(-1) - { - } - - ParserError(ErrorType type, String msg, int line) - : m_type(type) - , m_message(msg) - , m_line(line) - { - } - - JSObject* toErrorObject(JSGlobalObject* globalObject, const SourceCode& source) - { - switch (m_type) { - case ErrorNone: - return 0; - case SyntaxError: - return addErrorInfo(globalObject->globalExec(), createSyntaxError(globalObject, m_message), m_line, source); - case EvalError: - return createSyntaxError(globalObject, m_message); - case StackOverflow: - return createStackOverflowError(globalObject); - case OutOfMemory: - return createOutOfMemoryError(globalObject); - } - CRASH(); - return createOutOfMemoryError(globalObject); // Appease Qt bot - } - -}; - template <typename T> inline bool isEvalNode() { return false; } template <> inline bool isEvalNode<EvalNode>() { return true; } @@ -151,8 +111,8 @@ struct ScopeLabelInfo { }; struct Scope { - Scope(const JSGlobalData* globalData, bool isFunction, bool strictMode) - : m_globalData(globalData) + Scope(const VM* vm, bool isFunction, bool strictMode) + : m_vm(vm) , m_shadowsArguments(false) , m_usesEval(false) , m_needsFullActivation(false) @@ -167,7 +127,7 @@ struct Scope { } Scope(const Scope& rhs) - : m_globalData(rhs.m_globalData) + : m_vm(rhs.m_vm) , m_shadowsArguments(rhs.m_shadowsArguments) , m_usesEval(rhs.m_usesEval) , m_needsFullActivation(rhs.m_needsFullActivation) @@ -237,7 +197,7 @@ struct Scope { bool declareVariable(const Identifier* ident) { - bool isValidStrictMode = m_globalData->propertyNames->eval != *ident && m_globalData->propertyNames->arguments != *ident; + bool isValidStrictMode = m_vm->propertyNames->eval != *ident && m_vm->propertyNames->arguments != *ident; m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; m_declaredVariables.add(ident->string().impl()); return isValidStrictMode; @@ -254,8 +214,8 @@ struct Scope { bool declareParameter(const Identifier* ident) { - bool isArguments = m_globalData->propertyNames->arguments == *ident; - bool isValidStrictMode = m_declaredVariables.add(ident->string().impl()).isNewEntry && m_globalData->propertyNames->eval != *ident && !isArguments; + bool isArguments = m_vm->propertyNames->arguments == *ident; + bool isValidStrictMode = m_declaredVariables.add(ident->string().impl()).isNewEntry && m_vm->propertyNames->eval != *ident && !isArguments; m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; if (isArguments) m_shadowsArguments = true; @@ -328,35 +288,32 @@ struct Scope { continue; vector.append(*it); } - vector.shrinkToFit(); } - void saveFunctionInfo(SourceProviderCacheItem* info) + void fillParametersForSourceProviderCache(SourceProviderCacheItemCreationParameters& parameters) { 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); + parameters.usesEval = m_usesEval; + parameters.strictMode = m_strictMode; + parameters.needsFullActivation = m_needsFullActivation; + copyCapturedVariablesToVector(m_writtenVariables, parameters.writtenVariables); + copyCapturedVariablesToVector(m_usedVariables, parameters.usedVariables); } - void restoreFunctionInfo(const SourceProviderCacheItem* info) + void restoreFromSourceProviderCache(const SourceProviderCacheItem* info) { 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]); - size = info->writtenVariables.size(); - for (unsigned i = 0; i < size; ++i) - m_writtenVariables.add(info->writtenVariables[i]); + for (unsigned i = 0; i < info->usedVariablesCount; ++i) + m_usedVariables.add(info->usedVariables()[i]); + for (unsigned i = 0; i < info->writtenVariablesCount; ++i) + m_writtenVariables.add(info->writtenVariables()[i]); } private: - const JSGlobalData* m_globalData; + const VM* m_vm; bool m_shadowsArguments : 1; bool m_usesEval : 1; bool m_needsFullActivation : 1; @@ -409,7 +366,7 @@ class Parser { WTF_MAKE_FAST_ALLOCATED; public: - Parser(JSGlobalData*, const SourceCode&, FunctionParameters*, const Identifier&, JSParserStrictness, JSParserMode); + Parser(VM*, const SourceCode&, FunctionParameters*, const Identifier&, JSParserStrictness, JSParserMode); ~Parser(); template <class ParsedNode> @@ -466,7 +423,7 @@ private: isStrict = m_scopeStack.last().strictMode(); isFunction = m_scopeStack.last().isFunction(); } - m_scopeStack.append(Scope(m_globalData, isFunction, isStrict)); + m_scopeStack.append(Scope(m_vm, isFunction, isStrict)); return currentScope(); } @@ -525,11 +482,11 @@ private: bool isFunctionBodyNode(ScopeNode*) { return false; } bool isFunctionBodyNode(FunctionBodyNode*) { return true; } - 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()); } @@ -538,6 +495,7 @@ private: { 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()); } @@ -565,7 +523,7 @@ private: return m_token.m_type == expected; } - ALWAYS_INLINE int tokenStart() + ALWAYS_INLINE unsigned tokenStart() { return m_token.m_location.startOffset; } @@ -575,11 +533,21 @@ private: return m_token.m_location.line; } - ALWAYS_INLINE int tokenEnd() + ALWAYS_INLINE int tokenColumn() + { + return tokenStart() - tokenLineStart(); + } + + ALWAYS_INLINE unsigned tokenEnd() { return m_token.m_location.endOffset; } + ALWAYS_INLINE unsigned tokenLineStart() + { + return m_token.m_location.lineStartOffset; + } + ALWAYS_INLINE const JSTokenLocation& tokenLocation() { return m_token.m_location; @@ -749,14 +717,24 @@ private: case RESERVED: case NUMBER: case IDENT: - case STRING: + case STRING: + case UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK: + case UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK: + case UNTERMINATED_MULTILINE_COMMENT_ERRORTOK: + case UNTERMINATED_NUMERIC_LITERAL_ERRORTOK: + case UNTERMINATED_STRING_LITERAL_ERRORTOK: + case INVALID_IDENTIFIER_ESCAPE_ERRORTOK: + case INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK: + case INVALID_NUMERIC_LITERAL_ERRORTOK: + case INVALID_OCTAL_NUMBER_ERRORTOK: + case INVALID_STRING_LITERAL_ERRORTOK: case ERRORTOK: - case EOFTOK: + case EOFTOK: return 0; case LastUntaggedToken: break; } - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); return "internal error"; } @@ -778,7 +756,36 @@ private: case STRING: m_errorMessage = "Unexpected string " + getToken(); return; - case ERRORTOK: + + case UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK: + case UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK: + m_errorMessage = "Incomplete unicode escape in identifier: '" + getToken() + '\''; + return; + case UNTERMINATED_MULTILINE_COMMENT_ERRORTOK: + m_errorMessage = "Unterminated multiline comment"; + return; + case UNTERMINATED_NUMERIC_LITERAL_ERRORTOK: + m_errorMessage = "Unterminated numeric literal '" + getToken() + '\''; + return; + case UNTERMINATED_STRING_LITERAL_ERRORTOK: + m_errorMessage = "Unterminated string literal '" + getToken() + '\''; + return; + case INVALID_IDENTIFIER_ESCAPE_ERRORTOK: + m_errorMessage = "Invalid escape in identifier: '" + getToken() + '\''; + return; + case INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK: + m_errorMessage = "Invalid unicode escape in identifier: '" + getToken() + '\''; + return; + case INVALID_NUMERIC_LITERAL_ERRORTOK: + m_errorMessage = "Invalid numeric literal: '" + getToken() + '\''; + return; + case INVALID_OCTAL_NUMBER_ERRORTOK: + m_errorMessage = "Invalid use of octal: '" + getToken() + '\''; + return; + case INVALID_STRING_LITERAL_ERRORTOK: + m_errorMessage = "Invalid string literal: '" + getToken() + '\''; + return; + case ERRORTOK: m_errorMessage = "Unrecognized token '" + getToken() + '\''; return; case EOFTOK: @@ -788,7 +795,7 @@ private: m_errorMessage = ASCIILiteral("Return statements are only valid inside functions"); return; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); m_errorMessage = ASCIILiteral("internal error"); return; } @@ -796,17 +803,16 @@ private: NEVER_INLINE void updateErrorMessage() { - m_error = true; const char* name = getTokenName(m_token.m_type); if (!name) updateErrorMessageSpecialCase(m_token.m_type); else m_errorMessage = String::format("Unexpected token '%s'", name); + ASSERT(!m_errorMessage.isNull()); } NEVER_INLINE void updateErrorMessage(JSTokenType expectedToken) { - m_error = true; const char* name = getTokenName(expectedToken); if (name) m_errorMessage = String::format("Expected token '%s'", name); @@ -816,18 +822,19 @@ private: else updateErrorMessageSpecialCase(expectedToken); } + ASSERT(!m_errorMessage.isNull()); } NEVER_INLINE void updateErrorWithNameAndMessage(const char* beforeMsg, String name, const char* afterMsg) { - m_error = true; m_errorMessage = makeString(beforeMsg, " '", name, "' ", afterMsg); } NEVER_INLINE void updateErrorMessage(const char* msg) - { - m_error = true; + { + ASSERT(msg); m_errorMessage = String(msg); + ASSERT(!m_errorMessage.isNull()); } void startLoop() { currentScope()->startLoop(); } @@ -910,7 +917,7 @@ private: 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); - template <FunctionRequirements, bool nameIsInContainingScope, 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&, unsigned& openBraceOffset, unsigned& closeBraceOffset, int& bodyStartLine, unsigned& bodyStartColumn); ALWAYS_INLINE int isBinaryOperator(JSTokenType); bool allowAutomaticSemicolon(); @@ -933,26 +940,42 @@ private: return m_lastTokenEnd; } - JSGlobalData* m_globalData; + unsigned lastTokenLine() const + { + return m_lastLine; + } + + unsigned lastTokenLineStart() const + { + return m_lastTokenLineStart; + } + + bool hasError() const + { + return !m_errorMessage.isNull(); + } + + VM* m_vm; const SourceCode* m_source; ParserArena* m_arena; OwnPtr<LexerType> m_lexer; - StackBounds m_stack; + VMStackBounds m_stack; bool m_hasStackOverflow; - bool m_error; String m_errorMessage; JSToken m_token; bool m_allowsIn; - int m_lastLine; + unsigned m_lastLine; int m_lastTokenEnd; + unsigned m_lastTokenLine; + unsigned m_lastTokenLineStart; int m_assignmentCount; int m_nonLHSCount; bool m_syntaxAlreadyValidated; int m_statementDepth; int m_nonTrivialExpressionCount; const Identifier* m_lastIdentifier; - SourceProviderCache* m_functionCache; + RefPtr<SourceProviderCache> m_functionCache; SourceElements* m_sourceElements; ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations; ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations; @@ -994,6 +1017,9 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(ParserError& error) errLine = -1; errMsg = String(); + JSTokenLocation startLocation(tokenLocation()); + unsigned startColumn = m_source->startColumn(); + String parseError = parseInner(); int lineNumber = m_lexer->lineNumber(); @@ -1010,11 +1036,14 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(ParserError& error) RefPtr<ParsedNode> result; if (m_sourceElements) { - JSTokenLocation location; - location.line = m_lexer->lastLineNumber(); - location.column = m_lexer->currentColumnNumber(); - result = ParsedNode::create(m_globalData, - location, + JSTokenLocation endLocation; + endLocation.line = m_lexer->lastLineNumber(); + endLocation.lineStartOffset = m_lexer->currentLineStartOffset(); + endLocation.startOffset = m_lexer->currentOffset(); + result = ParsedNode::create(m_vm, + startLocation, + endLocation, + startColumn, m_sourceElements, m_varDeclarations ? &m_varDeclarations->data : 0, m_funcDeclarations ? &m_funcDeclarations->data : 0, @@ -1022,7 +1051,7 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(ParserError& error) *m_source, m_features, m_numConstants); - result->setLoc(m_source->firstLine(), m_lastLine, m_lexer->currentColumnNumber()); + result->setLoc(m_source->firstLine(), m_lastLine, 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 @@ -1031,11 +1060,19 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(ParserError& error) // code we assume that it was a syntax error since running out of stack is much less // likely, and we are currently unable to distinguish between the two cases. if (isFunctionBodyNode(static_cast<ParsedNode*>(0)) || m_hasStackOverflow) - error = ParserError::StackOverflow; - else if (isEvalNode<ParsedNode>()) - error = ParserError(ParserError::EvalError, errMsg, errLine); - else - error = ParserError(ParserError::SyntaxError, errMsg, errLine); + error = ParserError(ParserError::StackOverflow, ParserError::SyntaxErrorNone, m_token); + else { + ParserError::SyntaxErrorType errorType = ParserError::SyntaxErrorIrrecoverable; + if (m_token.m_type == EOFTOK) + errorType = ParserError::SyntaxErrorRecoverable; + else if (m_token.m_type & UnterminatedErrorTokenFlag) + errorType = ParserError::SyntaxErrorUnterminatedLiteral; + + if (isEvalNode<ParsedNode>()) + error = ParserError(ParserError::EvalError, errorType, m_token, errMsg, errLine); + else + error = ParserError(ParserError::SyntaxError, errorType, m_token, errMsg, errLine); + } } m_arena->reset(); @@ -1044,16 +1081,16 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(ParserError& error) } template <class ParsedNode> -PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, ParserError& error) +PassRefPtr<ParsedNode> parse(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, ParserError& error) { SamplingRegion samplingRegion("Parsing"); ASSERT(!source.provider()->source().isNull()); if (source.provider()->source().is8Bit()) { - Parser< Lexer<LChar> > parser(globalData, source, parameters, name, strictness, parserMode); + Parser< Lexer<LChar> > parser(vm, source, parameters, name, strictness, parserMode); return parser.parse<ParsedNode>(error); } - Parser< Lexer<UChar> > parser(globalData, source, parameters, name, strictness, parserMode); + Parser< Lexer<UChar> > parser(vm, source, parameters, name, strictness, parserMode); return parser.parse<ParsedNode>(error); } diff --git a/Source/JavaScriptCore/parser/ParserArena.h b/Source/JavaScriptCore/parser/ParserArena.h index 2f5b447b1..45d4b158e 100644 --- a/Source/JavaScriptCore/parser/ParserArena.h +++ b/Source/JavaScriptCore/parser/ParserArena.h @@ -43,10 +43,10 @@ namespace JSC { } template <typename T> - ALWAYS_INLINE const Identifier& makeIdentifier(JSGlobalData*, const T* characters, size_t length); - ALWAYS_INLINE const Identifier& makeIdentifierLCharFromUChar(JSGlobalData*, const UChar* characters, size_t length); + ALWAYS_INLINE const Identifier& makeIdentifier(VM*, const T* characters, size_t length); + ALWAYS_INLINE const Identifier& makeIdentifierLCharFromUChar(VM*, const UChar* characters, size_t length); - const Identifier& makeNumericIdentifier(JSGlobalData*, double number); + const Identifier& makeNumericIdentifier(VM*, double number); bool isEmpty() const { return m_identifiers.isEmpty(); } @@ -69,51 +69,51 @@ namespace JSC { }; template <typename T> - ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifier(JSGlobalData* globalData, const T* characters, size_t length) + ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifier(VM* vm, const T* characters, size_t length) { if (characters[0] >= MaximumCachableCharacter) { - m_identifiers.append(Identifier(globalData, characters, length)); + m_identifiers.append(Identifier(vm, characters, length)); return m_identifiers.last(); } if (length == 1) { if (Identifier* ident = m_shortIdentifiers[characters[0]]) return *ident; - m_identifiers.append(Identifier(globalData, characters, length)); + m_identifiers.append(Identifier(vm, characters, length)); m_shortIdentifiers[characters[0]] = &m_identifiers.last(); return m_identifiers.last(); } Identifier* ident = m_recentIdentifiers[characters[0]]; if (ident && Identifier::equal(ident->impl(), characters, length)) return *ident; - m_identifiers.append(Identifier(globalData, characters, length)); + m_identifiers.append(Identifier(vm, characters, length)); m_recentIdentifiers[characters[0]] = &m_identifiers.last(); return m_identifiers.last(); } - ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifierLCharFromUChar(JSGlobalData* globalData, const UChar* characters, size_t length) + ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifierLCharFromUChar(VM* vm, const UChar* characters, size_t length) { if (characters[0] >= MaximumCachableCharacter) { - m_identifiers.append(Identifier::createLCharFromUChar(globalData, characters, length)); + m_identifiers.append(Identifier::createLCharFromUChar(vm, characters, length)); return m_identifiers.last(); } if (length == 1) { if (Identifier* ident = m_shortIdentifiers[characters[0]]) return *ident; - m_identifiers.append(Identifier(globalData, characters, length)); + m_identifiers.append(Identifier(vm, characters, length)); m_shortIdentifiers[characters[0]] = &m_identifiers.last(); return m_identifiers.last(); } Identifier* ident = m_recentIdentifiers[characters[0]]; if (ident && Identifier::equal(ident->impl(), characters, length)) return *ident; - m_identifiers.append(Identifier::createLCharFromUChar(globalData, characters, length)); + m_identifiers.append(Identifier::createLCharFromUChar(vm, characters, length)); m_recentIdentifiers[characters[0]] = &m_identifiers.last(); return m_identifiers.last(); } - inline const Identifier& IdentifierArena::makeNumericIdentifier(JSGlobalData* globalData, double number) + inline const Identifier& IdentifierArena::makeNumericIdentifier(VM* vm, double number) { - m_identifiers.append(Identifier(globalData, String::numberToStringECMAScript(number))); + m_identifiers.append(Identifier(vm, String::numberToStringECMAScript(number))); return m_identifiers.last(); } diff --git a/Source/JavaScriptCore/parser/ParserError.h b/Source/JavaScriptCore/parser/ParserError.h new file mode 100644 index 000000000..baa4465d0 --- /dev/null +++ b/Source/JavaScriptCore/parser/ParserError.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2013 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ParserError_h +#define ParserError_h + +#include "Error.h" +#include "ExceptionHelpers.h" +#include "ParserTokens.h" +#include <wtf/text/WTFString.h> + +namespace JSC { + +struct ParserError { + enum SyntaxErrorType { + SyntaxErrorNone, + SyntaxErrorIrrecoverable, + SyntaxErrorUnterminatedLiteral, + SyntaxErrorRecoverable + }; + + enum ErrorType { + ErrorNone, + StackOverflow, + EvalError, + OutOfMemory, + SyntaxError + }; + + ErrorType m_type; + SyntaxErrorType m_syntaxErrorType; + JSToken m_token; + String m_message; + int m_line; + ParserError() + : m_type(ErrorNone) + , m_syntaxErrorType(SyntaxErrorNone) + , m_line(-1) + { + } + + explicit ParserError(ErrorType type) + : m_type(type) + , m_syntaxErrorType(SyntaxErrorNone) + , m_line(-1) + { + } + + ParserError(ErrorType type, SyntaxErrorType syntaxError, JSToken token) + : m_type(type) + , m_syntaxErrorType(syntaxError) + , m_token(token) + , m_line(-1) + { + } + + ParserError(ErrorType type, SyntaxErrorType syntaxError, JSToken token, String msg, int line) + : m_type(type) + , m_syntaxErrorType(syntaxError) + , m_token(token) + , m_message(msg) + , m_line(line) + { + } + + JSObject* toErrorObject(JSGlobalObject* globalObject, const SourceCode& source) + { + switch (m_type) { + case ErrorNone: + return 0; + case SyntaxError: + return addErrorInfo(globalObject->globalExec(), createSyntaxError(globalObject, m_message), m_line, source); + case EvalError: + return createSyntaxError(globalObject, m_message); + case StackOverflow: + return createStackOverflowError(globalObject); + case OutOfMemory: + return createOutOfMemoryError(globalObject); + } + CRASH(); + return createOutOfMemoryError(globalObject); // Appease Qt bot + } +#undef GET_ERROR_CODE +}; + +} // namespace JSC + +#endif // ParserError_h diff --git a/Source/JavaScriptCore/parser/ParserModes.h b/Source/JavaScriptCore/parser/ParserModes.h index 41fb7fdf9..a7383a3e1 100644 --- a/Source/JavaScriptCore/parser/ParserModes.h +++ b/Source/JavaScriptCore/parser/ParserModes.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,6 +35,21 @@ enum JSParserMode { JSParseProgramCode, JSParseFunctionCode }; enum ProfilerMode { ProfilerOff, ProfilerOn }; enum DebuggerMode { DebuggerOff, DebuggerOn }; -} +enum FunctionNameIsInScopeToggle { FunctionNameIsNotInScope, FunctionNameIsInScope }; -#endif +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; + +} // namespace JSC + +#endif // ParserModes_h diff --git a/Source/JavaScriptCore/parser/ParserTokens.h b/Source/JavaScriptCore/parser/ParserTokens.h index 14191b95d..ed9780b52 100644 --- a/Source/JavaScriptCore/parser/ParserTokens.h +++ b/Source/JavaScriptCore/parser/ParserTokens.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,6 +27,8 @@ #define ParserTokens_h #include "ParserModes.h" +#include <limits.h> +#include <stdint.h> namespace JSC { @@ -38,6 +40,8 @@ enum { BinaryOpTokenPrecedenceShift = 8, BinaryOpTokenAllowsInPrecedenceAdditionalShift = 4, BinaryOpTokenPrecedenceMask = 15 << BinaryOpTokenPrecedenceShift, + ErrorTokenFlag = 1 << (BinaryOpTokenAllowsInPrecedenceAdditionalShift + BinaryOpTokenPrecedenceShift + 7), + UnterminatedErrorTokenFlag = ErrorTokenFlag << 1 }; #define BINARY_OP_PRECEDENCE(prec) (((prec) << BinaryOpTokenPrecedenceShift) | ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift))) @@ -85,7 +89,6 @@ enum JSTokenType { SEMICOLON, COLON, DOT, - ERRORTOK, EOFTOK, EQUAL, PLUSEQUAL, @@ -133,28 +136,44 @@ enum JSTokenType { MINUS = 19 | BINARY_OP_PRECEDENCE(9) | UnaryOpTokenFlag, TIMES = 20 | BINARY_OP_PRECEDENCE(10), DIVIDE = 21 | BINARY_OP_PRECEDENCE(10), - MOD = 22 | BINARY_OP_PRECEDENCE(10) + MOD = 22 | BINARY_OP_PRECEDENCE(10), + ERRORTOK = 0 | ErrorTokenFlag, + UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK = 0 | ErrorTokenFlag | UnterminatedErrorTokenFlag, + INVALID_IDENTIFIER_ESCAPE_ERRORTOK = 1 | ErrorTokenFlag, + UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK = 2 | ErrorTokenFlag | UnterminatedErrorTokenFlag, + INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK = 3 | ErrorTokenFlag, + UNTERMINATED_MULTILINE_COMMENT_ERRORTOK = 4 | ErrorTokenFlag | UnterminatedErrorTokenFlag, + UNTERMINATED_NUMERIC_LITERAL_ERRORTOK = 5 | ErrorTokenFlag | UnterminatedErrorTokenFlag, + INVALID_OCTAL_NUMBER_ERRORTOK = 6 | ErrorTokenFlag | UnterminatedErrorTokenFlag, + INVALID_NUMERIC_LITERAL_ERRORTOK = 7 | ErrorTokenFlag, + UNTERMINATED_STRING_LITERAL_ERRORTOK = 8 | ErrorTokenFlag | UnterminatedErrorTokenFlag, + INVALID_STRING_LITERAL_ERRORTOK = 9 | ErrorTokenFlag, }; union JSTokenData { - int intValue; + struct { + uint32_t line; + uint32_t offset; + uint32_t lineStartOffset; + }; double doubleValue; const Identifier* ident; }; struct JSTokenLocation { - JSTokenLocation() : line(0), column(0) { } + JSTokenLocation() : line(0), lineStartOffset(0), startOffset(0) { } JSTokenLocation(const JSTokenLocation& location) { line = location.line; + lineStartOffset = location.lineStartOffset; startOffset = location.startOffset; endOffset = location.endOffset; - column = location.column; } + int line; - int startOffset; - int endOffset; - int column; + unsigned lineStartOffset; + unsigned startOffset; + unsigned endOffset; }; struct JSToken { @@ -163,7 +182,6 @@ struct JSToken { JSTokenLocation m_location; }; -} - +} // namespace JSC #endif // ParserTokens_h diff --git a/Source/JavaScriptCore/parser/ResultType.h b/Source/JavaScriptCore/parser/ResultType.h index 8f30e5b64..de4bde66b 100644 --- a/Source/JavaScriptCore/parser/ResultType.h +++ b/Source/JavaScriptCore/parser/ResultType.h @@ -62,6 +62,11 @@ namespace JSC { return (m_type & TypeBits) == TypeMaybeString; } + bool definitelyIsBoolean() + { + return (m_type & TypeBits) == TypeMaybeBool; + } + bool mightBeNumber() { return m_type & TypeMaybeNumber; diff --git a/Source/JavaScriptCore/parser/SourceCode.h b/Source/JavaScriptCore/parser/SourceCode.h index a094469a2..f221f9244 100644 --- a/Source/JavaScriptCore/parser/SourceCode.h +++ b/Source/JavaScriptCore/parser/SourceCode.h @@ -41,25 +41,44 @@ namespace JSC { , m_startChar(0) , m_endChar(0) , m_firstLine(0) + , m_startColumn(0) { } - SourceCode(PassRefPtr<SourceProvider> provider, int firstLine = 1) + SourceCode(WTF::HashTableDeletedValueType) + : m_provider(WTF::HashTableDeletedValue) + { + } + + SourceCode(PassRefPtr<SourceProvider> provider) + : m_provider(provider) + , m_startChar(0) + , m_endChar(m_provider->source().length()) + , m_firstLine(1) + , m_startColumn(1) + { + } + + SourceCode(PassRefPtr<SourceProvider> provider, int firstLine, int startColumn) : m_provider(provider) , m_startChar(0) , m_endChar(m_provider->source().length()) , m_firstLine(std::max(firstLine, 1)) + , m_startColumn(std::max(startColumn, 1)) { } - SourceCode(PassRefPtr<SourceProvider> provider, int start, int end, int firstLine) + SourceCode(PassRefPtr<SourceProvider> provider, int start, int end, int firstLine, int startColumn) : m_provider(provider) , m_startChar(start) , m_endChar(end) , m_firstLine(std::max(firstLine, 1)) + , m_startColumn(std::max(startColumn, 1)) { } + bool isHashTableDeletedValue() const { return m_provider.isHashTableDeletedValue(); } + String toString() const { if (!m_provider) @@ -77,29 +96,32 @@ namespace JSC { bool isNull() const { return !m_provider; } SourceProvider* provider() const { return m_provider.get(); } int firstLine() const { return m_firstLine; } + int startColumn() const { return m_startColumn; } int startOffset() const { return m_startChar; } int endOffset() const { return m_endChar; } int length() const { return m_endChar - m_startChar; } - SourceCode subExpression(unsigned openBrace, unsigned closeBrace, int firstLine); + SourceCode subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn); private: RefPtr<SourceProvider> m_provider; int m_startChar; int m_endChar; int m_firstLine; + int m_startColumn; }; inline SourceCode makeSource(const String& source, const String& url = String(), const TextPosition& startPosition = TextPosition::minimumPosition()) { - return SourceCode(StringSourceProvider::create(source, url, startPosition), startPosition.m_line.oneBasedInt()); + return SourceCode(StringSourceProvider::create(source, url, startPosition), startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt()); } - inline SourceCode SourceCode::subExpression(unsigned openBrace, unsigned closeBrace, int firstLine) + inline SourceCode SourceCode::subExpression(unsigned openBrace, unsigned closeBrace, int firstLine, int startColumn) { ASSERT(provider()->source()[openBrace] == '{'); ASSERT(provider()->source()[closeBrace] == '}'); - return SourceCode(provider(), openBrace, closeBrace + 1, firstLine); + startColumn += 1; // Convert to base 1. + return SourceCode(provider(), openBrace, closeBrace + 1, firstLine, startColumn); } } // namespace JSC diff --git a/Source/JavaScriptCore/parser/SourceProvider.cpp b/Source/JavaScriptCore/parser/SourceProvider.cpp new file mode 100644 index 000000000..47b29aa37 --- /dev/null +++ b/Source/JavaScriptCore/parser/SourceProvider.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2013 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "SourceProvider.h" +#include <wtf/StdLibExtras.h> +#include <wtf/TCSpinLock.h> + +namespace JSC { + +SourceProvider::SourceProvider(const String& url, const TextPosition& startPosition) + : m_url(url) + , m_startPosition(startPosition) + , m_validated(false) + , m_id(0) +{ +} + +SourceProvider::~SourceProvider() +{ +} + +static inline size_t charPositionExtractor(const size_t* value) +{ + return *value; +} + +static TCMalloc_SpinLock providerIdLock = SPINLOCK_INITIALIZER; + +void SourceProvider::getID() +{ + SpinLockHolder lock(&providerIdLock); + if (!m_id) { + static intptr_t nextProviderID = 0; + m_id = ++nextProviderID; + } +} + +} // namespace JSC + diff --git a/Source/JavaScriptCore/parser/SourceProvider.h b/Source/JavaScriptCore/parser/SourceProvider.h index 145b2dd16..4ced9d9c7 100644 --- a/Source/JavaScriptCore/parser/SourceProvider.h +++ b/Source/JavaScriptCore/parser/SourceProvider.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2012, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,11 +29,10 @@ #ifndef SourceProvider_h #define SourceProvider_h -#include "SourceProviderCache.h" #include <wtf/PassOwnPtr.h> #include <wtf/RefCounted.h> -#include <wtf/UnusedParam.h> #include <wtf/text/TextPosition.h> +#include <wtf/text/WTFString.h> namespace JSC { @@ -41,20 +40,9 @@ namespace JSC { public: static const intptr_t nullID = 1; - SourceProvider(const String& url, const TextPosition& startPosition, SourceProviderCache* cache = 0) - : m_url(url) - , m_startPosition(startPosition) - , m_validated(false) - , m_cache(cache ? cache : new SourceProviderCache) - , m_cacheOwned(!cache) - { - } + JS_EXPORT_PRIVATE SourceProvider(const String& url, const TextPosition& startPosition); - virtual ~SourceProvider() - { - if (m_cacheOwned) - delete m_cache; - } + JS_EXPORT_PRIVATE virtual ~SourceProvider(); virtual const String& source() const = 0; String getRange(int start, int end) const @@ -69,23 +57,23 @@ namespace JSC { ASSERT(this); if (!this) // Be defensive in release mode. return nullID; - return reinterpret_cast<intptr_t>(this); + if (!m_id) + getID(); + return m_id; } bool isValid() const { return m_validated; } void setValid() { m_validated = true; } - SourceProviderCache* cache() const { return m_cache; } - void notifyCacheSizeChanged(int delta) { if (!m_cacheOwned) cacheSizeChanged(delta); } - private: - virtual void cacheSizeChanged(int delta) { UNUSED_PARAM(delta); } + + JS_EXPORT_PRIVATE void getID(); + Vector<size_t>& lineStarts(); String m_url; TextPosition m_startPosition; - bool m_validated; - SourceProviderCache* m_cache; - bool m_cacheOwned; + bool m_validated : 1; + uintptr_t m_id : sizeof(uintptr_t) * 8 - 1; }; class StringSourceProvider : public SourceProvider { diff --git a/Source/JavaScriptCore/parser/SourceProviderCache.cpp b/Source/JavaScriptCore/parser/SourceProviderCache.cpp index ad1cbe02e..f284ee63a 100644 --- a/Source/JavaScriptCore/parser/SourceProviderCache.cpp +++ b/Source/JavaScriptCore/parser/SourceProviderCache.cpp @@ -36,18 +36,11 @@ SourceProviderCache::~SourceProviderCache() void SourceProviderCache::clear() { m_map.clear(); - m_contentByteSize = 0; } -unsigned SourceProviderCache::byteSize() const -{ - return m_contentByteSize + sizeof(*this) + m_map.capacity() * sizeof(SourceProviderCacheItem*); -} - -void SourceProviderCache::add(int sourcePosition, PassOwnPtr<SourceProviderCacheItem> item, unsigned size) +void SourceProviderCache::add(int sourcePosition, PassOwnPtr<SourceProviderCacheItem> item) { m_map.add(sourcePosition, item); - m_contentByteSize += size; } } diff --git a/Source/JavaScriptCore/parser/SourceProviderCache.h b/Source/JavaScriptCore/parser/SourceProviderCache.h index c346fba0c..06b6c45a2 100644 --- a/Source/JavaScriptCore/parser/SourceProviderCache.h +++ b/Source/JavaScriptCore/parser/SourceProviderCache.h @@ -30,23 +30,22 @@ #include <wtf/HashMap.h> #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> +#include <wtf/RefCounted.h> namespace JSC { -class SourceProviderCache { +class SourceProviderCache : public RefCounted<SourceProviderCache> { WTF_MAKE_FAST_ALLOCATED; public: - SourceProviderCache() : m_contentByteSize(0) {} + SourceProviderCache() { } JS_EXPORT_PRIVATE ~SourceProviderCache(); JS_EXPORT_PRIVATE void clear(); - JS_EXPORT_PRIVATE unsigned byteSize() const; - void add(int sourcePosition, PassOwnPtr<SourceProviderCacheItem>, unsigned size); + void add(int sourcePosition, PassOwnPtr<SourceProviderCacheItem>); const SourceProviderCacheItem* get(int sourcePosition) const { return m_map.get(sourcePosition); } private: HashMap<int, OwnPtr<SourceProviderCacheItem> > m_map; - unsigned m_contentByteSize; }; } diff --git a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h index ec3890560..8d35a3d27 100644 --- a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h +++ b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h @@ -27,37 +27,46 @@ #define SourceProviderCacheItem_h #include "ParserTokens.h" +#include <wtf/PassOwnPtr.h> #include <wtf/Vector.h> #include <wtf/text/WTFString.h> namespace JSC { +struct SourceProviderCacheItemCreationParameters { + unsigned functionStart; + unsigned closeBraceLine; + unsigned closeBraceOffset; + unsigned closeBraceLineStartOffset; + bool needsFullActivation; + bool usesEval; + bool strictMode; + Vector<RefPtr<StringImpl> > usedVariables; + Vector<RefPtr<StringImpl> > writtenVariables; +}; + +#if COMPILER(MSVC) +#pragma warning(push) +#pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning +#endif + class SourceProviderCacheItem { WTF_MAKE_FAST_ALLOCATED; public: - SourceProviderCacheItem(unsigned functionStart, unsigned closeBraceLine, unsigned closeBracePos) - : functionStart(functionStart) - , closeBraceLine(closeBraceLine) - , closeBracePos(closeBracePos) - { - } - unsigned approximateByteSize() const - { - // The identifiers are uniqued strings so most likely there are few names that actually use any additional memory. - static const unsigned assummedAverageIdentifierSize = sizeof(RefPtr<StringImpl>) + 2; - unsigned size = sizeof(*this); - size += usedVariables.size() * assummedAverageIdentifierSize; - size += writtenVariables.size() * assummedAverageIdentifierSize; - return size; - } + static PassOwnPtr<SourceProviderCacheItem> create(const SourceProviderCacheItemCreationParameters&); + ~SourceProviderCacheItem(); + JSToken closeBraceToken() const { JSToken token; token.m_type = CLOSEBRACE; - token.m_data.intValue = closeBracePos; - token.m_location.startOffset = closeBracePos; - token.m_location.endOffset = closeBracePos + 1; + token.m_data.offset = closeBraceOffset; + token.m_location.startOffset = closeBraceOffset; + token.m_location.endOffset = closeBraceOffset + 1; token.m_location.line = closeBraceLine; + token.m_location.lineStartOffset = closeBraceLineStartOffset; + // token.m_location.sourceOffset is initialized once by the client. So, + // we do not need to set it here. return token; } @@ -67,13 +76,62 @@ public: unsigned closeBraceLine : 31; bool usesEval : 1; - unsigned closeBracePos : 31; + unsigned closeBraceOffset : 31; bool strictMode : 1; - Vector<RefPtr<StringImpl> > usedVariables; - Vector<RefPtr<StringImpl> > writtenVariables; + unsigned closeBraceLineStartOffset; + unsigned usedVariablesCount; + unsigned writtenVariablesCount; + + StringImpl** usedVariables() const { return const_cast<StringImpl**>(m_variables); } + StringImpl** writtenVariables() const { return const_cast<StringImpl**>(&m_variables[usedVariablesCount]); } + +private: + SourceProviderCacheItem(const SourceProviderCacheItemCreationParameters&); + + StringImpl* m_variables[0]; }; +inline SourceProviderCacheItem::~SourceProviderCacheItem() +{ + for (unsigned i = 0; i < usedVariablesCount + writtenVariablesCount; ++i) + m_variables[i]->deref(); +} + +inline PassOwnPtr<SourceProviderCacheItem> SourceProviderCacheItem::create(const SourceProviderCacheItemCreationParameters& parameters) +{ + size_t variableCount = parameters.writtenVariables.size() + parameters.usedVariables.size(); + size_t objectSize = sizeof(SourceProviderCacheItem) + sizeof(StringImpl*) * variableCount; + void* slot = fastMalloc(objectSize); + return adoptPtr(new (slot) SourceProviderCacheItem(parameters)); +} + +inline SourceProviderCacheItem::SourceProviderCacheItem(const SourceProviderCacheItemCreationParameters& parameters) + : functionStart(parameters.functionStart) + , needsFullActivation(parameters.needsFullActivation) + , closeBraceLine(parameters.closeBraceLine) + , usesEval(parameters.usesEval) + , closeBraceOffset(parameters.closeBraceOffset) + , strictMode(parameters.strictMode) + , closeBraceLineStartOffset(parameters.closeBraceLineStartOffset) + , usedVariablesCount(parameters.usedVariables.size()) + , writtenVariablesCount(parameters.writtenVariables.size()) +{ + unsigned j = 0; + for (unsigned i = 0; i < usedVariablesCount; ++i, ++j) { + m_variables[j] = parameters.usedVariables[i].get(); + m_variables[j]->ref(); + } + for (unsigned i = 0; i < writtenVariablesCount; ++i, ++j) { + m_variables[j] = parameters.writtenVariables[i].get(); + m_variables[j]->ref(); + } +} + +#if COMPILER(MSVC) +#pragma warning(pop) +#endif + } #endif // SourceProviderCacheItem_h diff --git a/Source/JavaScriptCore/parser/SyntaxChecker.h b/Source/JavaScriptCore/parser/SyntaxChecker.h index 0e6889752..7f902c0fd 100644 --- a/Source/JavaScriptCore/parser/SyntaxChecker.h +++ b/Source/JavaScriptCore/parser/SyntaxChecker.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -64,7 +64,7 @@ public: SyntaxChecker* m_context; }; - SyntaxChecker(JSGlobalData* , void*) + SyntaxChecker(VM* , void*) { } @@ -119,21 +119,21 @@ public: static const unsigned DontBuildStrings = LexerFlagsDontBuildStrings; int createSourceElements() { return 1; } - ExpressionType makeFunctionCallNode(const JSTokenLocation&, int, int, int, int, int) { return CallExpr; } + ExpressionType makeFunctionCallNode(const JSTokenLocation&, int, int, int, int, int, int, int) { return CallExpr; } void appendToComma(ExpressionType& base, ExpressionType right) { base = right; } ExpressionType createCommaExpr(const JSTokenLocation&, ExpressionType, ExpressionType right) { return right; } - ExpressionType makeAssignNode(const JSTokenLocation&, ExpressionType, Operator, ExpressionType, bool, bool, int, int, int) { return AssignmentExpr; } - ExpressionType makePrefixNode(const JSTokenLocation&, ExpressionType, Operator, int, int, int) { return PreExpr; } - ExpressionType makePostfixNode(const JSTokenLocation&, ExpressionType, Operator, int, int, int) { return PostExpr; } + ExpressionType makeAssignNode(const JSTokenLocation&, ExpressionType, Operator, ExpressionType, bool, bool, int, int, int, int, int) { return AssignmentExpr; } + ExpressionType makePrefixNode(const JSTokenLocation&, ExpressionType, Operator, int, int, int, int, int) { return PreExpr; } + ExpressionType makePostfixNode(const JSTokenLocation&, ExpressionType, Operator, int, int, int, int, int) { return PostExpr; } ExpressionType makeTypeOfNode(const JSTokenLocation&, ExpressionType) { return TypeofExpr; } - ExpressionType makeDeleteNode(const JSTokenLocation&, ExpressionType, int, int, int) { return DeleteExpr; } + ExpressionType makeDeleteNode(const JSTokenLocation&, ExpressionType, int, int, int, int, int) { return DeleteExpr; } ExpressionType makeNegateNode(const JSTokenLocation&, ExpressionType) { return UnaryExpr; } ExpressionType makeBitwiseNotNode(const JSTokenLocation&, ExpressionType) { return UnaryExpr; } ExpressionType createLogicalNot(const JSTokenLocation&, ExpressionType) { return UnaryExpr; } ExpressionType createUnaryPlus(const JSTokenLocation&, ExpressionType) { return UnaryExpr; } ExpressionType createVoid(const JSTokenLocation&, ExpressionType) { return UnaryExpr; } ExpressionType thisExpr(const JSTokenLocation&) { return ThisExpr; } - ExpressionType createResolve(const JSTokenLocation&, const Identifier*, int) { return ResolveExpr; } + ExpressionType createResolve(const JSTokenLocation&, const Identifier*, int, int, int) { return ResolveExpr; } ExpressionType createObjectLiteral(const JSTokenLocation&) { return ObjectLiteralExpr; } ExpressionType createObjectLiteral(const JSTokenLocation&, int) { return ObjectLiteralExpr; } ExpressionType createArray(const JSTokenLocation&, int) { return ArrayLiteralExpr; } @@ -142,15 +142,16 @@ public: ExpressionType createString(const JSTokenLocation&, const Identifier*) { return StringExpr; } ExpressionType createBoolean(const JSTokenLocation&, bool) { return BoolExpr; } ExpressionType createNull(const JSTokenLocation&) { return NullExpr; } - ExpressionType createBracketAccess(const JSTokenLocation&, ExpressionType, ExpressionType, bool, int, int, int) { return BracketExpr; } - ExpressionType createDotAccess(const JSTokenLocation&, ExpressionType, const Identifier*, int, int, int) { return DotExpr; } - ExpressionType createRegExp(const JSTokenLocation&, const Identifier& pattern, const Identifier&, int) { return Yarr::checkSyntax(pattern.string()) ? 0 : RegExpExpr; } + ExpressionType createBracketAccess(const JSTokenLocation&, ExpressionType, ExpressionType, bool, int, int, int, int, int) { return BracketExpr; } + ExpressionType createDotAccess(const JSTokenLocation&, ExpressionType, const Identifier*, int, int, int, int, int) { return DotExpr; } + ExpressionType createRegExp(const JSTokenLocation&, const Identifier& pattern, const Identifier&, int, int, int) { return Yarr::checkSyntax(pattern.string()) ? 0 : RegExpExpr; } + ExpressionType createNewExpr(const JSTokenLocation&, ExpressionType, int, int, int, int, int, int) { return NewExpr; } ExpressionType createNewExpr(const JSTokenLocation&, ExpressionType, int, int, int, int) { return NewExpr; } - ExpressionType createNewExpr(const JSTokenLocation&, ExpressionType, int, int) { return NewExpr; } ExpressionType createConditionalExpr(const JSTokenLocation&, ExpressionType, ExpressionType, ExpressionType) { return ConditionalExpr; } - ExpressionType createAssignResolve(const JSTokenLocation&, const Identifier&, ExpressionType, int, int, int) { return AssignmentExpr; } - ExpressionType createFunctionExpr(const JSTokenLocation&, const Identifier*, int, int, int, int, int, int) { return FunctionExpr; } - int createFunctionBody(const JSTokenLocation&, bool) { return 1; } + ExpressionType createAssignResolve(const JSTokenLocation&, const Identifier&, ExpressionType, int, int, int, int, int) { return AssignmentExpr; } + ExpressionType createFunctionExpr(const JSTokenLocation&, const Identifier*, int, int, int, int, int, int, int) { return FunctionExpr; } + int createFunctionBody(const JSTokenLocation&, const JSTokenLocation&, int, bool) { return 1; } + void setFunctionStart(int, int) { } int createArguments() { return 1; } int createArguments(int) { return 1; } int createArgumentsList(const JSTokenLocation&, int) { return 1; } @@ -162,11 +163,11 @@ public: ASSERT(name); return Property(name, type); } - template <bool complete> Property createProperty(JSGlobalData* globalData, double name, int, PropertyNode::Type type) + template <bool complete> Property createProperty(VM* vm, double name, int, PropertyNode::Type type) { if (!complete) return Property(type); - return Property(&globalData->parserArena->identifierArena().makeNumericIdentifier(globalData, name), type); + return Property(&vm->parserArena->identifierArena().makeNumericIdentifier(vm, name), type); } int createPropertyList(const JSTokenLocation&, Property) { return 1; } int createPropertyList(const JSTokenLocation&, Property, int) { return 1; } @@ -178,50 +179,50 @@ public: int createClauseList(int) { return 1; } int createClauseList(int, int) { return 1; } void setUsesArguments(int) { } - int createFuncDeclStatement(const JSTokenLocation&, const Identifier*, int, int, int, int, int, int) { return 1; } + int createFuncDeclStatement(const JSTokenLocation&, const Identifier*, int, int, int, int, int, int, int) { return 1; } int createBlockStatement(const JSTokenLocation&, int, int, int) { return 1; } int createExprStatement(const JSTokenLocation&, int, int, int) { return 1; } int createIfStatement(const JSTokenLocation&, int, int, int, int) { return 1; } int createIfStatement(const JSTokenLocation&, int, int, int, int, int) { return 1; } int createForLoop(const JSTokenLocation&, int, int, int, int, int, int) { return 1; } - int createForInLoop(const JSTokenLocation&, const Identifier*, int, int, int, int, int, int, int, int, int, int) { return 1; } - int createForInLoop(const JSTokenLocation&, int, int, int, int, int, int, int, int) { return 1; } + int createForInLoop(const JSTokenLocation&, const Identifier*, int, int, int, int, int, int, int, int, int, int, int, int) { return 1; } + int createForInLoop(const JSTokenLocation&, int, int, int, int, int, int, int, int, int, int) { return 1; } int createEmptyStatement(const JSTokenLocation&) { return 1; } int createVarStatement(const JSTokenLocation&, int, int, int) { return 1; } - int createReturnStatement(const JSTokenLocation&, int, int, int, int, int) { return 1; } - int createBreakStatement(const JSTokenLocation&, int, int, int, int) { return 1; } - int createBreakStatement(const JSTokenLocation&, const Identifier*, int, int, int, int) { return 1; } - int createContinueStatement(const JSTokenLocation&, int, int, int, int) { return 1; } - int createContinueStatement(const JSTokenLocation&, const Identifier*, int, int, int, int) { return 1; } + int createReturnStatement(const JSTokenLocation&, int, int, int, int, int, int, int) { return 1; } + int createBreakStatement(const JSTokenLocation&, int, int, int, int, int) { return 1; } + int createBreakStatement(const JSTokenLocation&, const Identifier*, int, int, int, int, int) { return 1; } + int createContinueStatement(const JSTokenLocation&, int, int, int, int, int) { return 1; } + int createContinueStatement(const JSTokenLocation&, const Identifier*, int, int, int, int, int) { return 1; } int createTryStatement(const JSTokenLocation&, int, const Identifier*, int, int, int, int) { return 1; } int createSwitchStatement(const JSTokenLocation&, int, int, int, int, int, int) { return 1; } int createWhileStatement(const JSTokenLocation&, int, int, int, int) { return 1; } - int createWithStatement(const JSTokenLocation&, int, int, int, int, int, int) { return 1; } + int createWithStatement(const JSTokenLocation&, int, int, int, int, int, int, int, int) { return 1; } int createDoWhileStatement(const JSTokenLocation&, int, int, int, int) { return 1; } - int createLabelStatement(const JSTokenLocation&, const Identifier*, int, int, int) { return 1; } - int createThrowStatement(const JSTokenLocation&, int, int, int, int, int) { return 1; } + int createLabelStatement(const JSTokenLocation&, const Identifier*, int, int, int, int, int) { return 1; } + int createThrowStatement(const JSTokenLocation&, int, int, int, int, int, int, int) { return 1; } int createDebugger(const JSTokenLocation&, int, int) { return 1; } int createConstStatement(const JSTokenLocation&, int, int, int) { return 1; } int appendConstDecl(const JSTokenLocation&, int, const Identifier*, int) { return 1; } - template <bool strict> Property createGetterOrSetterProperty(const JSTokenLocation&, PropertyNode::Type type, const Identifier* name, int, int, int, int, int, int) + template <bool strict> Property createGetterOrSetterProperty(const JSTokenLocation&, PropertyNode::Type type, const Identifier* name, int, int, int, int, int, int, int) { ASSERT(name); if (!strict) return Property(type); return Property(name, type); } - template <bool strict> Property createGetterOrSetterProperty(JSGlobalData* globalData, const JSTokenLocation&, PropertyNode::Type type, double name, int, int, int, int, int, int) + template <bool strict> Property createGetterOrSetterProperty(VM* vm, const JSTokenLocation&, PropertyNode::Type type, double name, int, int, int, int, int, int, int) { if (!strict) return Property(type); - return Property(&globalData->parserArena->identifierArena().makeNumericIdentifier(globalData, name), type); + return Property(&vm->parserArena->identifierArena().makeNumericIdentifier(vm, name), type); } void appendStatement(int, int) { } void addVar(const Identifier*, bool) { } int combineCommaNodes(const JSTokenLocation&, int, int) { return 1; } int evalCount() const { return 0; } - void appendBinaryExpressionInfo(int& operandStackDepth, int expr, int, int, int, bool) + void appendBinaryExpressionInfo(int& operandStackDepth, int expr, int, int, int, int, int, bool) { if (!m_topBinaryExpr) m_topBinaryExpr = expr; @@ -239,13 +240,14 @@ public: void operatorStackAppend(int& operatorStackDepth, int, int) { operatorStackDepth++; } int popOperandStack(int&) { int res = m_topBinaryExpr; m_topBinaryExpr = 0; return res; } - void appendUnaryToken(int& stackDepth, int tok, int) { stackDepth = 1; m_topUnaryToken = tok; } + void appendUnaryToken(int& stackDepth, int tok, int, int, int) { stackDepth = 1; m_topUnaryToken = tok; } int unaryTokenStackLastType(int&) { return m_topUnaryToken; } - int unaryTokenStackLastStart(int&) { return 0; } + unsigned unaryTokenStackLastStart(int&) { return 0; } + unsigned unaryTokenStackLastLineStartPosition(int&) { return 0; } void unaryTokenStackRemoveLast(int& stackDepth) { stackDepth = 0; } - void assignmentStackAppend(int, int, int, int, int, Operator) { } - int createAssignment(const JSTokenLocation&, int, int, int, int, int) { ASSERT_NOT_REACHED(); return 1; } + void assignmentStackAppend(int, int, int, int, int, int, int, Operator) { } + int createAssignment(const JSTokenLocation&, int, int, int, int, int) { RELEASE_ASSERT_NOT_REACHED(); return 1; } 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; } |