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

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

Fix: <rdar://problem/5607032> (REGRESSION: testapi exits with assertion failure in debug build) and <rdar://problem/5440659> (JSGlobalContextCreate throws away globalObjectClass's prototype)

Split Interpreter's initialization into two distinct steps: the creation of the global prototypes
and constructors, and storing them on the global object. This allows JSClassRef's passed to
JSGlobalContextCreate to be instantiated with the correct prototype.

Reviewed by Darin Adler.

  • Property svn:eol-style set to native
File size: 27.7 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_currentExec(0)
86 , m_globalObject(0)
87 , m_globalExec(this, 0, 0, 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(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
311ExecState* Interpreter::globalExec()
312{
313 return &m_globalExec;
314}
315
316Completion Interpreter::checkSyntax(const UString& sourceURL, int startingLineNumber, const UString& code)
317{
318 return checkSyntax(sourceURL, startingLineNumber, code.data(), code.size());
319}
320
321Completion Interpreter::checkSyntax(const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength)
322{
323 JSLock lock;
324
325 int errLine;
326 UString errMsg;
327 RefPtr<ProgramNode> progNode = parser().parseProgram(sourceURL, startingLineNumber, code, codeLength, 0, &errLine, &errMsg);
328 if (!progNode)
329 return Completion(Throw, Error::create(&m_globalExec, SyntaxError, errMsg, errLine, 0, sourceURL));
330 return Completion(Normal);
331}
332
333Completion Interpreter::evaluate(const UString& sourceURL, int startingLineNumber, const UString& code, JSValue* thisV)
334{
335 return evaluate(sourceURL, startingLineNumber, code.data(), code.size(), thisV);
336}
337
338Completion Interpreter::evaluate(const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength, JSValue* thisV)
339{
340 JSLock lock;
341
342 // prevent against infinite recursion
343 if (m_recursion >= 20)
344 return Completion(Throw, Error::create(&m_globalExec, GeneralError, "Recursion too deep"));
345
346 // parse the source code
347 int sourceId;
348 int errLine;
349 UString errMsg;
350 RefPtr<ProgramNode> progNode = parser().parseProgram(sourceURL, startingLineNumber, code, codeLength, &sourceId, &errLine, &errMsg);
351
352 // notify debugger that source has been parsed
353 if (m_debugger) {
354 bool cont = m_debugger->sourceParsed(&m_globalExec, sourceId, sourceURL, UString(code, codeLength), startingLineNumber, errLine, errMsg);
355 if (!cont)
356 return Completion(Break);
357 }
358
359 // no program node means a syntax error occurred
360 if (!progNode)
361 return Completion(Throw, Error::create(&m_globalExec, SyntaxError, errMsg, errLine, sourceId, sourceURL));
362
363 m_globalExec.clearException();
364
365 m_recursion++;
366
367 JSGlobalObject* globalObj = m_globalObject;
368 JSObject* thisObj = globalObj;
369
370 // "this" must be an object... use same rules as Function.prototype.apply()
371 if (thisV && !thisV->isUndefinedOrNull())
372 thisObj = thisV->toObject(&m_globalExec);
373
374 Completion res;
375 if (m_globalExec.hadException())
376 // the thisV->toObject() conversion above might have thrown an exception - if so, propagate it
377 res = Completion(Throw, m_globalExec.exception());
378 else {
379 // execute the code
380 ExecState newExec(this, globalObj, thisObj, progNode.get());
381 res = progNode->execute(&newExec);
382 }
383
384 m_recursion--;
385
386 if (shouldPrintExceptions() && res.complType() == Throw) {
387 JSLock lock;
388 ExecState* exec = globalExec();
389 CString f = sourceURL.UTF8String();
390 CString message = res.value()->toObject(exec)->toString(exec).UTF8String();
391 int line = res.value()->toObject(exec)->get(exec, "line")->toUInt32(exec);
392#if PLATFORM(WIN_OS)
393 printf("%s line %d: %s\n", f.c_str(), line, message.c_str());
394#else
395 printf("[%d] %s line %d: %s\n", getpid(), f.c_str(), line, message.c_str());
396#endif
397 }
398
399 return res;
400}
401
402JSObject *Interpreter::builtinObject() const
403{
404 return m_Object;
405}
406
407JSObject *Interpreter::builtinFunction() const
408{
409 return m_Function;
410}
411
412JSObject *Interpreter::builtinArray() const
413{
414 return m_Array;
415}
416
417JSObject *Interpreter::builtinBoolean() const
418{
419 return m_Boolean;
420}
421
422JSObject *Interpreter::builtinString() const
423{
424 return m_String;
425}
426
427JSObject *Interpreter::builtinNumber() const
428{
429 return m_Number;
430}
431
432JSObject *Interpreter::builtinDate() const
433{
434 return m_Date;
435}
436
437JSObject *Interpreter::builtinError() const
438{
439 return m_Error;
440}
441
442JSObject *Interpreter::builtinObjectPrototype() const
443{
444 return m_ObjectPrototype;
445}
446
447JSObject *Interpreter::builtinFunctionPrototype() const
448{
449 return m_FunctionPrototype;
450}
451
452JSObject *Interpreter::builtinArrayPrototype() const
453{
454 return m_ArrayPrototype;
455}
456
457JSObject *Interpreter::builtinBooleanPrototype() const
458{
459 return m_BooleanPrototype;
460}
461
462JSObject *Interpreter::builtinStringPrototype() const
463{
464 return m_StringPrototype;
465}
466
467JSObject *Interpreter::builtinNumberPrototype() const
468{
469 return m_NumberPrototype;
470}
471
472JSObject *Interpreter::builtinDatePrototype() const
473{
474 return m_DatePrototype;
475}
476
477JSObject *Interpreter::builtinRegExpPrototype() const
478{
479 return m_RegExpPrototype;
480}
481
482JSObject *Interpreter::builtinErrorPrototype() const
483{
484 return m_ErrorPrototype;
485}
486
487JSObject *Interpreter::builtinEvalError() const
488{
489 return m_EvalError;
490}
491
492JSObject *Interpreter::builtinRangeError() const
493{
494 return m_RangeError;
495}
496
497JSObject *Interpreter::builtinReferenceError() const
498{
499 return m_ReferenceError;
500}
501
502JSObject *Interpreter::builtinSyntaxError() const
503{
504 return m_SyntaxError;
505}
506
507JSObject *Interpreter::builtinTypeError() const
508{
509 return m_TypeError;
510}
511
512JSObject *Interpreter::builtinURIError() const
513{
514 return m_UriError;
515}
516
517JSObject *Interpreter::builtinEvalErrorPrototype() const
518{
519 return m_EvalErrorPrototype;
520}
521
522JSObject *Interpreter::builtinRangeErrorPrototype() const
523{
524 return m_RangeErrorPrototype;
525}
526
527JSObject *Interpreter::builtinReferenceErrorPrototype() const
528{
529 return m_ReferenceErrorPrototype;
530}
531
532JSObject *Interpreter::builtinSyntaxErrorPrototype() const
533{
534 return m_SyntaxErrorPrototype;
535}
536
537JSObject *Interpreter::builtinTypeErrorPrototype() const
538{
539 return m_TypeErrorPrototype;
540}
541
542JSObject *Interpreter::builtinURIErrorPrototype() const
543{
544 return m_UriErrorPrototype;
545}
546
547void Interpreter::mark()
548{
549 if (m_currentExec)
550 m_currentExec->mark();
551
552 if (m_globalExec.exception() && !m_globalExec.exception()->marked())
553 m_globalExec.exception()->mark();
554
555 if (m_globalObject && !m_globalObject->marked())
556 m_globalObject->mark();
557
558 if (m_Object && !m_Object->marked())
559 m_Object->mark();
560 if (m_Function && !m_Function->marked())
561 m_Function->mark();
562 if (m_Array && !m_Array->marked())
563 m_Array->mark();
564 if (m_Boolean && !m_Boolean->marked())
565 m_Boolean->mark();
566 if (m_String && !m_String->marked())
567 m_String->mark();
568 if (m_Number && !m_Number->marked())
569 m_Number->mark();
570 if (m_Date && !m_Date->marked())
571 m_Date->mark();
572 if (m_RegExp && !m_RegExp->marked())
573 m_RegExp->mark();
574 if (m_Error && !m_Error->marked())
575 m_Error->mark();
576
577 if (m_ObjectPrototype && !m_ObjectPrototype->marked())
578 m_ObjectPrototype->mark();
579 if (m_FunctionPrototype && !m_FunctionPrototype->marked())
580 m_FunctionPrototype->mark();
581 if (m_ArrayPrototype && !m_ArrayPrototype->marked())
582 m_ArrayPrototype->mark();
583 if (m_BooleanPrototype && !m_BooleanPrototype->marked())
584 m_BooleanPrototype->mark();
585 if (m_StringPrototype && !m_StringPrototype->marked())
586 m_StringPrototype->mark();
587 if (m_NumberPrototype && !m_NumberPrototype->marked())
588 m_NumberPrototype->mark();
589 if (m_DatePrototype && !m_DatePrototype->marked())
590 m_DatePrototype->mark();
591 if (m_RegExpPrototype && !m_RegExpPrototype->marked())
592 m_RegExpPrototype->mark();
593 if (m_ErrorPrototype && !m_ErrorPrototype->marked())
594 m_ErrorPrototype->mark();
595
596 if (m_EvalError && !m_EvalError->marked())
597 m_EvalError->mark();
598 if (m_RangeError && !m_RangeError->marked())
599 m_RangeError->mark();
600 if (m_ReferenceError && !m_ReferenceError->marked())
601 m_ReferenceError->mark();
602 if (m_SyntaxError && !m_SyntaxError->marked())
603 m_SyntaxError->mark();
604 if (m_TypeError && !m_TypeError->marked())
605 m_TypeError->mark();
606 if (m_UriError && !m_UriError->marked())
607 m_UriError->mark();
608
609 if (m_EvalErrorPrototype && !m_EvalErrorPrototype->marked())
610 m_EvalErrorPrototype->mark();
611 if (m_RangeErrorPrototype && !m_RangeErrorPrototype->marked())
612 m_RangeErrorPrototype->mark();
613 if (m_ReferenceErrorPrototype && !m_ReferenceErrorPrototype->marked())
614 m_ReferenceErrorPrototype->mark();
615 if (m_SyntaxErrorPrototype && !m_SyntaxErrorPrototype->marked())
616 m_SyntaxErrorPrototype->mark();
617 if (m_TypeErrorPrototype && !m_TypeErrorPrototype->marked())
618 m_TypeErrorPrototype->mark();
619 if (m_UriErrorPrototype && !m_UriErrorPrototype->marked())
620 m_UriErrorPrototype->mark();
621}
622
623static bool printExceptions = false;
624
625bool Interpreter::shouldPrintExceptions()
626{
627 return printExceptions;
628}
629
630void Interpreter::setShouldPrintExceptions(bool print)
631{
632 printExceptions = print;
633}
634
635void Interpreter::saveBuiltins (SavedBuiltins& builtins) const
636{
637 if (!builtins._internal)
638 builtins._internal = new SavedBuiltinsInternal;
639
640 builtins._internal->m_Object = m_Object;
641 builtins._internal->m_Function = m_Function;
642 builtins._internal->m_Array = m_Array;
643 builtins._internal->m_Boolean = m_Boolean;
644 builtins._internal->m_String = m_String;
645 builtins._internal->m_Number = m_Number;
646 builtins._internal->m_Date = m_Date;
647 builtins._internal->m_RegExp = m_RegExp;
648 builtins._internal->m_Error = m_Error;
649
650 builtins._internal->m_ObjectPrototype = m_ObjectPrototype;
651 builtins._internal->m_FunctionPrototype = m_FunctionPrototype;
652 builtins._internal->m_ArrayPrototype = m_ArrayPrototype;
653 builtins._internal->m_BooleanPrototype = m_BooleanPrototype;
654 builtins._internal->m_StringPrototype = m_StringPrototype;
655 builtins._internal->m_NumberPrototype = m_NumberPrototype;
656 builtins._internal->m_DatePrototype = m_DatePrototype;
657 builtins._internal->m_RegExpPrototype = m_RegExpPrototype;
658 builtins._internal->m_ErrorPrototype = m_ErrorPrototype;
659
660 builtins._internal->m_EvalError = m_EvalError;
661 builtins._internal->m_RangeError = m_RangeError;
662 builtins._internal->m_ReferenceError = m_ReferenceError;
663 builtins._internal->m_SyntaxError = m_SyntaxError;
664 builtins._internal->m_TypeError = m_TypeError;
665 builtins._internal->m_UriError = m_UriError;
666
667 builtins._internal->m_EvalErrorPrototype = m_EvalErrorPrototype;
668 builtins._internal->m_RangeErrorPrototype = m_RangeErrorPrototype;
669 builtins._internal->m_ReferenceErrorPrototype = m_ReferenceErrorPrototype;
670 builtins._internal->m_SyntaxErrorPrototype = m_SyntaxErrorPrototype;
671 builtins._internal->m_TypeErrorPrototype = m_TypeErrorPrototype;
672 builtins._internal->m_UriErrorPrototype = m_UriErrorPrototype;
673}
674
675void Interpreter::restoreBuiltins (const SavedBuiltins& builtins)
676{
677 if (!builtins._internal)
678 return;
679
680 m_Object = builtins._internal->m_Object;
681 m_Function = builtins._internal->m_Function;
682 m_Array = builtins._internal->m_Array;
683 m_Boolean = builtins._internal->m_Boolean;
684 m_String = builtins._internal->m_String;
685 m_Number = builtins._internal->m_Number;
686 m_Date = builtins._internal->m_Date;
687 m_RegExp = builtins._internal->m_RegExp;
688 m_Error = builtins._internal->m_Error;
689
690 m_ObjectPrototype = builtins._internal->m_ObjectPrototype;
691 m_FunctionPrototype = builtins._internal->m_FunctionPrototype;
692 m_ArrayPrototype = builtins._internal->m_ArrayPrototype;
693 m_BooleanPrototype = builtins._internal->m_BooleanPrototype;
694 m_StringPrototype = builtins._internal->m_StringPrototype;
695 m_NumberPrototype = builtins._internal->m_NumberPrototype;
696 m_DatePrototype = builtins._internal->m_DatePrototype;
697 m_RegExpPrototype = builtins._internal->m_RegExpPrototype;
698 m_ErrorPrototype = builtins._internal->m_ErrorPrototype;
699
700 m_EvalError = builtins._internal->m_EvalError;
701 m_RangeError = builtins._internal->m_RangeError;
702 m_ReferenceError = builtins._internal->m_ReferenceError;
703 m_SyntaxError = builtins._internal->m_SyntaxError;
704 m_TypeError = builtins._internal->m_TypeError;
705 m_UriError = builtins._internal->m_UriError;
706
707 m_EvalErrorPrototype = builtins._internal->m_EvalErrorPrototype;
708 m_RangeErrorPrototype = builtins._internal->m_RangeErrorPrototype;
709 m_ReferenceErrorPrototype = builtins._internal->m_ReferenceErrorPrototype;
710 m_SyntaxErrorPrototype = builtins._internal->m_SyntaxErrorPrototype;
711 m_TypeErrorPrototype = builtins._internal->m_TypeErrorPrototype;
712 m_UriErrorPrototype = builtins._internal->m_UriErrorPrototype;
713}
714
715void Interpreter::startTimeoutCheck()
716{
717 if (m_timeoutCheckCount == 0)
718 resetTimeoutCheck();
719
720 m_timeoutCheckCount++;
721}
722
723void Interpreter::stopTimeoutCheck()
724{
725 m_timeoutCheckCount--;
726}
727
728void Interpreter::resetTimeoutCheck()
729{
730 m_tickCount = 0;
731 m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
732 m_timeAtLastCheckTimeout = 0;
733 m_timeExecuting = 0;
734}
735
736// Returns the current time in milliseconds
737// It doesn't matter what "current time" is here, just as long as
738// it's possible to measure the time difference correctly.
739static inline unsigned getCurrentTime() {
740#if HAVE(SYS_TIME_H)
741 struct timeval tv;
742 gettimeofday(&tv, 0);
743 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
744#elif PLATFORM(QT)
745 QDateTime t = QDateTime::currentDateTime();
746 return t.toTime_t() * 1000 + t.time().msec();
747#elif PLATFORM(WIN_OS)
748 return timeGetTime();
749#else
750#error Platform does not have getCurrentTime function
751#endif
752}
753
754bool Interpreter::checkTimeout()
755{
756 m_tickCount = 0;
757
758 unsigned currentTime = getCurrentTime();
759
760 if (!m_timeAtLastCheckTimeout) {
761 // Suspicious amount of looping in a script -- start timing it
762 m_timeAtLastCheckTimeout = currentTime;
763 return false;
764 }
765
766 unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout;
767
768 if (timeDiff == 0)
769 timeDiff = 1;
770
771 m_timeExecuting += timeDiff;
772 m_timeAtLastCheckTimeout = currentTime;
773
774 // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in
775 // preferredScriptCheckTimeInterval
776 m_ticksUntilNextTimeoutCheck = (unsigned)((float)preferredScriptCheckTimeInterval / timeDiff) * m_ticksUntilNextTimeoutCheck;
777
778 // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
779 // preferred script check time interval.
780 if (m_ticksUntilNextTimeoutCheck == 0)
781 m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
782
783 if (m_timeoutTime && m_timeExecuting > m_timeoutTime) {
784 if (shouldInterruptScript())
785 return true;
786
787 resetTimeoutCheck();
788 }
789
790 return false;
791}
792
793
794SavedBuiltins::SavedBuiltins() :
795 _internal(0)
796{
797}
798
799SavedBuiltins::~SavedBuiltins()
800{
801 delete _internal;
802}
803
804}
Note: See TracBrowser for help on using the repository browser.