summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/parser
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2013-09-13 12:51:20 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-19 20:50:05 +0200
commitd441d6f39bb846989d95bcf5caf387b42414718d (patch)
treee367e64a75991c554930278175d403c072de6bb8 /Source/JavaScriptCore/parser
parent0060b2994c07842f4c59de64b5e3e430525c4b90 (diff)
downloadqtwebkit-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')
-rw-r--r--Source/JavaScriptCore/parser/ASTBuilder.h515
-rw-r--r--Source/JavaScriptCore/parser/Lexer.cpp173
-rw-r--r--Source/JavaScriptCore/parser/Lexer.h105
-rw-r--r--Source/JavaScriptCore/parser/NodeConstructors.h158
-rw-r--r--Source/JavaScriptCore/parser/Nodes.cpp89
-rw-r--r--Source/JavaScriptCore/parser/Nodes.h414
-rw-r--r--Source/JavaScriptCore/parser/Parser.cpp321
-rw-r--r--Source/JavaScriptCore/parser/Parser.h239
-rw-r--r--Source/JavaScriptCore/parser/ParserArena.h26
-rw-r--r--Source/JavaScriptCore/parser/ParserError.h110
-rw-r--r--Source/JavaScriptCore/parser/ParserModes.h21
-rw-r--r--Source/JavaScriptCore/parser/ParserTokens.h40
-rw-r--r--Source/JavaScriptCore/parser/ResultType.h5
-rw-r--r--Source/JavaScriptCore/parser/SourceCode.h34
-rw-r--r--Source/JavaScriptCore/parser/SourceProvider.cpp62
-rw-r--r--Source/JavaScriptCore/parser/SourceProvider.h36
-rw-r--r--Source/JavaScriptCore/parser/SourceProviderCache.cpp9
-rw-r--r--Source/JavaScriptCore/parser/SourceProviderCache.h9
-rw-r--r--Source/JavaScriptCore/parser/SourceProviderCacheItem.h100
-rw-r--r--Source/JavaScriptCore/parser/SyntaxChecker.h74
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; }