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