KJS

ExecState.cpp
1 /*
2  * This file is part of the KDE libraries
3  * Copyright (C) 1999-2001 Harri Porten ([email protected])
4  * Copyright (C) 2001 Peter Kelly ([email protected])
5  * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
6  * Copyright (C) 2008 Maksim Orlovich ([email protected])
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB. If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  */
24 
25 #include "ExecState.h"
26 #include "function.h"
27 #include "scriptfunction.h"
28 #include "internal.h"
29 #include "nodes.h"
30 #include "debugger.h"
31 
32 namespace KJS
33 {
34 
36 {
37  JSObject *outerScope = scopeChain().bottom();
38  assert(outerScope->isGlobalObject());
39 
40  Interpreter *result = static_cast<JSGlobalObject *>(outerScope)->interpreter();
41 
42  if (!result) {
43  return dynamicInterpreter();
44  }
45 
46  return result;
47 }
48 
49 void ExecState::markSelf()
50 {
51  if (m_codeType != FunctionCode && m_localStore) {
52  //### some code dupe here with JSVariableObject::mark. Not sure how to best
53  // restructure.
54 
55  // Note: the m_localStore check is needed here, since for non-function code,
56  // we may create function object in declaration elaboration stage, before
57  // compilation and set up of this
58  size_t size = m_localStoreSize;
59  LocalStorageEntry *entries = m_localStore;
60 
61  for (size_t i = 0; i < size; ++i) {
62  JSValue *value = entries[i].val.valueVal;
63  if (!(entries[i].attributes & DontMark) && !JSValue::marked(value)) {
64  JSValue::mark(value);
65  }
66  }
67  }
68 
69  for (size_t i = 0; i < m_deferredCompletions.size(); ++i) {
70  JSValue *e = m_deferredCompletions[i].value();
71  if (e && !JSValue::marked(e)) {
72  JSValue::mark(e);
73  }
74  }
75 
76  JSValue *e = m_completion.value();
77  if (e && !JSValue::marked(e)) {
78  JSValue::mark(e);
79  }
80 
81  scope.mark();
82 
83  // Propagate up to other eval chains..
84  if (m_savedExec && m_savedExec != m_callingExec) {
85  ASSERT(m_savedExec != this);
86  m_savedExec->mark();
87  }
88 }
89 
90 void ExecState::mark()
91 {
92  for (ExecState *exec = this; exec; exec = exec->m_callingExec) {
93  exec->markSelf();
94  }
95 }
96 
98  m_interpreter(intp),
99  m_propertyNames(CommonIdentifiers::shared()),
100  m_callingExec(nullptr),
101  m_savedExec(save),
102  m_currentBody(nullptr),
103  m_function(nullptr),
104  m_localStore(nullptr),
105  m_pcBase(nullptr),
106  m_pc(nullptr),
107  m_machineLocalStore(nullptr)
108 {
109  /**
110  The reason we need m_savedExec and can't just be content with m_callingExec is two-fold.
111  First of all, in many cases KHTML (and ktranscript) invoke functions such as event handlers
112  on globalExec. When that happens, we still need to be able to mark the previous call-chain.
113  Also, it is possible for the client to call Interpreter::evaluate again; and we still
114  need to mark things from the outside when that happens
115  */
116 
117  if (m_callingExec && m_savedExec && m_callingExec != m_savedExec) {
118  assert(m_callingExec == intp->globalExec());
119  }
120  m_interpreter->setExecState(this);
121 }
122 
123 ExecState::~ExecState()
124 {
125  m_interpreter->setExecState(m_savedExec);
126 }
127 
128 void ExecState::pushExceptionHandler(HandlerType type, Addr addr)
129 {
130  m_exceptionHandlers.append(ExceptionHandler(type, addr));
131 }
132 
133 void ExecState::popExceptionHandler()
134 {
135  m_exceptionHandlers.removeLast();
136 }
137 
139 {
140  // First, unwind and get the old completion..
141  ASSERT(m_exceptionHandlers.last().type == RemoveDeferred);
142  popExceptionHandler();
143  Completion comp = m_deferredCompletions.last();
144  m_deferredCompletions.removeLast();
145 
146  // Now, our behavior behaves on whether we're inside an another
147  // try..finally or not. If we're, we must route even
148  // continue/break/return completions via the EH machinery;
149  // if not, we execute them directly
150  if (comp.complType() == Normal) {
151  // We just straight fell into 'finally'. Nothing fancy to do.
152  return nullptr;
153  }
154 
155  if (comp.complType() == Throw || insideTryFinally) {
156  setAbruptCompletion(comp);
157  } else {
158  if (comp.complType() == ReturnValue) {
159  return comp.value();
160  } else {
161  assert(comp.complType() == Break || comp.complType() == Continue);
162  *m_pc = m_pcBase + comp.target();
163  }
164  }
165 
166  return nullptr;
167 }
168 
170 {
171  if (e) {
172  setAbruptCompletion(Completion(Throw, e));
173  } else {
174  clearException();
175  }
176 }
177 
179 {
180  // If we already had an exception, merely update the object, to permit
181  // users to refine the exception, being careful not to double-unwind.
182  // However, warn about it in debug builds.
183  if (hadException()) {
184 #ifndef NDEBUG
185  printInfo(this, "warning: overriding already set exception ", m_completion.value());
186  printInfo(this, "with ", comp.value());
187 #endif
188 
189  m_completion = comp;
190  return;
191  }
192 
193  // Trace to debugger if needed.
194  Debugger *dbg = dynamicInterpreter()->debugger();
195  if (dbg && comp.complType() == Throw) {
196  dbg->reportException(this, comp.value());
197  }
198 
199  m_completion = comp;
200 
201  while (!m_exceptionHandlers.isEmpty()) {
202  switch (m_exceptionHandlers.last().type) {
203  case JumpToCatch:
204  *m_pc = m_pcBase + m_exceptionHandlers.last().dest;
205  m_exceptionHandlers.removeLast();
206  return; // done handling it
207  case PopScope:
208  popScope();
209  m_exceptionHandlers.removeLast();
210  continue; // get the next handler
211  case RemoveDeferred:
212  m_deferredCompletions.removeLast();
213  m_exceptionHandlers.removeLast();
214  continue; // get the next handler
215  case Silent:
216  // Exception blocked by tracing code. nothing to do.
217  return;
218  }
219  }
220 }
221 
222 void ExecState::quietUnwind(int depth)
223 {
224  ASSERT(m_exceptionHandlers.size() >= size_t(depth));
225  for (int e = 0; e < depth; ++e) {
226  HandlerType type = m_exceptionHandlers.last().type;
227  m_exceptionHandlers.removeLast();
228 
229  switch (type) {
230  case JumpToCatch:
231  break; //Nothing to do here!
232  case PopScope:
233  popScope();
234  break;
235  case RemoveDeferred:
236  m_deferredCompletions.removeLast();
237  break;
238  case Silent:
239  ASSERT(0); // Should not happen in the middle of the code.
240  break;
241  }
242  }
243 }
244 
245 GlobalExecState::GlobalExecState(Interpreter *intp, JSGlobalObject *glob): ExecState(intp, nullptr /* nothing else constructed yet*/)
246 {
247  scope.push(glob);
248  m_codeType = GlobalCode;
249  m_variable = glob;
250  m_thisVal = glob;
251 }
252 
253 InterpreterExecState::InterpreterExecState(Interpreter *intp, JSGlobalObject *glob,
254  JSObject *thisObject, ProgramNode *body):
255  ExecState(intp, intp->execState())
256 {
257  m_currentBody = body;
258  scope.push(glob);
259  m_codeType = GlobalCode;
260  m_variable = glob;
261  // Per 10.2.1, we should use the global object here, but
262  // Interpreter::evaluate permits it to be overridden, e.g. for LiveConnect.
263  m_thisVal = thisObject;
264 }
265 
266 EvalExecState::EvalExecState(Interpreter *intp, JSGlobalObject *glob,
267  ProgramNode *body, ExecState *callingExecState):
268  ExecState(intp, intp->execState())
269 {
270  m_currentBody = body;
271  m_codeType = EvalCode;
272  m_callingExec = callingExecState;
273  if (m_callingExec) {
274  scope = m_callingExec->scopeChain();
275  m_variable = m_callingExec->variableObject();
276  m_thisVal = m_callingExec->thisValue();
277  return;
278  }
279 
280  // 10.2.2 talks about the behavior w/o a calling context here,
281  // saying it should be like global code. This can not happen
282  // in actual JS code, but it may be synthesized by e.g.
283  // the JS debugger calling 'eval' itself, from globalExec
284  m_thisVal = glob;
285  m_variable = glob;
286  scope.push(glob);
287 }
288 
289 FunctionExecState::FunctionExecState(Interpreter *intp, JSObject *thisObject,
290  FunctionBodyNode *body, ExecState *callingExecState,
291  FunctionImp *function): ExecState(intp, intp->execState())
292 {
293  m_function = function;
294  m_currentBody = body;
295 
296  m_codeType = FunctionCode;
297  m_callingExec = callingExecState;
298  scope = function->scope(); // Activation will push itself when setting up
299  m_variable = m_interpreter->getRecycledActivation();// TODO: DontDelete ? (ECMA 10.2.3)
300  if (!m_variable) {
301  m_variable = new ActivationImp();
302  }
303  m_thisVal = thisObject;
304 }
305 
306 } // namespace KJS
307 
JSObject * thisValue() const
Returns the "this" value for the execution context.
Definition: ExecState.h:215
JSValue is the base type for all primitives (Undefined, Null, Boolean, String, Number) and objects in...
Definition: value.h:58
Addr target() const
Returns the address a break or a continue statement targets.
Definition: completion.h:78
virtual ExecState * globalExec()
Returns the execution state object which can be used to execute scripts using this interpreter at a t...
ComplType complType() const
Returns the type of this completion.
Definition: completion.h:61
bool hadException() const
Use this to check if an exception was thrown in the current execution state.
Definition: ExecState.h:163
@ PopScope
remove a scope chain entry, and run the next handler
Definition: ExecState.h:82
Completion objects are used to convey the return status and value from functions.
Definition: completion.h:52
void clearException()
Clears the exception or other abnormal completion set on this execution state.
Definition: ExecState.h:143
JSObject * variableObject() const
Returns the variable object for the execution context.
Definition: ExecState.h:191
Represents the current state of script execution.
Definition: ExecState.h:53
Interpreter objects can be used to evaluate ECMAScript code.
Definition: interpreter.h:56
const ScopeChain & scopeChain() const
Returns the scope chain for this execution context.
Definition: ExecState.h:180
@ RemoveDeferred
remove any deferred exception object, and run the next entry
Definition: ExecState.h:83
ExecState(Interpreter *intp, ExecState *save)
Definition: ExecState.cpp:97
Interpreter * lexicalInterpreter() const
Returns the interpreter associated with the current scope's global object.
Definition: ExecState.cpp:35
JSValue * reactivateCompletion(bool insideTryFinally)
This resumes dispatch of a completion that was deferred due to a try ...
Definition: ExecState.cpp:138
@ JumpToCatch
jump to the specified address
Definition: ExecState.h:81
void setAbruptCompletion(Completion comp)
Records an abrupt completion of code, and jumps to the closest catch or finally.
Definition: ExecState.cpp:178
Interpreter * dynamicInterpreter() const
Returns the interpreter associated with this execution state.
Definition: ExecState.h:64
JSValue * value() const
Returns the value of this completion if it is of type value-completion, 0 otherwise.
Definition: completion.h:70
ExecState * callingExecState()
Returns the context from which the current context was invoked.
Definition: ExecState.h:228
HandlerType
This describes how an exception should be handled.
Definition: ExecState.h:80
void setException(JSValue *e)
Set the exception associated with this execution state, updating the program counter appropriately,...
Definition: ExecState.cpp:169
@ Silent
just update the exception object. For debugger-type use only
Definition: ExecState.h:84
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu May 26 2022 03:55:07 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.