1 /* 2 * Copyright (C) 1999-2002 Harri Porten (porten (at) kde.org) 3 * Copyright (C) 2001 Peter Kelly (pmk (at) post.com) 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 5 * Copyright (C) 2007 Cameron Zwarich (cwzwarich (at) uwaterloo.ca) 6 * Copyright (C) 2007 Maks Orlovich 7 * Copyright (C) 2007 Eric Seidel <eric (at) 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 48 using namespace WTF; 49 50 namespace JSC { 51 52 53 // ------------------------------ StatementNode -------------------------------- 54 55 void StatementNode::setLoc(int firstLine, int lastLine) 56 { 57 m_line = firstLine; 58 m_lastLine = lastLine; 59 } 60 61 // ------------------------------ SourceElements -------------------------------- 62 63 void SourceElements::append(StatementNode* statement) 64 { 65 if (statement->isEmptyStatement()) 66 return; 67 m_statements.append(statement); 68 } 69 70 StatementNode* SourceElements::singleStatement() const 71 { 72 size_t size = m_statements.size(); 73 return size == 1 ? m_statements[0] : 0; 74 } 75 76 // -----------------------------ScopeNodeData --------------------------- 77 78 ScopeNodeData::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 92 ScopeNode::ScopeNode(JSGlobalData* globalData, bool inStrictContext) 93 : StatementNode(globalData) 94 , ParserArenaRefCounted(globalData) 95 , m_features(inStrictContext ? StrictModeFeature : NoFeatures) 96 { 97 } 98 99 ScopeNode::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 108 StatementNode* ScopeNode::singleStatement() const 109 { 110 return m_data->m_statements ? m_data->m_statements->singleStatement() : 0; 111 } 112 113 // ------------------------------ ProgramNode ----------------------------- 114 115 inline 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 120 PassRefPtr<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 133 inline 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 138 PassRefPtr<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 151 FunctionParameters::FunctionParameters(ParameterNode* firstParameter) 152 { 153 for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam()) 154 append(parameter->ident()); 155 } 156 157 inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, bool inStrictContext) 158 : ScopeNode(globalData, inStrictContext) 159 { 160 } 161 162 inline 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 167 void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident) 168 { 169 setSource(source); 170 finishParsing(FunctionParameters::create(firstParameter), ident); 171 } 172 173 void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters, const Identifier& ident) 174 { 175 ASSERT(!source().isNull()); 176 m_parameters = parameters; 177 m_ident = ident; 178 } 179 180 FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, bool inStrictContext) 181 { 182 return new FunctionBodyNode(globalData, inStrictContext); 183 } 184 185 PassRefPtr<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