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>
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.
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.
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.
28 #include "NodeConstructors.h"
30 #include "BytecodeGenerator.h"
31 #include "CallFrame.h"
34 #include "JSFunction.h"
35 #include "JSGlobalObject.h"
36 #include "JSNameScope.h"
37 #include "LabelScope.h"
39 #include "JSCInlines.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>
53 // ------------------------------ StatementNode --------------------------------
55 void StatementNode::setLoc(unsigned firstLine
, unsigned lastLine
, int startOffset
, int lineStartOffset
)
57 m_lastLine
= lastLine
;
58 m_position
= JSTextPosition(firstLine
, startOffset
, lineStartOffset
);
59 ASSERT(m_position
.offset
>= m_position
.lineStartOffset
);
62 // ------------------------------ SourceElements --------------------------------
64 void SourceElements::append(StatementNode
* statement
)
66 if (statement
->isEmptyStatement())
68 m_statements
.append(statement
);
71 StatementNode
* SourceElements::singleStatement() const
73 size_t size
= m_statements
.size();
74 return size
== 1 ? m_statements
[0] : 0;
77 // ------------------------------ ScopeNode -----------------------------
79 ScopeNode::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
)
91 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
)
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
)
99 , m_numConstants(numConstants
)
100 , m_statements(children
)
102 m_arena
.swap(*vm
->parserArena
);
104 m_varStack
.swap(*varStack
);
106 m_functionStack
.swap(*funcStack
);
107 m_capturedVariables
.swap(capturedVariables
);
110 StatementNode
* ScopeNode::singleStatement() const
112 return m_statements
? m_statements
->singleStatement() : 0;
115 // ------------------------------ ProgramNode -----------------------------
117 inline 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
)
124 PassRefPtr
<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
)
126 RefPtr
<ProgramNode
> node
= new ProgramNode(vm
, startLocation
, endLocation
, startColumn
, endColumn
, children
, varStack
, funcStack
, capturedVariables
, source
, features
, numConstants
);
128 ASSERT(node
->m_arena
.last() == node
);
129 node
->m_arena
.removeLast();
130 ASSERT(!node
->m_arena
.contains(node
.get()));
132 return node
.release();
136 void ProgramNode::setClosedVariables(Vector
<RefPtr
<StringImpl
>>&& closedVariables
)
138 m_closedVariables
= WTF::move(closedVariables
);
141 // ------------------------------ EvalNode -----------------------------
143 inline 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
)
149 PassRefPtr
<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
)
151 RefPtr
<EvalNode
> node
= new EvalNode(vm
, startLocation
, endLocation
, endColumn
, children
, varStack
, funcStack
, capturedVariables
, source
, features
, numConstants
);
153 ASSERT(node
->m_arena
.last() == node
);
154 node
->m_arena
.removeLast();
155 ASSERT(!node
->m_arena
.contains(node
.get()));
157 return node
.release();
160 // ------------------------------ FunctionBodyNode -----------------------------
162 PassRefPtr
<FunctionParameters
> FunctionParameters::create(ParameterNode
* firstParameter
)
164 unsigned parameterCount
= 0;
165 for (ParameterNode
* parameter
= firstParameter
; parameter
; parameter
= parameter
->nextParam())
168 size_t objectSize
= sizeof(FunctionParameters
) - sizeof(void*) + sizeof(DeconstructionPatternNode
*) * parameterCount
;
169 void* slot
= fastMalloc(objectSize
);
170 return adoptRef(new (slot
) FunctionParameters(firstParameter
, parameterCount
));
173 FunctionParameters::FunctionParameters(ParameterNode
* firstParameter
, unsigned size
)
177 for (ParameterNode
* parameter
= firstParameter
; parameter
; parameter
= parameter
->nextParam()) {
178 auto pattern
= parameter
->pattern();
180 patterns()[i
++] = pattern
;
184 FunctionParameters::~FunctionParameters()
186 for (unsigned i
= 0; i
< m_size
; ++i
)
187 patterns()[i
]->deref();
190 inline 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
)
197 inline 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
)
204 void FunctionBodyNode::finishParsing(const SourceCode
& source
, ParameterNode
* firstParameter
, const Identifier
& ident
, enum FunctionMode functionMode
)
207 finishParsing(FunctionParameters::create(firstParameter
), ident
, functionMode
);
210 void FunctionBodyNode::finishParsing(PassRefPtr
<FunctionParameters
> parameters
, const Identifier
& ident
, enum FunctionMode functionMode
)
212 ASSERT(!source().isNull());
213 m_parameters
= parameters
;
215 m_functionMode
= functionMode
;
218 FunctionBodyNode
* FunctionBodyNode::create(VM
* vm
, const JSTokenLocation
& startLocation
, const JSTokenLocation
& endLocation
, unsigned startColumn
, unsigned endColumn
, bool inStrictContext
)
220 return new FunctionBodyNode(vm
, startLocation
, endLocation
, startColumn
, endColumn
, inStrictContext
);
223 PassRefPtr
<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
)
225 RefPtr
<FunctionBodyNode
> node
= new FunctionBodyNode(vm
, startLocation
, endLocation
, startColumn
, endColumn
, children
, varStack
, funcStack
, capturedVariables
, sourceCode
, features
, numConstants
);
227 ASSERT(node
->m_arena
.last() == node
);
228 node
->m_arena
.removeLast();
229 ASSERT(!node
->m_arena
.contains(node
.get()));
231 return node
.release();
234 void FunctionBodyNode::setEndPosition(JSTextPosition position
)
236 m_lastLine
= position
.line
;
237 m_endColumn
= position
.offset
- position
.lineStartOffset
;