initial import
[vuplus_webkit] / 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 "Heap.h"
34 #include "CommonIdentifiers.h"
35 #include "DebuggerActivation.h"
36 #include "FunctionConstructor.h"
37 #include "GetterSetter.h"
38 #include "Interpreter.h"
39 #include "JSActivation.h"
40 #include "JSAPIValueWrapper.h"
41 #include "JSArray.h"
42 #include "JSByteArray.h"
43 #include "JSClassRef.h"
44 #include "JSFunction.h"
45 #include "JSLock.h"
46 #include "JSNotAnObject.h"
47 #include "JSPropertyNameIterator.h"
48 #include "JSStaticScopeObject.h"
49 #include "Lexer.h"
50 #include "Lookup.h"
51 #include "Nodes.h"
52 #include "Parser.h"
53 #include "RegExpCache.h"
54 #include "RegExpObject.h"
55 #include "StrictEvalActivation.h"
56 #include <wtf/WTFThreadData.h>
57 #if ENABLE(REGEXP_TRACING)
58 #include "RegExp.h"
59 #endif
60
61
62 #if ENABLE(JSC_MULTIPLE_THREADS)
63 #include <wtf/Threading.h>
64 #endif
65
66 #if PLATFORM(MAC)
67 #include "ProfilerServer.h"
68 #include <CoreFoundation/CoreFoundation.h>
69 #endif
70
71 using namespace WTF;
72
73 namespace {
74
75 using namespace JSC;
76
77 class Recompiler : public MarkedBlock::VoidFunctor {
78 public:
79     void operator()(JSCell*);
80 };
81
82 inline void Recompiler::operator()(JSCell* cell)
83 {
84     if (!cell->inherits(&JSFunction::s_info))
85         return;
86     JSFunction* function = asFunction(cell);
87     if (!function->executable() || function->executable()->isHostFunction())
88         return;
89     function->jsExecutable()->discardCode();
90 }
91
92 } // namespace
93
94 namespace JSC {
95
96 extern JSC_CONST_HASHTABLE HashTable arrayConstructorTable;
97 extern JSC_CONST_HASHTABLE HashTable arrayPrototypeTable;
98 extern JSC_CONST_HASHTABLE HashTable booleanPrototypeTable;
99 extern JSC_CONST_HASHTABLE HashTable jsonTable;
100 extern JSC_CONST_HASHTABLE HashTable dateTable;
101 extern JSC_CONST_HASHTABLE HashTable dateConstructorTable;
102 extern JSC_CONST_HASHTABLE HashTable errorPrototypeTable;
103 extern JSC_CONST_HASHTABLE HashTable globalObjectTable;
104 extern JSC_CONST_HASHTABLE HashTable mathTable;
105 extern JSC_CONST_HASHTABLE HashTable numberConstructorTable;
106 extern JSC_CONST_HASHTABLE HashTable numberPrototypeTable;
107 extern JSC_CONST_HASHTABLE HashTable objectConstructorTable;
108 extern JSC_CONST_HASHTABLE HashTable objectPrototypeTable;
109 extern JSC_CONST_HASHTABLE HashTable regExpTable;
110 extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable;
111 extern JSC_CONST_HASHTABLE HashTable regExpPrototypeTable;
112 extern JSC_CONST_HASHTABLE HashTable stringTable;
113 extern JSC_CONST_HASHTABLE HashTable stringConstructorTable;
114
115 void* JSGlobalData::jsFinalObjectVPtr;
116 void* JSGlobalData::jsArrayVPtr;
117 void* JSGlobalData::jsByteArrayVPtr;
118 void* JSGlobalData::jsStringVPtr;
119 void* JSGlobalData::jsFunctionVPtr;
120
121 #if COMPILER(GCC)
122 // Work around for gcc trying to coalesce our reads of the various cell vptrs
123 #define CLOBBER_MEMORY() do { \
124     asm volatile ("" : : : "memory"); \
125 } while (false)
126 #else
127 #define CLOBBER_MEMORY() do { } while (false)
128 #endif
129
130 void JSGlobalData::storeVPtrs()
131 {
132     // Enough storage to fit a JSArray, JSByteArray, JSString, or JSFunction.
133     // COMPILE_ASSERTS below check that this is true.
134     char storage[64];
135
136     COMPILE_ASSERT(sizeof(JSFinalObject) <= sizeof(storage), sizeof_JSFinalObject_must_be_less_than_storage);
137     JSCell* jsFinalObject = new (storage) JSFinalObject(JSFinalObject::VPtrStealingHack);
138     CLOBBER_MEMORY();
139     JSGlobalData::jsFinalObjectVPtr = jsFinalObject->vptr();
140
141     COMPILE_ASSERT(sizeof(JSArray) <= sizeof(storage), sizeof_JSArray_must_be_less_than_storage);
142     JSCell* jsArray = new (storage) JSArray(JSArray::VPtrStealingHack);
143     CLOBBER_MEMORY();
144     JSGlobalData::jsArrayVPtr = jsArray->vptr();
145
146     COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(storage), sizeof_JSByteArray_must_be_less_than_storage);
147     JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
148     CLOBBER_MEMORY();
149     JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
150
151     COMPILE_ASSERT(sizeof(JSString) <= sizeof(storage), sizeof_JSString_must_be_less_than_storage);
152     JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
153     CLOBBER_MEMORY();
154     JSGlobalData::jsStringVPtr = jsString->vptr();
155
156     COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(storage), sizeof_JSFunction_must_be_less_than_storage);
157     JSCell* jsFunction = new (storage) JSFunction(JSCell::VPtrStealingHack);
158     CLOBBER_MEMORY();
159     JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
160 }
161
162 JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType, HeapSize heapSize)
163     : globalDataType(globalDataType)
164     , clientData(0)
165     , topCallFrame(CallFrame::noCaller())
166     , arrayConstructorTable(fastNew<HashTable>(JSC::arrayConstructorTable))
167     , arrayPrototypeTable(fastNew<HashTable>(JSC::arrayPrototypeTable))
168     , booleanPrototypeTable(fastNew<HashTable>(JSC::booleanPrototypeTable))
169     , dateTable(fastNew<HashTable>(JSC::dateTable))
170     , dateConstructorTable(fastNew<HashTable>(JSC::dateConstructorTable))
171     , errorPrototypeTable(fastNew<HashTable>(JSC::errorPrototypeTable))
172     , globalObjectTable(fastNew<HashTable>(JSC::globalObjectTable))
173     , jsonTable(fastNew<HashTable>(JSC::jsonTable))
174     , mathTable(fastNew<HashTable>(JSC::mathTable))
175     , numberConstructorTable(fastNew<HashTable>(JSC::numberConstructorTable))
176     , numberPrototypeTable(fastNew<HashTable>(JSC::numberPrototypeTable))
177     , objectConstructorTable(fastNew<HashTable>(JSC::objectConstructorTable))
178     , objectPrototypeTable(fastNew<HashTable>(JSC::objectPrototypeTable))
179     , regExpTable(fastNew<HashTable>(JSC::regExpTable))
180     , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
181     , regExpPrototypeTable(fastNew<HashTable>(JSC::regExpPrototypeTable))
182     , stringTable(fastNew<HashTable>(JSC::stringTable))
183     , stringConstructorTable(fastNew<HashTable>(JSC::stringConstructorTable))
184     , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable())
185     , propertyNames(new CommonIdentifiers(this))
186     , emptyList(new MarkedArgumentBuffer)
187 #if ENABLE(ASSEMBLER)
188     , executableAllocator(*this)
189 #endif
190     , lexer(new Lexer(this))
191     , parser(new Parser)
192     , interpreter(0)
193     , heap(this, heapSize)
194 #if ENABLE(TIERED_COMPILATION)
195     , sizeOfLastOSRScratchBuffer(0)
196 #endif
197     , dynamicGlobalObject(0)
198     , cachedUTCOffset(std::numeric_limits<double>::quiet_NaN())
199     , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth)
200     , m_regExpCache(new RegExpCache(this))
201 #if ENABLE(REGEXP_TRACING)
202     , m_rtTraceList(new RTTraceList())
203 #endif
204 #ifndef NDEBUG
205     , exclusiveThread(0)
206 #endif
207 #if ENABLE(GC_VALIDATION)
208     , m_isInitializingObject(false)
209 #endif
210 {
211     interpreter = new Interpreter;
212     if (globalDataType == Default)
213         m_stack = wtfThreadData().stack();
214
215     // Need to be careful to keep everything consistent here
216     IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable);
217     JSLock lock(SilenceAssertionsOnly);
218     structureStructure.set(*this, Structure::createStructure(*this));
219     debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, 0, jsNull()));
220     activationStructure.set(*this, JSActivation::createStructure(*this, 0, jsNull()));
221     interruptedExecutionErrorStructure.set(*this, InterruptedExecutionError::createStructure(*this, 0, jsNull()));
222     terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull()));
223     staticScopeStructure.set(*this, JSStaticScopeObject::createStructure(*this, 0, jsNull()));
224     strictEvalActivationStructure.set(*this, StrictEvalActivation::createStructure(*this, 0, jsNull()));
225     stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull()));
226     notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull()));
227     propertyNameIteratorStructure.set(*this, JSPropertyNameIterator::createStructure(*this, 0, jsNull()));
228     getterSetterStructure.set(*this, GetterSetter::createStructure(*this, 0, jsNull()));
229     apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, 0, jsNull()));
230     scopeChainNodeStructure.set(*this, ScopeChainNode::createStructure(*this, 0, jsNull()));
231     executableStructure.set(*this, ExecutableBase::createStructure(*this, 0, jsNull()));
232     nativeExecutableStructure.set(*this, NativeExecutable::createStructure(*this, 0, jsNull()));
233     evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, 0, jsNull()));
234     programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull()));
235     functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull()));
236     regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull()));
237     structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull()));
238
239     wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable);
240
241 #if PLATFORM(MAC)
242     startProfilerServerIfNeeded();
243 #endif
244 #if ENABLE(JIT) && ENABLE(INTERPRETER)
245 #if USE(CF)
246     CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman);
247     CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication);
248     if (canUseJIT) {
249         m_canUseJIT = kCFBooleanTrue == canUseJIT;
250         CFRelease(canUseJIT);
251     } else {
252       char* canUseJITString = getenv("JavaScriptCoreUseJIT");
253       m_canUseJIT = !canUseJITString || atoi(canUseJITString);
254     }
255     CFRelease(canUseJITKey);
256 #elif OS(UNIX)
257     char* canUseJITString = getenv("JavaScriptCoreUseJIT");
258     m_canUseJIT = !canUseJITString || atoi(canUseJITString);
259 #else
260     m_canUseJIT = true;
261 #endif
262 #endif
263 #if ENABLE(JIT)
264 #if ENABLE(INTERPRETER)
265     if (m_canUseJIT)
266         m_canUseJIT = executableAllocator.isValid();
267 #endif
268     jitStubs = adoptPtr(new JITThunks(this));
269 #endif
270
271     heap.notifyIsSafeToCollect();
272 }
273
274 void JSGlobalData::clearBuiltinStructures()
275 {
276     structureStructure.clear();
277     debuggerActivationStructure.clear();
278     activationStructure.clear();
279     interruptedExecutionErrorStructure.clear();
280     terminatedExecutionErrorStructure.clear();
281     staticScopeStructure.clear();
282     strictEvalActivationStructure.clear();
283     stringStructure.clear();
284     notAnObjectStructure.clear();
285     propertyNameIteratorStructure.clear();
286     getterSetterStructure.clear();
287     apiWrapperStructure.clear();
288     scopeChainNodeStructure.clear();
289     executableStructure.clear();
290     nativeExecutableStructure.clear();
291     evalExecutableStructure.clear();
292     programExecutableStructure.clear();
293     functionExecutableStructure.clear();
294     regExpStructure.clear();
295     structureChainStructure.clear();
296 }
297
298 JSGlobalData::~JSGlobalData()
299 {
300     // By the time this is destroyed, heap.destroy() must already have been called.
301
302     delete interpreter;
303 #ifndef NDEBUG
304     // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance.
305     interpreter = 0;
306 #endif
307
308     arrayPrototypeTable->deleteTable();
309     arrayConstructorTable->deleteTable();
310     booleanPrototypeTable->deleteTable();
311     dateTable->deleteTable();
312     dateConstructorTable->deleteTable();
313     errorPrototypeTable->deleteTable();
314     globalObjectTable->deleteTable();
315     jsonTable->deleteTable();
316     mathTable->deleteTable();
317     numberConstructorTable->deleteTable();
318     numberPrototypeTable->deleteTable();
319     objectConstructorTable->deleteTable();
320     objectPrototypeTable->deleteTable();
321     regExpTable->deleteTable();
322     regExpConstructorTable->deleteTable();
323     regExpPrototypeTable->deleteTable();
324     stringTable->deleteTable();
325     stringConstructorTable->deleteTable();
326
327     fastDelete(const_cast<HashTable*>(arrayConstructorTable));
328     fastDelete(const_cast<HashTable*>(arrayPrototypeTable));
329     fastDelete(const_cast<HashTable*>(booleanPrototypeTable));
330     fastDelete(const_cast<HashTable*>(dateTable));
331     fastDelete(const_cast<HashTable*>(dateConstructorTable));
332     fastDelete(const_cast<HashTable*>(errorPrototypeTable));
333     fastDelete(const_cast<HashTable*>(globalObjectTable));
334     fastDelete(const_cast<HashTable*>(jsonTable));
335     fastDelete(const_cast<HashTable*>(mathTable));
336     fastDelete(const_cast<HashTable*>(numberConstructorTable));
337     fastDelete(const_cast<HashTable*>(numberPrototypeTable));
338     fastDelete(const_cast<HashTable*>(objectConstructorTable));
339     fastDelete(const_cast<HashTable*>(objectPrototypeTable));
340     fastDelete(const_cast<HashTable*>(regExpTable));
341     fastDelete(const_cast<HashTable*>(regExpConstructorTable));
342     fastDelete(const_cast<HashTable*>(regExpPrototypeTable));
343     fastDelete(const_cast<HashTable*>(stringTable));
344     fastDelete(const_cast<HashTable*>(stringConstructorTable));
345
346     delete parser;
347     delete lexer;
348
349     deleteAllValues(opaqueJSClassData);
350
351     delete emptyList;
352
353     delete propertyNames;
354     if (globalDataType != Default)
355         deleteIdentifierTable(identifierTable);
356
357     delete clientData;
358     delete m_regExpCache;
359 #if ENABLE(REGEXP_TRACING)
360     delete m_rtTraceList;
361 #endif
362
363 #if ENABLE(TIERED_COMPILATION)
364     for (unsigned i = 0; i < osrScratchBuffers.size(); ++i)
365         fastFree(osrScratchBuffers[i]);
366 #endif
367 }
368
369 PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type, HeapSize heapSize)
370 {
371     return adoptRef(new JSGlobalData(APIContextGroup, type, heapSize));
372 }
373
374 PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type, HeapSize heapSize)
375 {
376     return adoptRef(new JSGlobalData(Default, type, heapSize));
377 }
378
379 PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type, HeapSize heapSize)
380 {
381     return create(type, heapSize);
382 }
383
384 bool JSGlobalData::sharedInstanceExists()
385 {
386     return sharedInstanceInternal();
387 }
388
389 JSGlobalData& JSGlobalData::sharedInstance()
390 {
391     JSGlobalData*& instance = sharedInstanceInternal();
392     if (!instance) {
393         instance = adoptRef(new JSGlobalData(APIShared, ThreadStackTypeSmall, SmallHeap)).leakRef();
394 #if ENABLE(JSC_MULTIPLE_THREADS)
395         instance->makeUsableFromMultipleThreads();
396 #endif
397     }
398     return *instance;
399 }
400
401 JSGlobalData*& JSGlobalData::sharedInstanceInternal()
402 {
403     ASSERT(JSLock::currentThreadIsHoldingLock());
404     static JSGlobalData* sharedInstance;
405     return sharedInstance;
406 }
407
408 #if ENABLE(JIT)
409 NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function)
410 {
411     return jitStubs->hostFunctionStub(this, function);
412 }
413 NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator)
414 {
415     return jitStubs->hostFunctionStub(this, function, generator);
416 }
417 #else
418 NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function)
419 {
420     return NativeExecutable::create(*this, function, callHostFunctionAsConstructor);
421 }
422 #endif
423
424 JSGlobalData::ClientData::~ClientData()
425 {
426 }
427
428 void JSGlobalData::resetDateCache()
429 {
430     cachedUTCOffset = std::numeric_limits<double>::quiet_NaN();
431     dstOffsetCache.reset();
432     cachedDateString = UString();
433     cachedDateStringValue = std::numeric_limits<double>::quiet_NaN();
434     dateInstanceCache.reset();
435 }
436
437 void JSGlobalData::startSampling()
438 {
439     interpreter->startSampling();
440 }
441
442 void JSGlobalData::stopSampling()
443 {
444     interpreter->stopSampling();
445 }
446
447 void JSGlobalData::dumpSampleData(ExecState* exec)
448 {
449     interpreter->dumpSampleData(exec);
450 #if ENABLE(ASSEMBLER)
451     ExecutableAllocator::dumpProfile();
452 #endif
453 }
454
455 void JSGlobalData::recompileAllJSFunctions()
456 {
457     // If JavaScript is running, it's not safe to recompile, since we'll end
458     // up throwing away code that is live on the stack.
459     ASSERT(!dynamicGlobalObject);
460     
461     heap.forEachCell<Recompiler>();
462 }
463
464 struct StackPreservingRecompiler : public MarkedBlock::VoidFunctor {
465     HashSet<FunctionExecutable*> currentlyExecutingFunctions;
466     void operator()(JSCell* cell)
467     {
468         if (!cell->inherits(&FunctionExecutable::s_info))
469             return;
470         FunctionExecutable* executable = static_cast<FunctionExecutable*>(cell);
471         if (currentlyExecutingFunctions.contains(executable))
472             return;
473         executable->discardCode();
474     }
475 };
476
477 void JSGlobalData::releaseExecutableMemory()
478 {
479     if (dynamicGlobalObject) {
480         StackPreservingRecompiler recompiler;
481         HashSet<JSCell*> roots;
482         heap.getConservativeRegisterRoots(roots);
483         HashSet<JSCell*>::iterator end = roots.end();
484         for (HashSet<JSCell*>::iterator ptr = roots.begin(); ptr != end; ++ptr) {
485             ScriptExecutable* executable = 0;
486             JSCell* cell = *ptr;
487             if (cell->inherits(&ScriptExecutable::s_info))
488                 executable = static_cast<ScriptExecutable*>(*ptr);
489             else if (cell->inherits(&JSFunction::s_info)) {
490                 JSFunction* function = asFunction(*ptr);
491                 if (function->isHostFunction())
492                     continue;
493                 executable = function->jsExecutable();
494             } else
495                 continue;
496             ASSERT(executable->inherits(&ScriptExecutable::s_info));
497             executable->unlinkCalls();
498             if (executable->inherits(&FunctionExecutable::s_info))
499                 recompiler.currentlyExecutingFunctions.add(static_cast<FunctionExecutable*>(executable));
500                 
501         }
502         heap.forEachCell<StackPreservingRecompiler>(recompiler);
503     }
504     m_regExpCache->invalidateCode();
505     heap.collectAllGarbage();
506 }
507     
508 void releaseExecutableMemory(JSGlobalData& globalData)
509 {
510     globalData.releaseExecutableMemory();
511 }
512
513 #if ENABLE(REGEXP_TRACING)
514 void JSGlobalData::addRegExpToTrace(RegExp* regExp)
515 {
516     m_rtTraceList->add(regExp);
517 }
518
519 void JSGlobalData::dumpRegExpTrace()
520 {
521     // The first RegExp object is ignored.  It is create by the RegExpPrototype ctor and not used.
522     RTTraceList::iterator iter = ++m_rtTraceList->begin();
523     
524     if (iter != m_rtTraceList->end()) {
525         printf("\nRegExp Tracing\n");
526         printf("                                                            match()    matches\n");
527         printf("Regular Expression                          JIT Address      calls      found\n");
528         printf("----------------------------------------+----------------+----------+----------\n");
529     
530         unsigned reCount = 0;
531     
532         for (; iter != m_rtTraceList->end(); ++iter, ++reCount)
533             (*iter)->printTraceData();
534
535         printf("%d Regular Expressions\n", reCount);
536     }
537     
538     m_rtTraceList->clear();
539 }
540 #else
541 void JSGlobalData::dumpRegExpTrace()
542 {
543 }
544 #endif
545
546 } // namespace JSC