Unreviewed, rolling out r144074.
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSGlobalData.cpp
1 /*
2  * Copyright (C) 2008, 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "JSGlobalData.h"
31
32 #include "ArgList.h"
33 #include "CodeCache.h"
34 #include "CommonIdentifiers.h"
35 #include "DFGLongLivedState.h"
36 #include "DebuggerActivation.h"
37 #include "FunctionConstructor.h"
38 #include "GCActivityCallback.h"
39 #include "GetterSetter.h"
40 #include "Heap.h"
41 #include "HostCallReturnValue.h"
42 #include "IncrementalSweeper.h"
43 #include "Interpreter.h"
44 #include "JSActivation.h"
45 #include "JSAPIValueWrapper.h"
46 #include "JSArray.h"
47 #include "JSClassRef.h"
48 #include "JSFunction.h"
49 #include "JSLock.h"
50 #include "JSNameScope.h"
51 #include "JSNotAnObject.h"
52 #include "JSPropertyNameIterator.h"
53 #include "JSWithScope.h"
54 #include "Lexer.h"
55 #include "Lookup.h"
56 #include "Nodes.h"
57 #include "ParserArena.h"
58 #include "RegExpCache.h"
59 #include "RegExpObject.h"
60 #include "SourceProviderCache.h"
61 #include "StrictEvalActivation.h"
62 #include "StrongInlines.h"
63 #include "UnlinkedCodeBlock.h"
64 #include <wtf/RetainPtr.h>
65 #include <wtf/Threading.h>
66 #include <wtf/WTFThreadData.h>
67
68 #if ENABLE(DFG_JIT)
69 #include "ConservativeRoots.h"
70 #endif
71
72 #if ENABLE(REGEXP_TRACING)
73 #include "RegExp.h"
74 #endif
75
76 #if USE(CF)
77 #include <CoreFoundation/CoreFoundation.h>
78 #endif
79
80 using namespace WTF;
81
82 namespace JSC {
83
84 extern const HashTable arrayConstructorTable;
85 extern const HashTable arrayPrototypeTable;
86 extern const HashTable booleanPrototypeTable;
87 extern const HashTable jsonTable;
88 extern const HashTable dateTable;
89 extern const HashTable dateConstructorTable;
90 extern const HashTable errorPrototypeTable;
91 extern const HashTable globalObjectTable;
92 extern const HashTable mathTable;
93 extern const HashTable numberConstructorTable;
94 extern const HashTable numberPrototypeTable;
95 JS_EXPORTDATA extern const HashTable objectConstructorTable;
96 extern const HashTable objectPrototypeTable;
97 extern const HashTable privateNamePrototypeTable;
98 extern const HashTable regExpTable;
99 extern const HashTable regExpConstructorTable;
100 extern const HashTable regExpPrototypeTable;
101 extern const HashTable stringTable;
102 extern const HashTable stringConstructorTable;
103
104 // Note: Platform.h will enforce that ENABLE(ASSEMBLER) is true if either
105 // ENABLE(JIT) or ENABLE(YARR_JIT) or both are enabled. The code below
106 // just checks for ENABLE(JIT) or ENABLE(YARR_JIT) with this premise in mind.
107
108 #if ENABLE(ASSEMBLER)
109 static bool enableAssembler(ExecutableAllocator& executableAllocator)
110 {
111     if (!executableAllocator.isValid() || (!Options::useJIT() && !Options::useRegExpJIT()))
112         return false;
113
114 #if USE(CF)
115 #if COMPILER(GCC) && !COMPILER(CLANG)
116     // FIXME: remove this once the EWS have been upgraded to LLVM.
117     // Work around a bug of GCC with strict-aliasing.
118     RetainPtr<CFStringRef> canUseJITKeyRetain(AdoptCF, CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman));
119     CFStringRef canUseJITKey = canUseJITKeyRetain.get();
120 #else
121     CFStringRef canUseJITKey = CFSTR("JavaScriptCoreUseJIT");
122 #endif // COMPILER(GCC) && !COMPILER(CLANG)
123     RetainPtr<CFBooleanRef> canUseJIT(AdoptCF, (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication));
124     if (canUseJIT)
125         return kCFBooleanTrue == canUseJIT.get();
126 #endif
127
128 #if USE(CF) || OS(UNIX)
129     char* canUseJITString = getenv("JavaScriptCoreUseJIT");
130     return !canUseJITString || atoi(canUseJITString);
131 #else
132     return true;
133 #endif
134 }
135 #endif // ENABLE(!ASSEMBLER)
136
137 JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
138     :
139 #if ENABLE(ASSEMBLER)
140       executableAllocator(*this),
141 #endif
142       heap(this, heapType)
143     , globalDataType(globalDataType)
144     , clientData(0)
145     , topCallFrame(CallFrame::noCaller())
146     , arrayConstructorTable(fastNew<HashTable>(JSC::arrayConstructorTable))
147     , arrayPrototypeTable(fastNew<HashTable>(JSC::arrayPrototypeTable))
148     , booleanPrototypeTable(fastNew<HashTable>(JSC::booleanPrototypeTable))
149     , dateTable(fastNew<HashTable>(JSC::dateTable))
150     , dateConstructorTable(fastNew<HashTable>(JSC::dateConstructorTable))
151     , errorPrototypeTable(fastNew<HashTable>(JSC::errorPrototypeTable))
152     , globalObjectTable(fastNew<HashTable>(JSC::globalObjectTable))
153     , jsonTable(fastNew<HashTable>(JSC::jsonTable))
154     , mathTable(fastNew<HashTable>(JSC::mathTable))
155     , numberConstructorTable(fastNew<HashTable>(JSC::numberConstructorTable))
156     , numberPrototypeTable(fastNew<HashTable>(JSC::numberPrototypeTable))
157     , objectConstructorTable(fastNew<HashTable>(JSC::objectConstructorTable))
158     , objectPrototypeTable(fastNew<HashTable>(JSC::objectPrototypeTable))
159     , privateNamePrototypeTable(fastNew<HashTable>(JSC::privateNamePrototypeTable))
160     , regExpTable(fastNew<HashTable>(JSC::regExpTable))
161     , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
162     , regExpPrototypeTable(fastNew<HashTable>(JSC::regExpPrototypeTable))
163     , stringTable(fastNew<HashTable>(JSC::stringTable))
164     , stringConstructorTable(fastNew<HashTable>(JSC::stringConstructorTable))
165     , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable())
166     , propertyNames(new CommonIdentifiers(this))
167     , emptyList(new MarkedArgumentBuffer)
168     , parserArena(adoptPtr(new ParserArena))
169     , keywords(adoptPtr(new Keywords(this)))
170     , interpreter(0)
171     , jsArrayClassInfo(&JSArray::s_info)
172     , jsFinalObjectClassInfo(&JSFinalObject::s_info)
173 #if ENABLE(DFG_JIT)
174     , sizeOfLastScratchBuffer(0)
175 #endif
176     , dynamicGlobalObject(0)
177     , cachedUTCOffset(QNaN)
178     , m_enabledProfiler(0)
179     , m_regExpCache(new RegExpCache(this))
180 #if ENABLE(REGEXP_TRACING)
181     , m_rtTraceList(new RTTraceList())
182 #endif
183 #ifndef NDEBUG
184     , exclusiveThread(0)
185 #endif
186 #if CPU(X86) && ENABLE(JIT)
187     , m_timeoutCount(512)
188 #endif
189     , m_newStringsSinceLastHashConst(0)
190 #if ENABLE(ASSEMBLER)
191     , m_canUseAssembler(enableAssembler(executableAllocator))
192 #endif
193 #if ENABLE(JIT)
194     , m_canUseJIT(m_canUseAssembler && Options::useJIT())
195 #endif
196 #if ENABLE(YARR_JIT)
197     , m_canUseRegExpJIT(m_canUseAssembler && Options::useRegExpJIT())
198 #endif
199 #if ENABLE(GC_VALIDATION)
200     , m_initializingObjectClass(0)
201 #endif
202     , m_inDefineOwnProperty(false)
203     , m_codeCache(CodeCache::create())
204 {
205     interpreter = new Interpreter(*this);
206
207     // Need to be careful to keep everything consistent here
208     JSLockHolder lock(this);
209     IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable);
210     structureStructure.set(*this, Structure::createStructure(*this));
211     structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull()));
212     debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, 0, jsNull()));
213     interruptedExecutionErrorStructure.set(*this, InterruptedExecutionError::createStructure(*this, 0, jsNull()));
214     terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull()));
215     stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull()));
216     notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull()));
217     propertyNameIteratorStructure.set(*this, JSPropertyNameIterator::createStructure(*this, 0, jsNull()));
218     getterSetterStructure.set(*this, GetterSetter::createStructure(*this, 0, jsNull()));
219     apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, 0, jsNull()));
220     JSScopeStructure.set(*this, JSScope::createStructure(*this, 0, jsNull()));
221     executableStructure.set(*this, ExecutableBase::createStructure(*this, 0, jsNull()));
222     nativeExecutableStructure.set(*this, NativeExecutable::createStructure(*this, 0, jsNull()));
223     evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, 0, jsNull()));
224     programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull()));
225     functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull()));
226     regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull()));
227     sharedSymbolTableStructure.set(*this, SharedSymbolTable::createStructure(*this, 0, jsNull()));
228     structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull()));
229     sparseArrayValueMapStructure.set(*this, SparseArrayValueMap::createStructure(*this, 0, jsNull()));
230     withScopeStructure.set(*this, JSWithScope::createStructure(*this, 0, jsNull()));
231     unlinkedFunctionExecutableStructure.set(*this, UnlinkedFunctionExecutable::createStructure(*this, 0, jsNull()));
232     unlinkedProgramCodeBlockStructure.set(*this, UnlinkedProgramCodeBlock::createStructure(*this, 0, jsNull()));
233     unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull()));
234     unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull()));
235     smallStrings.initializeCommonStrings(*this);
236
237     wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable);
238
239 #if ENABLE(JIT)
240     jitStubs = adoptPtr(new JITThunks());
241     performPlatformSpecificJITAssertions(this);
242 #endif
243     
244     interpreter->initialize(this->canUseJIT());
245     
246 #if ENABLE(JIT)
247     initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support.
248 #endif
249
250     heap.notifyIsSafeToCollect();
251
252     LLInt::Data::performAssertions(*this);
253     
254     if (Options::enableProfiler())
255         m_perBytecodeProfiler = adoptPtr(new Profiler::Database(*this));
256
257 #if ENABLE(DFG_JIT)
258     if (canUseJIT())
259         m_dfgState = adoptPtr(new DFG::LongLivedState());
260 #endif
261 }
262
263 JSGlobalData::~JSGlobalData()
264 {
265     // Clear this first to ensure that nobody tries to remove themselves from it.
266     m_perBytecodeProfiler.clear();
267     
268     ASSERT(!m_apiLock.currentThreadIsHoldingLock());
269     heap.didStartVMShutdown();
270
271     delete interpreter;
272 #ifndef NDEBUG
273     interpreter = reinterpret_cast<Interpreter*>(0xbbadbeef);
274 #endif
275
276     arrayPrototypeTable->deleteTable();
277     arrayConstructorTable->deleteTable();
278     booleanPrototypeTable->deleteTable();
279     dateTable->deleteTable();
280     dateConstructorTable->deleteTable();
281     errorPrototypeTable->deleteTable();
282     globalObjectTable->deleteTable();
283     jsonTable->deleteTable();
284     mathTable->deleteTable();
285     numberConstructorTable->deleteTable();
286     numberPrototypeTable->deleteTable();
287     objectConstructorTable->deleteTable();
288     objectPrototypeTable->deleteTable();
289     privateNamePrototypeTable->deleteTable();
290     regExpTable->deleteTable();
291     regExpConstructorTable->deleteTable();
292     regExpPrototypeTable->deleteTable();
293     stringTable->deleteTable();
294     stringConstructorTable->deleteTable();
295
296     fastDelete(const_cast<HashTable*>(arrayConstructorTable));
297     fastDelete(const_cast<HashTable*>(arrayPrototypeTable));
298     fastDelete(const_cast<HashTable*>(booleanPrototypeTable));
299     fastDelete(const_cast<HashTable*>(dateTable));
300     fastDelete(const_cast<HashTable*>(dateConstructorTable));
301     fastDelete(const_cast<HashTable*>(errorPrototypeTable));
302     fastDelete(const_cast<HashTable*>(globalObjectTable));
303     fastDelete(const_cast<HashTable*>(jsonTable));
304     fastDelete(const_cast<HashTable*>(mathTable));
305     fastDelete(const_cast<HashTable*>(numberConstructorTable));
306     fastDelete(const_cast<HashTable*>(numberPrototypeTable));
307     fastDelete(const_cast<HashTable*>(objectConstructorTable));
308     fastDelete(const_cast<HashTable*>(objectPrototypeTable));
309     fastDelete(const_cast<HashTable*>(privateNamePrototypeTable));
310     fastDelete(const_cast<HashTable*>(regExpTable));
311     fastDelete(const_cast<HashTable*>(regExpConstructorTable));
312     fastDelete(const_cast<HashTable*>(regExpPrototypeTable));
313     fastDelete(const_cast<HashTable*>(stringTable));
314     fastDelete(const_cast<HashTable*>(stringConstructorTable));
315
316     opaqueJSClassData.clear();
317
318     delete emptyList;
319
320     delete propertyNames;
321     if (globalDataType != Default)
322         deleteIdentifierTable(identifierTable);
323
324     delete clientData;
325     delete m_regExpCache;
326 #if ENABLE(REGEXP_TRACING)
327     delete m_rtTraceList;
328 #endif
329
330 #if ENABLE(DFG_JIT)
331     for (unsigned i = 0; i < scratchBuffers.size(); ++i)
332         fastFree(scratchBuffers[i]);
333 #endif
334 }
335
336 PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(HeapType heapType)
337 {
338     return adoptRef(new JSGlobalData(APIContextGroup, heapType));
339 }
340
341 PassRefPtr<JSGlobalData> JSGlobalData::create(HeapType heapType)
342 {
343     return adoptRef(new JSGlobalData(Default, heapType));
344 }
345
346 PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(HeapType heapType)
347 {
348     return create(heapType);
349 }
350
351 bool JSGlobalData::sharedInstanceExists()
352 {
353     return sharedInstanceInternal();
354 }
355
356 JSGlobalData& JSGlobalData::sharedInstance()
357 {
358     GlobalJSLock globalLock;
359     JSGlobalData*& instance = sharedInstanceInternal();
360     if (!instance) {
361         instance = adoptRef(new JSGlobalData(APIShared, SmallHeap)).leakRef();
362         instance->makeUsableFromMultipleThreads();
363     }
364     return *instance;
365 }
366
367 JSGlobalData*& JSGlobalData::sharedInstanceInternal()
368 {
369     static JSGlobalData* sharedInstance;
370     return sharedInstance;
371 }
372
373 #if ENABLE(JIT)
374 static ThunkGenerator thunkGeneratorForIntrinsic(Intrinsic intrinsic)
375 {
376     switch (intrinsic) {
377     case CharCodeAtIntrinsic:
378         return charCodeAtThunkGenerator;
379     case CharAtIntrinsic:
380         return charAtThunkGenerator;
381     case FromCharCodeIntrinsic:
382         return fromCharCodeThunkGenerator;
383     case SqrtIntrinsic:
384         return sqrtThunkGenerator;
385     case PowIntrinsic:
386         return powThunkGenerator;
387     case AbsIntrinsic:
388         return absThunkGenerator;
389     case FloorIntrinsic:
390         return floorThunkGenerator;
391     case CeilIntrinsic:
392         return ceilThunkGenerator;
393     case RoundIntrinsic:
394         return roundThunkGenerator;
395     case ExpIntrinsic:
396         return expThunkGenerator;
397     case LogIntrinsic:
398         return logThunkGenerator;
399     default:
400         return 0;
401     }
402 }
403
404 NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, NativeFunction constructor)
405 {
406     return jitStubs->hostFunctionStub(this, function, constructor);
407 }
408 NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, Intrinsic intrinsic)
409 {
410     ASSERT(canUseJIT());
411     return jitStubs->hostFunctionStub(this, function, intrinsic != NoIntrinsic ? thunkGeneratorForIntrinsic(intrinsic) : 0, intrinsic);
412 }
413
414 #else // !ENABLE(JIT)
415 NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, NativeFunction constructor)
416 {
417     return NativeExecutable::create(*this, function, constructor);
418 }
419 #endif // !ENABLE(JIT)
420
421 JSGlobalData::ClientData::~ClientData()
422 {
423 }
424
425 void JSGlobalData::resetDateCache()
426 {
427     cachedUTCOffset = QNaN;
428     dstOffsetCache.reset();
429     cachedDateString = String();
430     cachedDateStringValue = QNaN;
431     dateInstanceCache.reset();
432 }
433
434 void JSGlobalData::startSampling()
435 {
436     interpreter->startSampling();
437 }
438
439 void JSGlobalData::stopSampling()
440 {
441     interpreter->stopSampling();
442 }
443
444 void JSGlobalData::discardAllCode()
445 {
446     m_codeCache->clear();
447     heap.deleteAllCompiledCode();
448     heap.reportAbandonedObjectGraph();
449 }
450
451 void JSGlobalData::dumpSampleData(ExecState* exec)
452 {
453     interpreter->dumpSampleData(exec);
454 #if ENABLE(ASSEMBLER)
455     ExecutableAllocator::dumpProfile();
456 #endif
457 }
458
459 SourceProviderCache* JSGlobalData::addSourceProviderCache(SourceProvider* sourceProvider)
460 {
461     SourceProviderCacheMap::AddResult addResult = sourceProviderCacheMap.add(sourceProvider, 0);
462     if (addResult.isNewEntry)
463         addResult.iterator->value = adoptRef(new SourceProviderCache);
464     return addResult.iterator->value.get();
465 }
466
467 void JSGlobalData::clearSourceProviderCaches()
468 {
469     sourceProviderCacheMap.clear();
470 }
471
472 struct StackPreservingRecompiler : public MarkedBlock::VoidFunctor {
473     HashSet<FunctionExecutable*> currentlyExecutingFunctions;
474     void operator()(JSCell* cell)
475     {
476         if (!cell->inherits(&FunctionExecutable::s_info))
477             return;
478         FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell);
479         if (currentlyExecutingFunctions.contains(executable))
480             return;
481         executable->clearCodeIfNotCompiling();
482     }
483 };
484
485 void JSGlobalData::releaseExecutableMemory()
486 {
487     if (dynamicGlobalObject) {
488         StackPreservingRecompiler recompiler;
489         HashSet<JSCell*> roots;
490         heap.getConservativeRegisterRoots(roots);
491         HashSet<JSCell*>::iterator end = roots.end();
492         for (HashSet<JSCell*>::iterator ptr = roots.begin(); ptr != end; ++ptr) {
493             ScriptExecutable* executable = 0;
494             JSCell* cell = *ptr;
495             if (cell->inherits(&ScriptExecutable::s_info))
496                 executable = static_cast<ScriptExecutable*>(*ptr);
497             else if (cell->inherits(&JSFunction::s_info)) {
498                 JSFunction* function = jsCast<JSFunction*>(*ptr);
499                 if (function->isHostFunction())
500                     continue;
501                 executable = function->jsExecutable();
502             } else
503                 continue;
504             ASSERT(executable->inherits(&ScriptExecutable::s_info));
505             executable->unlinkCalls();
506             if (executable->inherits(&FunctionExecutable::s_info))
507                 recompiler.currentlyExecutingFunctions.add(static_cast<FunctionExecutable*>(executable));
508                 
509         }
510         heap.objectSpace().forEachLiveCell<StackPreservingRecompiler>(recompiler);
511     }
512     m_regExpCache->invalidateCode();
513     heap.collectAllGarbage();
514 }
515     
516 void releaseExecutableMemory(JSGlobalData& globalData)
517 {
518     globalData.releaseExecutableMemory();
519 }
520
521 #if ENABLE(DFG_JIT)
522 void JSGlobalData::gatherConservativeRoots(ConservativeRoots& conservativeRoots)
523 {
524     for (size_t i = 0; i < scratchBuffers.size(); i++) {
525         ScratchBuffer* scratchBuffer = scratchBuffers[i];
526         if (scratchBuffer->activeLength()) {
527             void* bufferStart = scratchBuffer->dataBuffer();
528             conservativeRoots.add(bufferStart, static_cast<void*>(static_cast<char*>(bufferStart) + scratchBuffer->activeLength()));
529         }
530     }
531 }
532 #endif
533
534 #if ENABLE(REGEXP_TRACING)
535 void JSGlobalData::addRegExpToTrace(RegExp* regExp)
536 {
537     m_rtTraceList->add(regExp);
538 }
539
540 void JSGlobalData::dumpRegExpTrace()
541 {
542     // The first RegExp object is ignored.  It is create by the RegExpPrototype ctor and not used.
543     RTTraceList::iterator iter = ++m_rtTraceList->begin();
544     
545     if (iter != m_rtTraceList->end()) {
546         dataLogF("\nRegExp Tracing\n");
547         dataLogF("                                                            match()    matches\n");
548         dataLogF("Regular Expression                          JIT Address      calls      found\n");
549         dataLogF("----------------------------------------+----------------+----------+----------\n");
550     
551         unsigned reCount = 0;
552     
553         for (; iter != m_rtTraceList->end(); ++iter, ++reCount)
554             (*iter)->printTraceData();
555
556         dataLogF("%d Regular Expressions\n", reCount);
557     }
558     
559     m_rtTraceList->clear();
560 }
561 #else
562 void JSGlobalData::dumpRegExpTrace()
563 {
564 }
565 #endif
566
567 } // namespace JSC