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 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 "JSStaticScopeObject.h"
37#include "LabelScope.h"
38#include "Lexer.h"
39#include "Operations.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(int firstLine, int lastLine)
56{
57    m_line = firstLine;
58    m_lastLine = lastLine;
59}
60
61// ------------------------------ SourceElements --------------------------------
62
63void SourceElements::append(StatementNode* statement)
64{
65    if (statement->isEmptyStatement())
66        return;
67    m_statements.append(statement);
68}
69
70StatementNode* SourceElements::singleStatement() const
71{
72    size_t size = m_statements.size();
73    return size == 1 ? m_statements[0] : 0;
74}
75
76// -----------------------------ScopeNodeData ---------------------------
77
78ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, int numConstants)
79    : m_numConstants(numConstants)
80    , m_statements(statements)
81{
82    m_arena.swap(arena);
83    if (varStack)
84        m_varStack.swap(*varStack);
85    if (funcStack)
86        m_functionStack.swap(*funcStack);
87    m_capturedVariables.swap(capturedVariables);
88}
89
90// ------------------------------ ScopeNode -----------------------------
91
92ScopeNode::ScopeNode(JSGlobalData* globalData, bool inStrictContext)
93    : StatementNode(globalData)
94    , ParserArenaRefCounted(globalData)
95    , m_features(inStrictContext ? StrictModeFeature : NoFeatures)
96{
97}
98
99ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants)
100    : StatementNode(globalData)
101    , ParserArenaRefCounted(globalData)
102    , m_data(adoptPtr(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, capturedVariables, numConstants)))
103    , m_features(features)
104    , m_source(source)
105{
106}
107
108StatementNode* ScopeNode::singleStatement() const
109{
110    return m_data->m_statements ? m_data->m_statements->singleStatement() : 0;
111}
112
113// ------------------------------ ProgramNode -----------------------------
114
115inline ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
116    : ScopeNode(globalData, source, children, varStack, funcStack, capturedVariables, features, numConstants)
117{
118}
119
120PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
121{
122    RefPtr<ProgramNode> node = new ProgramNode(globalData, children, varStack, funcStack, capturedVariables, source, features, numConstants);
123
124    ASSERT(node->data()->m_arena.last() == node);
125    node->data()->m_arena.removeLast();
126    ASSERT(!node->data()->m_arena.contains(node.get()));
127
128    return node.release();
129}
130
131// ------------------------------ EvalNode -----------------------------
132
133inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
134    : ScopeNode(globalData, source, children, varStack, funcStack, capturedVariables, features, numConstants)
135{
136}
137
138PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
139{
140    RefPtr<EvalNode> node = new EvalNode(globalData, children, varStack, funcStack, capturedVariables, source, features, numConstants);
141
142    ASSERT(node->data()->m_arena.last() == node);
143    node->data()->m_arena.removeLast();
144    ASSERT(!node->data()->m_arena.contains(node.get()));
145
146    return node.release();
147}
148
149// ------------------------------ FunctionBodyNode -----------------------------
150
151FunctionParameters::FunctionParameters(ParameterNode* firstParameter)
152{
153    for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
154        append(parameter->ident());
155}
156
157inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, bool inStrictContext)
158    : ScopeNode(globalData, inStrictContext)
159{
160}
161
162inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
163    : ScopeNode(globalData, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants)
164{
165}
166
167void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident)
168{
169    setSource(source);
170    finishParsing(FunctionParameters::create(firstParameter), ident);
171}
172
173void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters, const Identifier& ident)
174{
175    ASSERT(!source().isNull());
176    m_parameters = parameters;
177    m_ident = ident;
178}
179
180FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, bool inStrictContext)
181{
182    return new FunctionBodyNode(globalData, inStrictContext);
183}
184
185PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
186{
187    RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants);
188
189    ASSERT(node->data()->m_arena.last() == node);
190    node->data()->m_arena.removeLast();
191    ASSERT(!node->data()->m_arena.contains(node.get()));
192
193    return node.release();
194}
195
196} // namespace JSC
197