source: webkit/trunk/JavaScriptCore/kjs/interpreter.cpp@ 28328

Last change on this file since 28328 was 28328, checked in by [email protected], 17 years ago

JavaScriptCore:

Reviewed by Eric Seidel.

Second step in refactoring JSGlobalObject: moved virtual functions from
Interpreter to JSGlobalObject.


Layout and JS tests pass. SunSpider reports a .7% speedup -- don't
believe his lies.

JavaScriptGlue:

Reviewed by Eric Seidel.

Updated to match the JavaScriptCore change to move virtual methods from
Interpreter to JSGlobalObject.


  • JSRun.cpp:
  • JSRun.h:
  • JSValueWrapper.cpp: (getThreadGlobalExecState):
  • JavaScriptGlue.cpp: (JSRunCopyGlobalObject): (JSRunEvaluate):

WebCore:

Reviewed by Eric Seidel.

Updated to match the JavaScriptCore change to move virtual methods from
Interpreter to JSGlobalObject.


Moved virtual ScriptInterpreter functions to Window.

WebKit/mac:

Reviewed by Eric Seidel.

Updated to match the JavaScriptCore change to move virtual methods from
Interpreter to JSGlobalObject.

  • WebView/WebFrame.mm: (-[WebFrame globalContext]): Use the toRef function instead of manually casting.
  • Property svn:eol-style set to native
