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 "Operations.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_lineNumber
= firstLine
;
58 m_lastLine
= lastLine
;
59 m_startOffset
= startOffset
;
60 m_lineStartOffset
= lineStartOffset
;
61 ASSERT(m_startOffset
>= m_lineStartOffset
);
64 // ------------------------------ SourceElements --------------------------------
66 void SourceElements::append(StatementNode
* statement
)
68 if (statement
->isEmptyStatement())
70 m_statements
.append(statement
);
73 StatementNode
* SourceElements::singleStatement() const
75 size_t size
= m_statements
.size();
76 return size
== 1 ? m_statements
[0] : 0;
79 // ------------------------------ ScopeNode -----------------------------
81 ScopeNode::ScopeNode(VM
* vm
, const JSTokenLocation
& startLocation
, const JSTokenLocation
& endLocation
, bool inStrictContext
)
82 : StatementNode(endLocation
)
83 , ParserArenaRefCounted(vm
)
84 , m_startLineNumber(startLocation
.line
)
85 , m_startStartOffset(startLocation
.startOffset
)
86 , m_startLineStartOffset(startLocation
.lineStartOffset
)
87 , m_features(inStrictContext
? StrictModeFeature
: NoFeatures
)
93 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
)
94 : StatementNode(endLocation
)
95 , ParserArenaRefCounted(vm
)
96 , m_startLineNumber(startLocation
.line
)
97 , m_startStartOffset(startLocation
.startOffset
)
98 , m_startLineStartOffset(startLocation
.lineStartOffset
)
99 , m_features(features
)
101 , m_numConstants(numConstants
)
102 , m_statements(children
)
104 m_arena
.swap(*vm
->parserArena
);
106 m_varStack
.swap(*varStack
);
108 m_functionStack
.swap(*funcStack
);
109 m_capturedVariables
.swap(capturedVariables
);
112 StatementNode
* ScopeNode::singleStatement() const
114 return m_statements
? m_statements
->singleStatement() : 0;
117 // ------------------------------ ProgramNode -----------------------------
119 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
)
120 : ScopeNode(vm
, startLocation
, endLocation
, source
, children
, varStack
, funcStack
, capturedVariables
, features
, numConstants
)
121 , m_startColumn(startColumn
)
125 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
)
127 RefPtr
<ProgramNode
> node
= new ProgramNode(vm
, startLocation
, endLocation
, startColumn
, children
, varStack
, funcStack
, capturedVariables
, source
, features
, numConstants
);
129 ASSERT(node
->m_arena
.last() == node
);
130 node
->m_arena
.removeLast();
131 ASSERT(!node
->m_arena
.contains(node
.get()));
133 return node
.release();
136 // ------------------------------ EvalNode -----------------------------
138 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
)
139 : ScopeNode(vm
, startLocation
, endLocation
, source
, children
, varStack
, funcStack
, capturedVariables
, features
, numConstants
)
143 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
)
145 RefPtr
<EvalNode
> node
= new EvalNode(vm
, startLocation
, endLocation
, children
, varStack
, funcStack
, capturedVariables
, source
, features
, numConstants
);
147 ASSERT(node
->m_arena
.last() == node
);
148 node
->m_arena
.removeLast();
149 ASSERT(!node
->m_arena
.contains(node
.get()));
151 return node
.release();
154 // ------------------------------ FunctionBodyNode -----------------------------
156 PassRefPtr
<FunctionParameters
> FunctionParameters::create(ParameterNode
* firstParameter
)
158 unsigned parameterCount
= 0;
159 for (ParameterNode
* parameter
= firstParameter
; parameter
; parameter
= parameter
->nextParam())
162 size_t objectSize
= sizeof(FunctionParameters
) - sizeof(void*) + sizeof(StringImpl
*) * parameterCount
;
163 void* slot
= fastMalloc(objectSize
);
164 return adoptRef(new (slot
) FunctionParameters(firstParameter
, parameterCount
));
167 FunctionParameters::FunctionParameters(ParameterNode
* firstParameter
, unsigned size
)
171 for (ParameterNode
* parameter
= firstParameter
; parameter
; parameter
= parameter
->nextParam())
172 new (&identifiers()[i
++]) Identifier(parameter
->ident());
175 FunctionParameters::~FunctionParameters()
177 for (unsigned i
= 0; i
< m_size
; ++i
)
178 identifiers()[i
].~Identifier();
181 inline FunctionBodyNode::FunctionBodyNode(VM
* vm
, const JSTokenLocation
& startLocation
, const JSTokenLocation
& endLocation
, unsigned startColumn
, bool inStrictContext
)
182 : ScopeNode(vm
, startLocation
, endLocation
, inStrictContext
)
183 , m_startColumn(startColumn
)
187 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
)
188 : ScopeNode(vm
, startLocation
, endLocation
, sourceCode
, children
, varStack
, funcStack
, capturedVariables
, features
, numConstants
)
189 , m_startColumn(startColumn
)
193 void FunctionBodyNode::finishParsing(const SourceCode
& source
, ParameterNode
* firstParameter
, const Identifier
& ident
, FunctionNameIsInScopeToggle functionNameIsInScopeToggle
)
196 finishParsing(FunctionParameters::create(firstParameter
), ident
, functionNameIsInScopeToggle
);
199 void FunctionBodyNode::finishParsing(PassRefPtr
<FunctionParameters
> parameters
, const Identifier
& ident
, FunctionNameIsInScopeToggle functionNameIsInScopeToggle
)
201 ASSERT(!source().isNull());
202 m_parameters
= parameters
;
204 m_functionNameIsInScopeToggle
= functionNameIsInScopeToggle
;
207 FunctionBodyNode
* FunctionBodyNode::create(VM
* vm
, const JSTokenLocation
& startLocation
, const JSTokenLocation
& endLocation
, unsigned startColumn
, bool inStrictContext
)
209 return new FunctionBodyNode(vm
, startLocation
, endLocation
, startColumn
, inStrictContext
);
212 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
)
214 RefPtr
<FunctionBodyNode
> node
= new FunctionBodyNode(vm
, startLocation
, endLocation
, startColumn
, children
, varStack
, funcStack
, capturedVariables
, sourceCode
, features
, numConstants
);
216 ASSERT(node
->m_arena
.last() == node
);
217 node
->m_arena
.removeLast();
218 ASSERT(!node
->m_arena
.contains(node
.get()));
220 return node
.release();