source: webkit/trunk/JavaScriptCore/kjs/interpreter.h@ 13597

Last change on this file since 13597 was 13304, checked in by mjs, 19 years ago

Reviewed by Anders.


The memory usage of Node was reduced by 2 machine words per node:

  • sourceURL was removed and only kept on FunctionBodyNode. The source URL can only be distinct per function or top-level program node, and you always have one.


  • refcount was removed and kept in a separate hashtable when greater than 1. newNodes set represents floating nodes with refcount of 0. This helps because almost all nodes have a refcount of 1 for almost all of their lifetime.


  • bindings/runtime_method.cpp: (RuntimeMethod::RuntimeMethod): Pass null body, added FIXME.
  • kjs/Parser.cpp: (KJS::clearNewNodes): New nodes are tracked in nodes.cpp now, but still clear them at the appropriate time.
  • kjs/context.h: (KJS::ContextImp::currentBody): added; used to retrieve source URL and sid for current code. (KJS::ContextImp::pushIteration): moved here from LabelStack (KJS::ContextImp::popIteration): ditto (KJS::ContextImp::inIteration): ditto (KJS::ContextImp::pushSwitch): ditto (KJS::ContextImp::popSwitch): ditto (KJS::ContextImp::inSwitch): ditto
  • kjs/function.cpp: (KJS::FunctionImp::FunctionImp): Add FunctionBodyNode* parameter. (KJS::FunctionImp::callAsFunction): Pass body to ContextImp. (KJS::FunctionImp::argumentsGetter): _context renamed to m_context. (KJS::DeclaredFunctionImp::DeclaredFunctionImp): Pass body to superclass constructor. (KJS::GlobalFuncImp::callAsFunction): Pass progNode as body for ContextImp in eval.
  • kjs/function.h: Move body field from DeclaredFunctionImp to FunctionImp.
  • kjs/grammar.y: Change DBG; statements no longer have a sourceid.
  • kjs/internal.cpp: (KJS::ContextImp::ContextImp): Initialize new m_currentBody, m_iterationDepth and m_switchDepth data members. New FunctionBodyNode* parameter - the function body provides source URL and SourceId. (KJS::InterpreterImp::mark): Use exception() function, not _exception directly. (KJS::InterpreterImp::evaluate): Pass progNode to ContextImp constructor to use as the body.
  • kjs/internal.h: (KJS::LabelStack::LabelStack): Remove iteration depth and switch depth; statement label stacks don't need these and it bloats their size. Put them in the ContextImp instead.
  • kjs/interpreter.cpp: (KJS::ExecState::lexicalInterpreter): Renamed _context to m_context.
  • kjs/interpreter.h: (KJS::ExecState::dynamicInterpreter): Renamed _context to m_context. (KJS::ExecState::context): ditto (KJS::ExecState::setException): Renamed _exception to m_exception (KJS::ExecState::clearException): ditto (KJS::ExecState::exception): ditto (KJS::ExecState::hadException): ditto (KJS::ExecState::ExecState): ditto both above renames
  • kjs/nodes.cpp: (Node::Node): Removed initialization of line, source URL and refcount. Add to local newNodes set instead of involving parser. (Node::ref): Instead of managing refcount directly, story refcount over 1 in a HashCountedSet, and keep a separate HashSet of "floating" nodes with refcount 0. (Node::deref): ditto (Node::refcount): ditto (Node::clearNewNodes): Destroy anything left in the new nodes set. (currentSourceId): Inline helper to get sourceId from function body via context. (currentSourceURL): ditto for sourceURL. (Node::createErrorCompletion): use new helper (Node::throwError): ditto (Node::setExceptionDetailsIfNeeded): ditto (StatementNode::StatementNode): remove initialization of l0 and sid, rename l1 to m_lastLine. (StatementNode::setLoc): Set own m_lastLine and Node's m_line. (StatementNode::hitStatement): Get sid, first line, last line in the proper new ways. (StatListNode::StatListNode): updated for setLoc changes (BlockNode::BlockNode): ditto (DoWhileNode::execute): excpect iteraton counts on ContextImp, not LabelStack (WhileNode::execute): ditto (ForNode::execute): ditto (ForInNode::execute): ditto (ContinueNode::execute): excpect inIteration on ContextImp, not LabelStack (BreakNode::execute): excpect inIteration and inSwitch on ContextImp, not LabelStack (SwitchNode::execute): expect switch counts on ContextImp, not LabelStack (FunctionBodyNode::FunctionBodyNode): update for new setLoc (FunctionBodyNode::processFuncDecl): reindent (SourceElementsNode::SourceElementsNode): update for new setLoc
  • kjs/nodes.h: (KJS::Node::lineNo): Renamed _line to m_line (KJS::StatementNode::firstLine): Use lineNo() (KJS::StatementNode::lastLine): Renamed l1 to m_lastLine (KJS::FunctionBodyNode::sourceId): added (KJS::FunctionBodyNode::sourceURL): added
  • kjs/testkjs.cpp:
  • Property svn:eol-style set to native
