Avoid heap allocating the root scope chain node for eval and closure free functions
[WebKit.git] / JavaScriptCore / kjs / ExecState.cpp
1 // -*- mode: c++; c-basic-offset: 4 -*-
2 /*
3  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
4  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
5  *  Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Library General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Library General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Library General Public License
18  *  along with this library; see the file COPYING.LIB.  If not, write to
19  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  *  Boston, MA 02110-1301, USA.
21  *
22  */
23
24 #include "config.h"
25 #include "ExecState.h"
26
27 #include "Activation.h"
28 #include "JSGlobalObject.h"
29 #include "function.h"
30 #include "internal.h"
31 #include "scope_chain_mark.h"
32
33 namespace KJS {
34
35 static inline List* globalEmptyList()
36 {
37     static List staticEmptyList;
38     return &staticEmptyList;
39 }
40
41 // ECMA 10.2
42
43 // The constructor for the globalExec pseudo-ExecState
44 inline ExecState::ExecState(JSGlobalObject* globalObject)
45     : m_globalObject(globalObject)
46     , m_exception(0)
47     , m_propertyNames(CommonIdentifiers::shared())
48     , m_emptyList(globalEmptyList())
49     , m_callingExec(0)
50     , m_scopeNode(0)
51     , m_function(0)
52     , m_arguments(0)
53     , m_activation(0)
54     , m_localStorage(&globalObject->localStorage())
55     , m_inlineScopeChainNode(0, 0)
56     , m_variableObject(globalObject)
57     , m_thisValue(globalObject)
58     , m_iterationDepth(0)
59     , m_switchDepth(0) 
60     , m_codeType(GlobalCode)
61 {
62     m_scopeChain.push(globalObject);
63 }
64
65 inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* /*thisObject*/, ProgramNode* programNode)
66     : m_globalObject(globalObject)
67     , m_exception(0)
68     , m_propertyNames(CommonIdentifiers::shared())
69     , m_emptyList(globalEmptyList())
70     , m_callingExec(0)
71     , m_scopeNode(programNode)
72     , m_function(0)
73     , m_arguments(0)
74     , m_activation(0)
75     , m_localStorage(&globalObject->localStorage())
76     , m_inlineScopeChainNode(0, 0)
77     , m_variableObject(globalObject)
78     , m_thisValue(globalObject)
79     , m_iterationDepth(0)
80     , m_switchDepth(0) 
81     , m_codeType(GlobalCode)
82 {
83     // FIXME: This function ignores the "thisObject" parameter, which means that the API for evaluating
84     // a script with a this object that's not the same as the global object is broken, and probably
85     // has been for some time.
86     ASSERT(m_scopeNode);
87     m_scopeChain.push(globalObject);
88 }
89
90 inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject, EvalNode* evalNode, ExecState* callingExec, const ScopeChain& scopeChain, JSVariableObject* variableObject)
91     : m_globalObject(globalObject)
92     , m_exception(0)
93     , m_propertyNames(callingExec->m_propertyNames)
94     , m_emptyList(callingExec->m_emptyList)
95     , m_callingExec(callingExec)
96     , m_scopeNode(evalNode)
97     , m_function(0)
98     , m_arguments(0)
99     , m_activation(0)
100     , m_localStorage(callingExec->m_localStorage)
101     , m_scopeChain(scopeChain)
102     , m_inlineScopeChainNode(0, 0)
103     , m_variableObject(variableObject)
104     , m_thisValue(thisObject)
105     , m_iterationDepth(0)
106     , m_switchDepth(0) 
107     , m_codeType(EvalCode)
108 {    
109     ASSERT(m_scopeNode);
110 }
111
112 inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject, 
113          FunctionBodyNode* functionBodyNode, ExecState* callingExec,
114          FunctionImp* func, const List& args)
115     : m_globalObject(globalObject)
116     , m_exception(0)
117     , m_propertyNames(callingExec->m_propertyNames)
118     , m_emptyList(callingExec->m_emptyList)
119     , m_callingExec(callingExec)
120     , m_scopeNode(functionBodyNode)
121     , m_function(func)
122     , m_arguments(&args)
123     , m_scopeChain(func->scope())
124     , m_inlineScopeChainNode(0, 0)
125     , m_thisValue(thisObject)
126     , m_iterationDepth(0)
127     , m_switchDepth(0) 
128     , m_codeType(FunctionCode)
129 {
130     ASSERT(m_scopeNode);
131
132     ActivationImp* activation = globalObject->pushActivation(this);
133     m_activation = activation;
134     m_localStorage = &activation->localStorage();
135     m_variableObject = activation;
136     if (functionBodyNode->usesEval() || functionBodyNode->needsClosure())
137         m_scopeChain.push(activation);
138     else {
139         m_inlineScopeChainNode.object = activation;
140         // The ScopeChain will ref this node itself, so we don't need to worry about
141         // anything trying to delete our scopenode
142         m_scopeChain.push(&m_inlineScopeChainNode);
143     }
144 }
145
146 inline ExecState::~ExecState()
147 {
148 }
149
150 JSGlobalObject* ExecState::lexicalGlobalObject() const
151 {
152     JSObject* object = m_scopeChain.bottom();
153     if (object && object->isGlobalObject())
154         return static_cast<JSGlobalObject*>(object);
155     return m_globalObject;
156 }
157
158 GlobalExecState::GlobalExecState(JSGlobalObject* globalObject)
159     : ExecState(globalObject)
160 {
161 }
162
163 GlobalExecState::~GlobalExecState()
164 {
165 }
166
167 InterpreterExecState::InterpreterExecState(JSGlobalObject* globalObject, JSObject* thisObject, ProgramNode* programNode)
168     : ExecState(globalObject, thisObject, programNode)
169 {
170     m_globalObject->activeExecStates().append(this);
171 }
172
173 InterpreterExecState::~InterpreterExecState()
174 {
175     ASSERT(m_globalObject->activeExecStates().last() == this);
176     m_globalObject->activeExecStates().removeLast();
177 }
178
179 EvalExecState::EvalExecState(JSGlobalObject* globalObject, JSObject* thisObj, EvalNode* evalNode, ExecState* callingExec, const ScopeChain& scopeChain, JSVariableObject* variableObject)
180     : ExecState(globalObject, thisObj, evalNode, callingExec, scopeChain, variableObject)
181 {
182     m_globalObject->activeExecStates().append(this);
183 }
184
185 EvalExecState::~EvalExecState()
186 {
187     ASSERT(m_globalObject->activeExecStates().last() == this);
188     m_globalObject->activeExecStates().removeLast();
189 }
190
191 FunctionExecState::FunctionExecState(JSGlobalObject* globalObject, JSObject* thisObject, 
192          FunctionBodyNode* functionBodyNode, ExecState* callingExec,
193          FunctionImp* func, const List& args)
194     : ExecState(globalObject, thisObject, functionBodyNode, callingExec, func, args)
195 {
196     m_globalObject->activeExecStates().append(this);
197 }
198
199 FunctionExecState::~FunctionExecState()
200 {
201     ASSERT(m_globalObject->activeExecStates().last() == this);
202     m_globalObject->activeExecStates().removeLast();
203
204     if (m_activation->needsPop())
205         m_globalObject->popActivation();
206 }
207
208 } // namespace KJS