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