File size: 15.8 KB
Line 
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 Apple Computer, Inc.
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#ifndef _KJS_INTERPRETER_H_
25#define _KJS_INTERPRETER_H_
26
27#include "value.h"
28#include "types.h"
29
30namespace KJS {
31
32 class ContextImp;
33 class InterpreterImp;
34 class RuntimeMethod;
35 class ScopeChain;
36
37 namespace Bindings {
38 class RootObject;
39 }
40
41 /**
42 * Represents an execution context, as specified by section 10 of the ECMA
43 * spec.
44 *
45 * An execution context contains information about the current state of the
46 * script - the scope for variable lookup, the value of "this", etc. A new
47 * execution context is entered whenever global code is executed (e.g. with
48 * Interpreter::evaluate()), a function is called (see
49 * Object::call()), or the builtin "eval" function is executed.
50 *
51 * Most inheritable functions in the KJS api take a ExecState pointer as
52 * their first parameter. This can be used to obtain a handle to the current
53 * execution context.
54 *
55 * Note: Context objects are wrapper classes/smart pointers for the internal
56 * KJS ContextImp type. When one context variable is assigned to another, it
57 * is still referencing the same internal object.
58 */
59 class Context {
60 public:
61 Context(ContextImp *i) : rep(i) { }
62
63 ContextImp *imp() const { return rep; }
64
65 /**
66 * Returns the scope chain for this execution context. This is used for
67 * variable lookup, with the list being searched from start to end until a
68 * variable is found.
69 *
70 * @return The execution context's scope chain
71 */
72 const ScopeChain &scopeChain() const;
73
74 /**
75 * Returns the variable object for the execution context. This contains a
76 * property for each variable declared in the execution context.
77 *
78 * @return The execution context's variable object
79 */
80 JSObject *variableObject() const;
81
82 /**
83 * Returns the "this" value for the execution context. This is the value
84 * returned when a script references the special variable "this". It should
85 * always be an Object, unless application-specific code has passed in a
86 * different type.
87 *
88 * The object that is used as the "this" value depends on the type of
89 * execution context - for global contexts, the global object is used. For
90 * function objewcts, the value is given by the caller (e.g. in the case of
91 * obj.func(), obj would be the "this" value). For code executed by the
92 * built-in "eval" function, the this value is the same as the calling
93 * context.
94 *
95 * @return The execution context's "this" value
96 */
97 JSObject *thisValue() const;
98
99 /**
100 * Returns the context from which the current context was invoked. For
101 * global code this will be a null context (i.e. one for which
102 * isNull() returns true). You should check isNull() on the returned
103 * value before calling any of it's methods.
104 *
105 * @return The calling execution context
106 */
107 const Context callingContext() const;
108
109 /**
110 * The line number on which the current statement begins
111 * NOTE: Only for source compatibility, JSC does not support this method.
112 */
113 int curStmtFirstLine() const { return 0; }
114
115 private:
116 ContextImp *rep;
117 };
118
119 class SavedBuiltinsInternal;
120
121 class SavedBuiltins {
122 friend class InterpreterImp;
123 public:
124 SavedBuiltins();
125 ~SavedBuiltins();
126 private:
127 SavedBuiltinsInternal *_internal;
128 };
129
130 /**
131 * Interpreter objects can be used to evaluate ECMAScript code. Each
132 * interpreter has a global object which is used for the purposes of code
133 * evaluation, and also provides access to built-in properties such as
134 * " Object" and "Number".
135 */
136 class Interpreter {
137 public:
138 /**
139 * Creates a new interpreter. The supplied object will be used as the global
140 * object for all scripts executed with this interpreter. During
141 * constuction, all the standard properties such as "Object" and "Number"
142 * will be added to the global object.
143 *
144 * Note: You should not use the same global object for multiple
145 * interpreters.
146 *
147 * This is due do the fact that the built-in properties are set in the
148 * constructor, and if these objects have been modified from another
149 * interpreter (e.g. a script modifying String.prototype), the changes will
150 * be overridden.
151 *
152 * @param global The object to use as the global object for this interpreter
153 */
154 Interpreter(JSObject *global);
155 /**
156 * Creates a new interpreter. A global object will be created and
157 * initialized with the standard global properties.
158 */
159 Interpreter();
160 virtual ~Interpreter();
161
162 /**
163 * Returns the object that is used as the global object during all script
164 * execution performed by this interpreter
165 */
166 JSObject *globalObject() const;
167
168 void initGlobalObject();
169
170 /**
171 * Returns the execution state object which can be used to execute
172 * scripts using this interpreter at a the "global" level, i.e. one
173 * with a execution context that has the global object as the "this"
174 * value, and who's scope chain contains only the global object.
175 *
176 * Note: this pointer remains constant for the life of the interpreter
177 * and should not be manually deleted.
178 *
179 * @return The interpreter global execution state object
180 */
181 virtual ExecState *globalExec();
182
183 /**
184 * Parses the supplied ECMAScript code and checks for syntax errors.
185 *
186 * @param code The code to check
187 * @return true if there were no syntax errors in the code, otherwise false
188 */
189 bool checkSyntax(const UString &code);
190
191 /**
192 * Evaluates the supplied ECMAScript code.
193 *
194 * Since this method returns a Completion, you should check the type of
195 * completion to detect an error or before attempting to access the returned
196 * value. For example, if an error occurs during script execution and is not
197 * caught by the script, the completion type will be Throw.
198 *
199 * If the supplied code is invalid, a SyntaxError will be thrown.
200 *
201 * @param code The code to evaluate
202 * @param thisV The value to pass in as the "this" value for the script
203 * execution. This should either be jsNull() or an Object.
204 * @return A completion object representing the result of the execution.
205 */
206 Completion evaluate(const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength, JSValue* thisV = 0);
207 Completion evaluate(const UString& sourceURL, int startingLineNumber, const UString& code, JSValue* thisV = 0);
208
209 /**
210 * @internal
211 *
212 * Returns the implementation object associated with this interpreter.
213 * Only useful for internal KJS operations.
214 */
215 InterpreterImp *imp() const { return rep; }
216
217 /**
218 * Returns the builtin "Object" object. This is the object that was set
219 * as a property of the global object during construction; if the property
220 * is replaced by script code, this method will still return the original
221 * object.
222 *
223 * @return The builtin "Object" object
224 */
225 JSObject *builtinObject() const;
226
227 /**
228 * Returns the builtin "Function" object.
229 */
230 JSObject *builtinFunction() const;
231
232 /**
233 * Returns the builtin "Array" object.
234 */
235 JSObject *builtinArray() const;
236
237 /**
238 * Returns the builtin "Boolean" object.
239 */
240 JSObject *builtinBoolean() const;
241
242 /**
243 * Returns the builtin "String" object.
244 */
245 JSObject *builtinString() const;
246
247 /**
248 * Returns the builtin "Number" object.
249 */
250 JSObject *builtinNumber() const;
251
252 /**
253 * Returns the builtin "Date" object.
254 */
255 JSObject *builtinDate() const;
256
257 /**
258 * Returns the builtin "RegExp" object.
259 */
260 JSObject *builtinRegExp() const;
261
262 /**
263 * Returns the builtin "Error" object.
264 */
265 JSObject *builtinError() const;
266
267 /**
268 * Returns the builtin "Object.prototype" object.
269 */
270 JSObject *builtinObjectPrototype() const;
271
272 /**
273 * Returns the builtin "Function.prototype" object.
274 */
275 JSObject *builtinFunctionPrototype() const;
276
277 /**
278 * Returns the builtin "Array.prototype" object.
279 */
280 JSObject *builtinArrayPrototype() const;
281
282 /**
283 * Returns the builtin "Boolean.prototype" object.
284 */
285 JSObject *builtinBooleanPrototype() const;
286
287 /**
288 * Returns the builtin "String.prototype" object.
289 */
290 JSObject *builtinStringPrototype() const;
291
292 /**
293 * Returns the builtin "Number.prototype" object.
294 */
295 JSObject *builtinNumberPrototype() const;
296
297 /**
298 * Returns the builtin "Date.prototype" object.
299 */
300 JSObject *builtinDatePrototype() const;
301
302 /**
303 * Returns the builtin "RegExp.prototype" object.
304 */
305 JSObject *builtinRegExpPrototype() const;
306
307 /**
308 * Returns the builtin "Error.prototype" object.
309 */
310 JSObject *builtinErrorPrototype() const;
311
312 /**
313 * The initial value of "Error" global property
314 */
315 JSObject *builtinEvalError() const;
316 JSObject *builtinRangeError() const;
317 JSObject *builtinReferenceError() const;
318 JSObject *builtinSyntaxError() const;
319 JSObject *builtinTypeError() const;
320 JSObject *builtinURIError() const;
321
322 JSObject *builtinEvalErrorPrototype() const;
323 JSObject *builtinRangeErrorPrototype() const;
324 JSObject *builtinReferenceErrorPrototype() const;
325 JSObject *builtinSyntaxErrorPrototype() const;
326 JSObject *builtinTypeErrorPrototype() const;
327 JSObject *builtinURIErrorPrototype() const;
328
329 enum CompatMode { NativeMode, IECompat, NetscapeCompat };
330 /**
331 * Call this to enable a compatibility mode with another browser.
332 * (by default konqueror is in "native mode").
333 * Currently, in KJS, this only changes the behavior of Date::getYear()
334 * which returns the full year under IE.
335 */
336 void setCompatMode(CompatMode mode);
337 CompatMode compatMode() const;
338
339 /**
340 * Run the garbage collection. Returns true when at least one object
341 * was collected; false otherwise.
342 */
343 static bool collect();
344
345 /**
346 * Called by InterpreterImp during the mark phase of the garbage collector
347 * Default implementation does nothing, this exist for classes that reimplement Interpreter.
348 */
349 virtual void mark() {}
350
351 /**
352 * Provides a way to distinguish derived classes.
353 * Only useful if you reimplement Interpreter and if different kind of
354 * interpreters are created in the same process.
355 * The base class returns 0, the ECMA-bindings interpreter returns 1.
356 */
357 virtual int rtti() { return 0; }
358
359#ifdef KJS_DEBUG_MEM
360 /**
361 * @internal
362 */
363 static void finalCheck();
364#endif
365
366 static bool shouldPrintExceptions();
367 static void setShouldPrintExceptions(bool);
368
369 void saveBuiltins (SavedBuiltins &) const;
370 void restoreBuiltins (const SavedBuiltins &);
371
372 /**
373 * Determine if the value is a global object (for any interpreter). This may
374 * be difficult to determine for multiple uses of JSC in a process that are
375 * logically independent of each other. In the case of WebCore, this method
376 * is used to determine if an object is the Window object so we can perform
377 * security checks.
378 */
379 virtual bool isGlobalObject(JSValue*) { return false; }
380
381 /**
382 * Find the interpreter for a particular global object. This should really
383 * be a static method, but we can't do that is C++. Again, as with isGlobalObject()
384 * implementation really need to know about all instances of Interpreter
385 * created in an application to correctly implement this method. The only
386 * override of this method is currently in WebCore.
387 */
388 virtual Interpreter* interpreterForGlobalObject(const JSValue*) { return 0; }
389
390 /**
391 * Determine if the it is 'safe' to execute code in the target interpreter from an
392 * object that originated in this interpreter. This check is used to enforce WebCore
393 * cross frame security rules. In particular, attempts to access 'bound' objects are
394 * not allowed unless isSafeScript returns true.
395 */
396 virtual bool isSafeScript(const Interpreter*) { return true; }
397
398#if PLATFORM(MAC)
399 virtual void *createLanguageInstanceForValue(ExecState*, int language, JSObject* value, const Bindings::RootObject* origin, const Bindings::RootObject* current);
400#endif
401
402 // This is a workaround to avoid accessing the global variables for these identifiers in
403 // important property lookup functions, to avoid taking PIC branches in Mach-O binaries
404 const Identifier& argumentsIdentifier() { return *m_argumentsPropertyName; }
405 const Identifier& specialPrototypeIdentifier() { return *m_specialPrototypePropertyName; }
406
407 private:
408 InterpreterImp *rep;
409
410 const Identifier *m_argumentsPropertyName;
411 const Identifier *m_specialPrototypePropertyName;
412
413 /**
414 * This constructor is not implemented, in order to prevent
415 * copy-construction of Interpreter objects. You should always pass around
416 * pointers to an interpreter instance instead.
417 */
418 Interpreter(const Interpreter&);
419
420 /**
421 * This constructor is not implemented, in order to prevent assignment of
422 * Interpreter objects. You should always pass around pointers to an
423 * interpreter instance instead.
424 */
425 Interpreter operator=(const Interpreter&);
426
427 protected:
428 virtual void virtual_hook( int id, void* data );
429 };
430
431 /**
432 * Represents the current state of script execution. This object allows you
433 * obtain a handle the interpreter that is currently executing the script,
434 * and also the current execution state context.
435 */
436 class ExecState {
437 friend class InterpreterImp;
438 friend class FunctionImp;
439 friend class RuntimeMethodImp;
440 friend class GlobalFuncImp;
441 public:
442 /**
443 * Returns the interpreter associated with this execution state
444 *
445 * @return The interpreter executing the script
446 */
447 Interpreter *dynamicInterpreter() const { return m_interpreter; }
448
449 // for compatibility
450 Interpreter *interpreter() const { return dynamicInterpreter(); }
451
452 /**
453 * Returns the interpreter associated with the current scope's
454 * global object
455 *
456 * @return The interpreter currently in scope
457 */
458 Interpreter *lexicalInterpreter() const;
459
460 /**
461 * Returns the execution context associated with this execution state
462 *
463 * @return The current execution state context
464 */
465 Context context() const { return m_context; }
466
467 void setException(JSValue* e) { m_exception = e; }
468 void clearException() { m_exception = 0; }
469 JSValue* exception() const { return m_exception; }
470 bool hadException() const { return m_exception; }
471
472 private:
473 ExecState(Interpreter* interp, ContextImp* con)
474 : m_interpreter(interp)
475 , m_context(con)
476 , m_exception(0)
477 {
478 }
479 Interpreter* m_interpreter;
480 ContextImp* m_context;
481 JSValue* m_exception;
482 };
483
484} // namespace
485
486#endif // _KJS_INTERPRETER_H_
Note: See TracBrowser for help on using the repository browser.