1/*
2*  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3*  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4*  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
5*  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6*  Copyright (C) 2007 Maks Orlovich
7*  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
8*
9*  This library is free software; you can redistribute it and/or
10*  modify it under the terms of the GNU Library General Public
11*  License as published by the Free Software Foundation; either
12*  version 2 of the License, or (at your option) any later version.
13*
14*  This library is distributed in the hope that it will be useful,
15*  but WITHOUT ANY WARRANTY; without even the implied warranty of
16*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17*  Library General Public License for more details.
18*
19*  You should have received a copy of the GNU Library General Public License
20*  along with this library; see the file COPYING.LIB.  If not, write to
21*  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22*  Boston, MA 02110-1301, USA.
23*
24*/
25
26#include "config.h"
27#include "Nodes.h"
28#include "NodeConstructors.h"
29
30#include "BytecodeGenerator.h"
31#include "CallFrame.h"
32#include "Debugger.h"
33#include "JIT.h"
34#include "JSFunction.h"
35#include "JSGlobalObject.h"
36#include "JSNameScope.h"
37#include "LabelScope.h"
38#include "Lexer.h"
39#include "JSCInlines.h"
40#include "Parser.h"
41#include "PropertyNameArray.h"
42#include "RegExpObject.h"
43#include "SamplingTool.h"
44#include <wtf/Assertions.h>
45#include <wtf/RefCountedLeakCounter.h>
46#include <wtf/Threading.h>
47
48using namespace WTF;
49
50namespace JSC {
51
52
53// ------------------------------ StatementNode --------------------------------
54
55void StatementNode::setLoc(unsigned firstLine, unsigned lastLine, int startOffset, int lineStartOffset)
56{
57    m_lastLine = lastLine;
58    m_position = JSTextPosition(firstLine, startOffset, lineStartOffset);
59    ASSERT(m_position.offset >= m_position.lineStartOffset);
60}
61
62// ------------------------------ SourceElements --------------------------------
63
64void SourceElements::append(StatementNode* statement)
65{
66    if (statement->isEmptyStatement())
67        return;
68    m_statements.append(statement);
69}
70
71StatementNode* SourceElements::singleStatement() const
72{
73    size_t size = m_statements.size();
74    return size == 1 ? m_statements[0] : 0;
75}
76
77// ------------------------------ ScopeNode -----------------------------
78
79ScopeNode::ScopeNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, bool inStrictContext)
80    : StatementNode(endLocation)
81    , ParserArenaRefCounted(vm)
82    , m_startLineNumber(startLocation.line)
83    , m_startStartOffset(startLocation.startOffset)
84    , m_startLineStartOffset(startLocation.lineStartOffset)
85    , m_features(inStrictContext ? StrictModeFeature : NoFeatures)
86    , m_numConstants(0)
87    , m_statements(0)
88{
89}
90
91ScopeNode::ScopeNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants)
92    : StatementNode(endLocation)
93    , ParserArenaRefCounted(vm)
94    , m_startLineNumber(startLocation.line)
95    , m_startStartOffset(startLocation.startOffset)
96    , m_startLineStartOffset(startLocation.lineStartOffset)
97    , m_features(features)
98    , m_source(source)
99    , m_numConstants(numConstants)
100    , m_statements(children)
101{
102    m_arena.swap(*vm->parserArena);
103    if (varStack)
104        m_varStack.swap(*varStack);
105    if (funcStack)
106        m_functionStack.swap(*funcStack);
107    m_capturedVariables.swap(capturedVariables);
108}
109
110StatementNode* ScopeNode::singleStatement() const
111{
112    return m_statements ? m_statements->singleStatement() : 0;
113}
114
115// ------------------------------ ProgramNode -----------------------------
116
117inline ProgramNode::ProgramNode(VM* vm, 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)
118    : ScopeNode(vm, startLocation, endLocation, source, children, varStack, funcStack, capturedVariables, features, numConstants)
119    , m_startColumn(startColumn)
120    , m_endColumn(endColumn)
121{
122}
123
124PassRefPtr<ProgramNode> ProgramNode::create(VM* vm, 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)
125{
126    RefPtr<ProgramNode> node = new ProgramNode(vm, startLocation, endLocation, startColumn, endColumn, children, varStack, funcStack,  capturedVariables, source, features, numConstants);
127
128    ASSERT(node->m_arena.last() == node);
129    node->m_arena.removeLast();
130    ASSERT(!node->m_arena.contains(node.get()));
131
132    return node.release();
133}
134
135
136void ProgramNode::setClosedVariables(Vector<RefPtr<StringImpl>>&& closedVariables)
137{
138    m_closedVariables = WTF::move(closedVariables);
139}
140
141// ------------------------------ EvalNode -----------------------------
142
143inline EvalNode::EvalNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned endColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
144    : ScopeNode(vm, startLocation, endLocation, source, children, varStack, funcStack, capturedVariables, features, numConstants)
145    , m_endColumn(endColumn)
146{
147}
148
149PassRefPtr<EvalNode> EvalNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned, unsigned endColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
150{
151    RefPtr<EvalNode> node = new EvalNode(vm, startLocation, endLocation, endColumn, children, varStack, funcStack, capturedVariables, source, features, numConstants);
152
153    ASSERT(node->m_arena.last() == node);
154    node->m_arena.removeLast();
155    ASSERT(!node->m_arena.contains(node.get()));
156
157    return node.release();
158}
159
160// ------------------------------ FunctionBodyNode -----------------------------
161
162PassRefPtr<FunctionParameters> FunctionParameters::create(ParameterNode* firstParameter)
163{
164    unsigned parameterCount = 0;
165    for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
166        ++parameterCount;
167
168    size_t objectSize = sizeof(FunctionParameters) - sizeof(void*) + sizeof(DeconstructionPatternNode*) * parameterCount;
169    void* slot = fastMalloc(objectSize);
170    return adoptRef(new (slot) FunctionParameters(firstParameter, parameterCount));
171}
172
173FunctionParameters::FunctionParameters(ParameterNode* firstParameter, unsigned size)
174    : m_size(size)
175{
176    unsigned i = 0;
177    for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam()) {
178        auto pattern = parameter->pattern();
179        pattern->ref();
180        patterns()[i++] = pattern;
181    }
182}
183
184FunctionParameters::~FunctionParameters()
185{
186    for (unsigned i = 0; i < m_size; ++i)
187        patterns()[i]->deref();
188}
189
190inline FunctionBodyNode::FunctionBodyNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, bool inStrictContext)
191    : ScopeNode(vm, startLocation, endLocation, inStrictContext)
192    , m_startColumn(startColumn)
193    , m_endColumn(endColumn)
194{
195}
196
197inline FunctionBodyNode::FunctionBodyNode(VM* vm, 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)
198    : ScopeNode(vm, startLocation, endLocation, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants)
199    , m_startColumn(startColumn)
200    , m_endColumn(endColumn)
201{
202}
203
204void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident, enum FunctionMode functionMode)
205{
206    setSource(source);
207    finishParsing(FunctionParameters::create(firstParameter), ident, functionMode);
208}
209
210void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters, const Identifier& ident, enum FunctionMode functionMode)
211{
212    ASSERT(!source().isNull());
213    m_parameters = parameters;
214    m_ident = ident;
215    m_functionMode = functionMode;
216}
217
218FunctionBodyNode* FunctionBodyNode::create(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, bool inStrictContext)
219{
220    return new FunctionBodyNode(vm, startLocation, endLocation, startColumn, endColumn, inStrictContext);
221}
222
223PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(VM* vm, 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)
224{
225    RefPtr<FunctionBodyNode> node = new FunctionBodyNode(vm, startLocation, endLocation, startColumn, endColumn , children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants);
226
227    ASSERT(node->m_arena.last() == node);
228    node->m_arena.removeLast();
229    ASSERT(!node->m_arena.contains(node.get()));
230
231    return node.release();
232}
233
234void FunctionBodyNode::setEndPosition(JSTextPosition position)
235{
236    m_lastLine = position.line;
237    m_endColumn = position.offset - position.lineStartOffset;
238}
239
240} // namespace JSC
241