/*
* 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>
#include "Nodes.h"
#include "NodeConstructors.h"
-#include "BytecodeGenerator.h"
#include "CallFrame.h"
#include "Debugger.h"
#include "JIT.h"
#include "JSFunction.h"
#include "JSGlobalObject.h"
-#include "JSStaticScopeObject.h"
+#include "JSNameScope.h"
#include "LabelScope.h"
#include "Lexer.h"
-#include "Operations.h"
+#include "JSCInlines.h"
#include "Parser.h"
#include "PropertyNameArray.h"
#include "RegExpObject.h"
// ------------------------------ StatementNode --------------------------------
-void StatementNode::setLoc(int firstLine, int lastLine)
+void StatementNode::setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset)
{
- m_line = firstLine;
m_lastLine = lastLine;
+ m_position = JSTextPosition(firstLine, startOffset, lineStartOffset);
+ ASSERT(m_position.offset >= m_position.lineStartOffset);
}
// ------------------------------ SourceElements --------------------------------
{
if (statement->isEmptyStatement())
return;
- m_statements.append(statement);
+
+ if (!m_head) {
+ m_head = statement;
+ m_tail = statement;
+ return;
+ }
+
+ m_tail->setNext(statement);
+ m_tail = statement;
}
StatementNode* SourceElements::singleStatement() const
{
- size_t size = m_statements.size();
- return size == 1 ? m_statements[0] : 0;
-}
-
-// -----------------------------ScopeNodeData ---------------------------
-
-ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, int numConstants)
- : m_numConstants(numConstants)
- , m_statements(statements)
-{
- m_arena.swap(arena);
- if (varStack)
- m_varStack.swap(*varStack);
- if (funcStack)
- m_functionStack.swap(*funcStack);
- m_capturedVariables.swap(capturedVariables);
+ return m_head == m_tail ? m_head : nullptr;
}
// ------------------------------ ScopeNode -----------------------------
-ScopeNode::ScopeNode(JSGlobalData* globalData, bool inStrictContext)
- : StatementNode(globalData)
- , ParserArenaRefCounted(globalData)
+ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, bool inStrictContext)
+ : StatementNode(endLocation)
+ , ParserArenaRoot(parserArena)
+ , 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 SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants)
- : StatementNode(globalData)
- , ParserArenaRefCounted(globalData)
- , m_data(adoptPtr(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, capturedVariables, numConstants)))
+ScopeNode::ScopeNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, const SourceCode& source, SourceElements* children, VarStack& varStack, FunctionStack& funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants)
+ : StatementNode(endLocation)
+ , ParserArenaRoot(parserArena)
+ , 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_varStack.swap(varStack);
+ m_functionStack.swap(funcStack);
+ m_capturedVariables.swap(capturedVariables);
}
StatementNode* ScopeNode::singleStatement() const
{
- return m_data->m_statements ? m_data->m_statements->singleStatement() : 0;
+ return m_statements ? m_statements->singleStatement() : 0;
}
// ------------------------------ ProgramNode -----------------------------
-inline ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
- : ScopeNode(globalData, source, children, varStack, funcStack, capturedVariables, features, numConstants)
+ProgramNode::ProgramNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VarStack& varStack, FunctionStack& funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
+ : ScopeNode(parserArena, startLocation, endLocation, source, children, varStack, funcStack, capturedVariables, features, numConstants)
+ , m_startColumn(startColumn)
+ , m_endColumn(endColumn)
{
}
-PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
+void ProgramNode::setClosedVariables(Vector<RefPtr<UniquedStringImpl>>&& closedVariables)
{
- RefPtr<ProgramNode> node = new ProgramNode(globalData, children, varStack, funcStack, capturedVariables, source, features, numConstants);
-
- ASSERT(node->data()->m_arena.last() == node);
- node->data()->m_arena.removeLast();
- ASSERT(!node->data()->m_arena.contains(node.get()));
-
- return node.release();
+ m_closedVariables = WTF::move(closedVariables);
}
// ------------------------------ EvalNode -----------------------------
-inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
- : ScopeNode(globalData, source, children, varStack, funcStack, capturedVariables, features, numConstants)
-{
-}
-
-PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
+EvalNode::EvalNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned, unsigned endColumn, SourceElements* children, VarStack& varStack, FunctionStack& funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
+ : ScopeNode(parserArena, startLocation, endLocation, source, children, varStack, funcStack, capturedVariables, features, numConstants)
+ , m_endColumn(endColumn)
{
- RefPtr<EvalNode> node = new EvalNode(globalData, children, varStack, funcStack, capturedVariables, source, features, numConstants);
-
- ASSERT(node->data()->m_arena.last() == node);
- node->data()->m_arena.removeLast();
- ASSERT(!node->data()->m_arena.contains(node.get()));
-
- return node.release();
}
// ------------------------------ FunctionBodyNode -----------------------------
-FunctionParameters::FunctionParameters(ParameterNode* firstParameter)
+Ref<FunctionParameters> FunctionParameters::create(ParameterNode* firstParameter)
{
+ unsigned parameterCount = 0;
for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
- append(parameter->ident());
+ ++parameterCount;
+
+ size_t objectSize = sizeof(FunctionParameters) - sizeof(void*) + sizeof(DestructuringPatternNode*) * parameterCount;
+ void* slot = fastMalloc(objectSize);
+ return adoptRef(*new (slot) FunctionParameters(firstParameter, parameterCount));
}
-inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, bool inStrictContext)
- : ScopeNode(globalData, inStrictContext)
+FunctionParameters::FunctionParameters(ParameterNode* firstParameter, unsigned size)
+ : m_size(size)
{
+ unsigned i = 0;
+ for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam()) {
+ auto pattern = parameter->pattern();
+ pattern->ref();
+ patterns()[i++] = pattern;
+ }
}
-inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
- : ScopeNode(globalData, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants)
+FunctionParameters::~FunctionParameters()
{
+ for (unsigned i = 0; i < m_size; ++i)
+ patterns()[i]->deref();
}
-void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident)
+FunctionBodyNode::FunctionBodyNode(
+ ParserArena&, const JSTokenLocation& startLocation,
+ const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn,
+ int functionKeywordStart, int functionNameStart, int parametersStart,
+ bool isInStrictContext, ConstructorKind constructorKind)
+ : StatementNode(endLocation)
+ , m_startColumn(startColumn)
+ , m_endColumn(endColumn)
+ , m_functionKeywordStart(functionKeywordStart)
+ , m_functionNameStart(functionNameStart)
+ , m_parametersStart(parametersStart)
+ , m_startStartOffset(startLocation.startOffset)
+ , m_isInStrictContext(isInStrictContext)
+ , m_constructorKind(static_cast<unsigned>(constructorKind))
{
- setSource(source);
- finishParsing(FunctionParameters::create(firstParameter), ident);
+ ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind));
}
-void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters, const Identifier& ident)
+void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident, enum FunctionMode functionMode)
{
- ASSERT(!source().isNull());
- m_parameters = parameters;
+ m_source = source;
+ m_parameters = FunctionParameters::create(firstParameter);
m_ident = ident;
+ m_functionMode = functionMode;
}
-FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, bool inStrictContext)
+void FunctionBodyNode::setEndPosition(JSTextPosition position)
{
- return new FunctionBodyNode(globalData, inStrictContext);
+ m_lastLine = position.line;
+ m_endColumn = position.offset - position.lineStartOffset;
}
-PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
-{
- RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants);
+// ------------------------------ FunctionNode -----------------------------
- ASSERT(node->data()->m_arena.last() == node);
- node->data()->m_arena.removeLast();
- ASSERT(!node->data()->m_arena.contains(node.get()));
+FunctionNode::FunctionNode(ParserArena& parserArena, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VarStack& varStack, FunctionStack& funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
+ : ScopeNode(parserArena, startLocation, endLocation, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants)
+ , m_startColumn(startColumn)
+ , m_endColumn(endColumn)
+{
+}
- return node.release();
+void FunctionNode::finishParsing(PassRefPtr<FunctionParameters> parameters, const Identifier& ident, enum FunctionMode functionMode)
+{
+ ASSERT(!source().isNull());
+ m_parameters = parameters;
+ m_ident = ident;
+ m_functionMode = functionMode;
}
} // namespace JSC