File size: 24.9 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2001 Harri Porten ([email protected])
5 * Copyright (C) 2001 Peter Kelly ([email protected])
6 * Copyright (C) 2003 Apple Computer, Inc.
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 "config.h"
26#include "interpreter.h"
27
28#include "ExecState.h"
29#include "JSGlobalObject.h"
30#include "SavedBuiltins.h"
31#include "array_object.h"
32#include "bool_object.h"
33#include "collector.h"
34#include "date_object.h"
35#include "debugger.h"
36#include "error_object.h"
37#include "function_object.h"
38#include "internal.h"
39#include "math_object.h"
40#include "nodes.h"
41#include "number_object.h"
42#include "object.h"
43#include "object_object.h"
44#include "operations.h"
45#include "regexp_object.h"
46#include "runtime.h"
47#include "string_object.h"
48#include "types.h"
49#include "value.h"
50#include <math.h>
51#include <signal.h>
52#include <stdio.h>
53#include <wtf/Assertions.h>
54
55#if HAVE(SYS_TIME_H)
56#include <sys/time.h>
57#endif
58
59#if PLATFORM(WIN_OS)
60#include <windows.h>
61#endif
62
63#if PLATFORM(QT)
64#include <QDateTime>
65#endif
66
67namespace KJS {
68
69// Default number of ticks before a timeout check should be done.
70static const int initialTickCountThreshold = 255;
71
72// Preferred number of milliseconds between each timeout check
73static const int preferredScriptCheckTimeInterval = 1000;
74
75Interpreter* Interpreter::s_hook = 0;
76
77typedef HashMap<JSObject*, Interpreter*> InterpreterMap;
78static inline InterpreterMap &interpreterMap()
79{
80 static InterpreterMap* map = new InterpreterMap;
81 return* map;
82}
83
84Interpreter::Interpreter()
85 : m_globalExec(this, 0, 0, 0)
86 , m_currentExec(0)
87 , m_globalObject(0)
88{
89 init();
90}
91
92void Interpreter::init()
93{
94 JSLock lock;
95
96 m_timeoutTime = 0;
97 m_recursion = 0;
98 m_debugger= 0;
99
100 resetTimeoutCheck();
101 m_timeoutCheckCount = 0;
102
103 m_compatMode = NativeMode;
104
105 if (s_hook) {
106 prev = s_hook;
107 next = s_hook->next;
108 s_hook->next->prev = this;
109 s_hook->next = this;
110 } else {
111 // This is the first interpreter
112 s_hook = next = prev = this;
113 }
114
115 createObjectsForGlobalObjectProperties();
116}
117
118Interpreter::~Interpreter()
119{
120 JSLock lock;
121
122 if (m_debugger)
123 m_debugger->detach(this);
124
125 next->prev = prev;
126 prev->next = next;
127 s_hook = next;
128 if (s_hook == this) {
129 // This was the last interpreter
130 s_hook = 0;
131 }
132}
133
134JSGlobalObject* Interpreter::globalObject() const
135{
136 // Now that we delay setting of the global object, people retrieving it before it is set may be in for a nasty surprise
137 ASSERT(m_globalObject);
138 return m_globalObject;
139}
140
141void Interpreter::setGlobalObject(JSGlobalObject* globalObject)
142{
143 ASSERT(!m_globalObject);
144 ASSERT(globalObject);
145 m_globalObject = globalObject;
146 m_globalExec.setGlobalObject(globalObject);
147
148 setGlobalObjectProperties();
149}
150
151void Interpreter::resetGlobalObjectProperties()
152{
153 ASSERT(m_globalObject);
154 createObjectsForGlobalObjectProperties();
155 setGlobalObjectProperties();
156}
157
158void Interpreter::createObjectsForGlobalObjectProperties()
159{
160 // Clear before inititalizing, to avoid marking uninitialized (dangerous) or
161 // stale (wasteful) pointers during initialization.
162
163 // Prototypes
164 m_FunctionPrototype = 0;
165 m_ObjectPrototype = 0;
166
167 m_ArrayPrototype = 0;
168 m_StringPrototype = 0;
169 m_BooleanPrototype = 0;
170 m_NumberPrototype = 0;
171 m_DatePrototype = 0;
172 m_RegExpPrototype = 0;
173 m_ErrorPrototype = 0;
174
175 m_EvalErrorPrototype = 0;
176 m_RangeErrorPrototype = 0;
177 m_ReferenceErrorPrototype = 0;
178 m_SyntaxErrorPrototype = 0;
179 m_TypeErrorPrototype = 0;
180 m_UriErrorPrototype = 0;
181
182 // Constructors
183 m_Object = 0;
184 m_Function = 0;
185 m_Array = 0;
186 m_String = 0;
187 m_Boolean = 0;
188 m_Number = 0;
189 m_Date = 0;
190 m_RegExp = 0;
191 m_Error = 0;
192
193 m_EvalError = 0;
194 m_RangeError = 0;
195 m_ReferenceError = 0;
196 m_SyntaxError = 0;
197 m_TypeError = 0;
198 m_UriError = 0;
199
200 // Prototypes
201 m_FunctionPrototype = new FunctionPrototype(&m_globalExec);
202 m_ObjectPrototype = new ObjectPrototype(&m_globalExec, m_FunctionPrototype);
203 m_FunctionPrototype->setPrototype(m_ObjectPrototype);
204
205 m_ArrayPrototype = new ArrayPrototype(&m_globalExec, m_ObjectPrototype);
206 m_StringPrototype = new StringPrototype(&m_globalExec, m_ObjectPrototype);
207 m_BooleanPrototype = new BooleanPrototype(&m_globalExec, m_ObjectPrototype, m_FunctionPrototype);
208 m_NumberPrototype = new NumberPrototype(&m_globalExec, m_ObjectPrototype, m_FunctionPrototype);
209 m_DatePrototype = new DatePrototype(&m_globalExec, m_ObjectPrototype);
210 m_RegExpPrototype = new RegExpPrototype(&m_globalExec, m_ObjectPrototype, m_FunctionPrototype);;
211 m_ErrorPrototype = new ErrorPrototype(&m_globalExec, m_ObjectPrototype, m_FunctionPrototype);
212
213 m_EvalErrorPrototype = new NativeErrorPrototype(&m_globalExec, m_ErrorPrototype, EvalError, "EvalError", "EvalError");
214 m_RangeErrorPrototype = new NativeErrorPrototype(&m_globalExec, m_ErrorPrototype, RangeError, "RangeError", "RangeError");
215 m_ReferenceErrorPrototype = new NativeErrorPrototype(&m_globalExec, m_ErrorPrototype, ReferenceError, "ReferenceError", "ReferenceError");
216 m_SyntaxErrorPrototype = new NativeErrorPrototype(&m_globalExec, m_ErrorPrototype, SyntaxError, "SyntaxError", "SyntaxError");
217 m_TypeErrorPrototype = new NativeErrorPrototype(&m_globalExec, m_ErrorPrototype, TypeError, "TypeError", "TypeError");
218 m_UriErrorPrototype = new NativeErrorPrototype(&m_globalExec, m_ErrorPrototype, URIError, "URIError", "URIError");
219
220 // Constructors
221 m_Object = new ObjectObjectImp(&m_globalExec, m_ObjectPrototype, m_FunctionPrototype);
222 m_Function = new FunctionObjectImp(&m_globalExec, m_FunctionPrototype);
223 m_Array = new ArrayObjectImp(&m_globalExec, m_FunctionPrototype, m_ArrayPrototype);
224 m_String = new StringObjectImp(&m_globalExec, m_FunctionPrototype, m_StringPrototype);
225 m_Boolean = new BooleanObjectImp(&m_globalExec, m_FunctionPrototype, m_BooleanPrototype);
226 m_Number = new NumberObjectImp(&m_globalExec, m_FunctionPrototype, m_NumberPrototype);
227 m_Date = new DateObjectImp(&m_globalExec, m_FunctionPrototype, m_DatePrototype);
228 m_RegExp = new RegExpObjectImp(&m_globalExec, m_FunctionPrototype, m_RegExpPrototype);
229 m_Error = new ErrorObjectImp(&m_globalExec, m_FunctionPrototype, m_ErrorPrototype);
230
231 m_EvalError = new NativeErrorImp(&m_globalExec, m_FunctionPrototype, m_EvalErrorPrototype);
232 m_RangeError = new NativeErrorImp(&m_globalExec, m_FunctionPrototype, m_RangeErrorPrototype);
233 m_ReferenceError = new NativeErrorImp(&m_globalExec, m_FunctionPrototype, m_ReferenceErrorPrototype);
234 m_SyntaxError = new NativeErrorImp(&m_globalExec, m_FunctionPrototype, m_SyntaxErrorPrototype);
235 m_TypeError = new NativeErrorImp(&m_globalExec, m_FunctionPrototype, m_TypeErrorPrototype);
236 m_UriError = new NativeErrorImp(&m_globalExec, m_FunctionPrototype, m_UriErrorPrototype);
237
238 m_FunctionPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Function, DontEnum);
239 m_ObjectPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Object, DontEnum | DontDelete | ReadOnly);
240 m_FunctionPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Function, DontEnum | DontDelete | ReadOnly);
241 m_ArrayPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Array, DontEnum | DontDelete | ReadOnly);
242 m_BooleanPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Boolean, DontEnum | DontDelete | ReadOnly);
243 m_StringPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_String, DontEnum | DontDelete | ReadOnly);
244 m_NumberPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Number, DontEnum | DontDelete | ReadOnly);
245 m_DatePrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Date, DontEnum | DontDelete | ReadOnly);
246 m_RegExpPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_RegExp, DontEnum | DontDelete | ReadOnly);
247 m_ErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_Error, DontEnum | DontDelete | ReadOnly);
248 m_EvalErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_EvalError, DontEnum | DontDelete | ReadOnly);
249 m_RangeErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_RangeError, DontEnum | DontDelete | ReadOnly);
250 m_ReferenceErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_ReferenceError, DontEnum | DontDelete | ReadOnly);
251 m_SyntaxErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_SyntaxError, DontEnum | DontDelete | ReadOnly);
252 m_TypeErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_TypeError, DontEnum | DontDelete | ReadOnly);
253 m_UriErrorPrototype->put(&m_globalExec, m_globalExec.propertyNames().constructor, m_UriError, DontEnum | DontDelete | ReadOnly);
254}
255
256void Interpreter::setGlobalObjectProperties()
257{
258 ASSERT(m_globalObject);
259 m_globalObject->setInterpreter(std::auto_ptr<Interpreter>(this));
260
261 // Set global object prototype
262 JSObject* o = m_globalObject;
263 while (o->prototype()->isObject())
264 o = static_cast<JSObject*>(o->prototype());
265 o->setPrototype(m_ObjectPrototype);
266
267 // Set global constructors
268 // FIXME: kjs_window.cpp checks Internal/DontEnum as a performance hack, to
269 // see that these values can be put directly without a check for override
270 // properties.
271 // FIXME: These properties should be handled by JSGlobalObject
272 m_globalObject->putDirect("Object", m_Object, DontEnum);
273 m_globalObject->putDirect("Function", m_Function, DontEnum);
274 m_globalObject->putDirect("Array", m_Array, DontEnum);
275 m_globalObject->putDirect("Boolean", m_Boolean, DontEnum);
276 m_globalObject->putDirect("String", m_String, DontEnum);
277 m_globalObject->putDirect("Number", m_Number, DontEnum);
278 m_globalObject->putDirect("Date", m_Date, DontEnum);
279 m_globalObject->putDirect("RegExp", m_RegExp, DontEnum);
280 m_globalObject->putDirect("Error", m_Error, DontEnum);
281 m_globalObject->putDirect("EvalError",m_EvalError, Internal);
282 m_globalObject->putDirect("RangeError",m_RangeError, Internal);
283 m_globalObject->putDirect("ReferenceError",m_ReferenceError, Internal);
284 m_globalObject->putDirect("SyntaxError",m_SyntaxError, Internal);
285 m_globalObject->putDirect("TypeError",m_TypeError, Internal);
286 m_globalObject->putDirect("URIError",m_UriError, Internal);
287
288 // Set global values
289 m_globalObject->putDirect("Math", new MathObjectImp(&m_globalExec, m_ObjectPrototype), DontEnum);
290 m_globalObject->putDirect("NaN", jsNaN(), DontEnum|DontDelete);
291 m_globalObject->putDirect("Infinity", jsNumber(Inf), DontEnum|DontDelete);
292 m_globalObject->putDirect("undefined", jsUndefined(), DontEnum|DontDelete);
293
294 // Set global functions
295 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::Eval, 1, "eval"), DontEnum);
296 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::ParseInt, 2, "parseInt"), DontEnum);
297 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::ParseFloat, 1, "parseFloat"), DontEnum);
298 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::IsNaN, 1, "isNaN"), DontEnum);
299 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::IsFinite, 1, "isFinite"), DontEnum);
300 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::Escape, 1, "escape"), DontEnum);
301 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::UnEscape, 1, "unescape"), DontEnum);
302 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::DecodeURI, 1, "decodeURI"), DontEnum);
303 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::DecodeURIComponent, 1, "decodeURIComponent"), DontEnum);
304 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::EncodeURI, 1, "encodeURI"), DontEnum);
305 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::EncodeURIComponent, 1, "encodeURIComponent"), DontEnum);
306#ifndef NDEBUG
307 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, m_FunctionPrototype, GlobalFuncImp::KJSPrint, 1, "kjsprint"), DontEnum);
308#endif
309}
310
311Completion Interpreter::checkSyntax(const UString& sourceURL, int startingLineNumber, const UString& code)
312{
313 return checkSyntax(sourceURL, startingLineNumber, code.data(), code.size());
314}
315
316Completion Interpreter::checkSyntax(const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength)
317{
318 JSLock lock;
319
320 int errLine;
321 UString errMsg;
322 RefPtr<ProgramNode> progNode = parser().parseProgram(sourceURL, startingLineNumber, code, codeLength, 0, &errLine, &errMsg);
323 if (!progNode)
324 return Completion(Throw, Error::create(&m_globalExec, SyntaxError, errMsg, errLine, 0, sourceURL));
325 return Completion(Normal);
326}
327
328Completion Interpreter::evaluate(const UString& sourceURL, int startingLineNumber, const UString& code, JSValue* thisV)
329{
330 return evaluate(sourceURL, startingLineNumber, code.data(), code.size(), thisV);
331}
332
333Completion Interpreter::evaluate(const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength, JSValue* thisV)
334{
335 JSLock lock;
336
337 // prevent against infinite recursion
338 if (m_recursion >= 20)
339 return Completion(Throw, Error::create(&m_globalExec, GeneralError, "Recursion too deep"));
340
341 // parse the source code
342 int sourceId;
343 int errLine;
344 UString errMsg;
345 RefPtr<ProgramNode> progNode = parser().parseProgram(sourceURL, startingLineNumber, code, codeLength, &sourceId, &errLine, &errMsg);
346
347 // notify debugger that source has been parsed
348 if (m_debugger) {
349 bool cont = m_debugger->sourceParsed(&m_globalExec, sourceId, sourceURL, UString(code, codeLength), startingLineNumber, errLine, errMsg);
350 if (!cont)
351 return Completion(Break);
352 }
353
354 // no program node means a syntax error occurred
355 if (!progNode)
356 return Completion(Throw, Error::create(&m_globalExec, SyntaxError, errMsg, errLine, sourceId, sourceURL));
357
358 m_globalExec.clearException();
359
360 m_recursion++;
361
362 JSGlobalObject* globalObj = m_globalObject;
363 JSObject* thisObj = globalObj;
364
365 // "this" must be an object... use same rules as Function.prototype.apply()
366 if (thisV && !thisV->isUndefinedOrNull())
367 thisObj = thisV->toObject(&m_globalExec);
368
369 Completion res;
370 if (m_globalExec.hadException())
371 // the thisV->toObject() conversion above might have thrown an exception - if so, propagate it
372 res = Completion(Throw, m_globalExec.exception());
373 else {
374 // execute the code
375 ExecState newExec(this, globalObj, thisObj, progNode.get());
376 res = progNode->execute(&newExec);
377 }
378
379 m_recursion--;
380
381 if (shouldPrintExceptions() && res.complType() == Throw) {
382 JSLock lock;
383 ExecState* exec = m_globalObject->globalExec();
384 CString f = sourceURL.UTF8String();
385 CString message = res.value()->toObject(exec)->toString(exec).UTF8String();
386 int line = res.value()->toObject(exec)->get(exec, "line")->toUInt32(exec);
387#if PLATFORM(WIN_OS)
388 printf("%s line %d: %s\n", f.c_str(), line, message.c_str());
389#else
390 printf("[%d] %s line %d: %s\n", getpid(), f.c_str(), line, message.c_str());
391#endif
392 }
393
394 return res;
395}
396
397JSObject *Interpreter::builtinObject() const
398{
399 return m_Object;
400}
401
402JSObject *Interpreter::builtinFunction() const
403{
404 return m_Function;
405}
406
407JSObject *Interpreter::builtinArray() const
408{
409 return m_Array;
410}
411
412JSObject *Interpreter::builtinBoolean() const
413{
414 return m_Boolean;
415}
416
417JSObject *Interpreter::builtinString() const
418{
419 return m_String;
420}
421
422JSObject *Interpreter::builtinNumber() const
423{
424 return m_Number;
425}
426
427JSObject *Interpreter::builtinDate() const
428{
429 return m_Date;
430}
431
432JSObject *Interpreter::builtinError() const
433{
434 return m_Error;
435}
436
437JSObject *Interpreter::builtinObjectPrototype() const
438{
439 return m_ObjectPrototype;
440}
441
442JSObject *Interpreter::builtinFunctionPrototype() const
443{
444 return m_FunctionPrototype;
445}
446
447JSObject *Interpreter::builtinArrayPrototype() const
448{
449 return m_ArrayPrototype;
450}
451
452JSObject *Interpreter::builtinBooleanPrototype() const
453{
454 return m_BooleanPrototype;
455}
456
457JSObject *Interpreter::builtinStringPrototype() const
458{
459 return m_StringPrototype;
460}
461
462JSObject *Interpreter::builtinNumberPrototype() const
463{
464 return m_NumberPrototype;
465}
466
467JSObject *Interpreter::builtinDatePrototype() const
468{
469 return m_DatePrototype;
470}
471
472JSObject *Interpreter::builtinRegExpPrototype() const
473{
474 return m_RegExpPrototype;
475}
476
477JSObject *Interpreter::builtinErrorPrototype() const
478{
479 return m_ErrorPrototype;
480}
481
482JSObject *Interpreter::builtinEvalError() const
483{
484 return m_EvalError;
485}
486
487JSObject *Interpreter::builtinRangeError() const
488{
489 return m_RangeError;
490}
491
492JSObject *Interpreter::builtinReferenceError() const
493{
494 return m_ReferenceError;
495}
496
497JSObject *Interpreter::builtinSyntaxError() const
498{
499 return m_SyntaxError;
500}
501
502JSObject *Interpreter::builtinTypeError() const
503{
504 return m_TypeError;
505}
506
507JSObject *Interpreter::builtinURIError() const
508{
509 return m_UriError;
510}
511
512JSObject *Interpreter::builtinEvalErrorPrototype() const
513{
514 return m_EvalErrorPrototype;
515}
516
517JSObject *Interpreter::builtinRangeErrorPrototype() const
518{
519 return m_RangeErrorPrototype;
520}
521
522JSObject *Interpreter::builtinReferenceErrorPrototype() const
523{
524 return m_ReferenceErrorPrototype;
525}
526
527JSObject *Interpreter::builtinSyntaxErrorPrototype() const
528{
529 return m_SyntaxErrorPrototype;
530}
531
532JSObject *Interpreter::builtinTypeErrorPrototype() const
533{
534 return m_TypeErrorPrototype;
535}
536
537JSObject *Interpreter::builtinURIErrorPrototype() const
538{
539 return m_UriErrorPrototype;
540}
541
542static bool printExceptions = false;
543
544bool Interpreter::shouldPrintExceptions()
545{
546 return printExceptions;
547}
548
549void Interpreter::setShouldPrintExceptions(bool print)
550{
551 printExceptions = print;
552}
553
554void Interpreter::saveBuiltins (SavedBuiltins& builtins) const
555{
556 if (!builtins._internal)
557 builtins._internal = new SavedBuiltinsInternal;
558
559 builtins._internal->m_Object = m_Object;
560 builtins._internal->m_Function = m_Function;
561 builtins._internal->m_Array = m_Array;
562 builtins._internal->m_Boolean = m_Boolean;
563 builtins._internal->m_String = m_String;
564 builtins._internal->m_Number = m_Number;
565 builtins._internal->m_Date = m_Date;
566 builtins._internal->m_RegExp = m_RegExp;
567 builtins._internal->m_Error = m_Error;
568
569 builtins._internal->m_ObjectPrototype = m_ObjectPrototype;
570 builtins._internal->m_FunctionPrototype = m_FunctionPrototype;
571 builtins._internal->m_ArrayPrototype = m_ArrayPrototype;
572 builtins._internal->m_BooleanPrototype = m_BooleanPrototype;
573 builtins._internal->m_StringPrototype = m_StringPrototype;
574 builtins._internal->m_NumberPrototype = m_NumberPrototype;
575 builtins._internal->m_DatePrototype = m_DatePrototype;
576 builtins._internal->m_RegExpPrototype = m_RegExpPrototype;
577 builtins._internal->m_ErrorPrototype = m_ErrorPrototype;
578
579 builtins._internal->m_EvalError = m_EvalError;
580 builtins._internal->m_RangeError = m_RangeError;
581 builtins._internal->m_ReferenceError = m_ReferenceError;
582 builtins._internal->m_SyntaxError = m_SyntaxError;
583 builtins._internal->m_TypeError = m_TypeError;
584 builtins._internal->m_UriError = m_UriError;
585
586 builtins._internal->m_EvalErrorPrototype = m_EvalErrorPrototype;
587 builtins._internal->m_RangeErrorPrototype = m_RangeErrorPrototype;
588 builtins._internal->m_ReferenceErrorPrototype = m_ReferenceErrorPrototype;
589 builtins._internal->m_SyntaxErrorPrototype = m_SyntaxErrorPrototype;
590 builtins._internal->m_TypeErrorPrototype = m_TypeErrorPrototype;
591 builtins._internal->m_UriErrorPrototype = m_UriErrorPrototype;
592}
593
594void Interpreter::restoreBuiltins (const SavedBuiltins& builtins)
595{
596 if (!builtins._internal)
597 return;
598
599 m_Object = builtins._internal->m_Object;
600 m_Function = builtins._internal->m_Function;
601 m_Array = builtins._internal->m_Array;
602 m_Boolean = builtins._internal->m_Boolean;
603 m_String = builtins._internal->m_String;
604 m_Number = builtins._internal->m_Number;
605 m_Date = builtins._internal->m_Date;
606 m_RegExp = builtins._internal->m_RegExp;
607 m_Error = builtins._internal->m_Error;
608
609 m_ObjectPrototype = builtins._internal->m_ObjectPrototype;
610 m_FunctionPrototype = builtins._internal->m_FunctionPrototype;
611 m_ArrayPrototype = builtins._internal->m_ArrayPrototype;
612 m_BooleanPrototype = builtins._internal->m_BooleanPrototype;
613 m_StringPrototype = builtins._internal->m_StringPrototype;
614 m_NumberPrototype = builtins._internal->m_NumberPrototype;
615 m_DatePrototype = builtins._internal->m_DatePrototype;
616 m_RegExpPrototype = builtins._internal->m_RegExpPrototype;
617 m_ErrorPrototype = builtins._internal->m_ErrorPrototype;
618
619 m_EvalError = builtins._internal->m_EvalError;
620 m_RangeError = builtins._internal->m_RangeError;
621 m_ReferenceError = builtins._internal->m_ReferenceError;
622 m_SyntaxError = builtins._internal->m_SyntaxError;
623 m_TypeError = builtins._internal->m_TypeError;
624 m_UriError = builtins._internal->m_UriError;
625
626 m_EvalErrorPrototype = builtins._internal->m_EvalErrorPrototype;
627 m_RangeErrorPrototype = builtins._internal->m_RangeErrorPrototype;
628 m_ReferenceErrorPrototype = builtins._internal->m_ReferenceErrorPrototype;
629 m_SyntaxErrorPrototype = builtins._internal->m_SyntaxErrorPrototype;
630 m_TypeErrorPrototype = builtins._internal->m_TypeErrorPrototype;
631 m_UriErrorPrototype = builtins._internal->m_UriErrorPrototype;
632}
633
634void Interpreter::startTimeoutCheck()
635{
636 if (m_timeoutCheckCount == 0)
637 resetTimeoutCheck();
638
639 m_timeoutCheckCount++;
640}
641
642void Interpreter::stopTimeoutCheck()
643{
644 m_timeoutCheckCount--;
645}
646
647void Interpreter::resetTimeoutCheck()
648{
649 m_tickCount = 0;
650 m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
651 m_timeAtLastCheckTimeout = 0;
652 m_timeExecuting = 0;
653}
654
655// Returns the current time in milliseconds
656// It doesn't matter what "current time" is here, just as long as
657// it's possible to measure the time difference correctly.
658static inline unsigned getCurrentTime() {
659#if HAVE(SYS_TIME_H)
660 struct timeval tv;
661 gettimeofday(&tv, 0);
662 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
663#elif PLATFORM(QT)
664 QDateTime t = QDateTime::currentDateTime();
665 return t.toTime_t() * 1000 + t.time().msec();
666#elif PLATFORM(WIN_OS)
667 return timeGetTime();
668#else
669#error Platform does not have getCurrentTime function
670#endif
671}
672
673bool Interpreter::checkTimeout()
674{
675 m_tickCount = 0;
676
677 unsigned currentTime = getCurrentTime();
678
679 if (!m_timeAtLastCheckTimeout) {
680 // Suspicious amount of looping in a script -- start timing it
681 m_timeAtLastCheckTimeout = currentTime;
682 return false;
683 }
684
685 unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout;
686
687 if (timeDiff == 0)
688 timeDiff = 1;
689
690 m_timeExecuting += timeDiff;
691 m_timeAtLastCheckTimeout = currentTime;
692
693 // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in
694 // preferredScriptCheckTimeInterval
695 m_ticksUntilNextTimeoutCheck = (unsigned)((float)preferredScriptCheckTimeInterval / timeDiff) * m_ticksUntilNextTimeoutCheck;
696
697 // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
698 // preferred script check time interval.
699 if (m_ticksUntilNextTimeoutCheck == 0)
700 m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
701
702 if (m_timeoutTime && m_timeExecuting > m_timeoutTime) {
703 if (m_globalObject->shouldInterruptScript())
704 return true;
705
706 resetTimeoutCheck();
707 }
708
709 return false;
710}
711
712
713SavedBuiltins::SavedBuiltins() :
714 _internal(0)
715{
716}
717
718SavedBuiltins::~SavedBuiltins()
719{
720 delete _internal;
721}
722
723}
Note: See TracBrowser for help on using the repository browser.