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