Foo::s_info should be Foo::info(), so that you can change how the s_info is actually...
[WebKit-https.git] / Source / JavaScriptCore / runtime / VM.cpp
1 /*
2  * Copyright (C) 2008, 2011, 2013 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 "VM.h"
31
32 #include "ArgList.h"
33 #include "CodeCache.h"
34 #include "CommonIdentifiers.h"
35 #include "DFGLongLivedState.h"
36 #include "DFGWorklist.h"
37 #include "DebuggerActivation.h"
38 #include "FunctionConstructor.h"
39 #include "GCActivityCallback.h"
40 #include "GetterSetter.h"
41 #include "Heap.h"
42 #include "HostCallReturnValue.h"
43 #include "IncrementalSweeper.h"
44 #include "Interpreter.h"
45 #include "JSActivation.h"
46 #include "JSAPIValueWrapper.h"
47 #include "JSArray.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/ProcessID.h>
65 #include <wtf/RetainPtr.h>
66 #include <wtf/StringPrintStream.h>
67 #include <wtf/Threading.h>
68 #include <wtf/WTFThreadData.h>
69
70 #if ENABLE(DFG_JIT)
71 #include "ConservativeRoots.h"
72 #endif
73
74 #if ENABLE(REGEXP_TRACING)
75 #include "RegExp.h"
76 #endif
77
78 #if USE(CF)
79 #include <CoreFoundation/CoreFoundation.h>
80 #endif
81
82 using namespace WTF;
83
84 namespace JSC {
85
86 extern const HashTable arrayConstructorTable;
87 extern const HashTable arrayPrototypeTable;
88 extern const HashTable booleanPrototypeTable;
89 extern const HashTable jsonTable;
90 extern const HashTable dateTable;
91 extern const HashTable dateConstructorTable;
92 extern const HashTable errorPrototypeTable;
93 extern const HashTable globalObjectTable;
94 extern const HashTable numberConstructorTable;
95 extern const HashTable numberPrototypeTable;
96 JS_EXPORTDATA extern const HashTable objectConstructorTable;
97 extern const HashTable privateNamePrototypeTable;
98 extern const HashTable regExpTable;
99 extern const HashTable regExpConstructorTable;
100 extern const HashTable regExpPrototypeTable;
101 extern const HashTable stringConstructorTable;
102
103 // Note: Platform.h will enforce that ENABLE(ASSEMBLER) is true if either
104 // ENABLE(JIT) or ENABLE(YARR_JIT) or both are enabled. The code below
105 // just checks for ENABLE(JIT) or ENABLE(YARR_JIT) with this premise in mind.
106
107 #if ENABLE(ASSEMBLER)
108 static bool enableAssembler(ExecutableAllocator& executableAllocator)
109 {
110     if (!executableAllocator.isValid() || (!Options::useJIT() && !Options::useRegExpJIT()))
111         return false;
112
113 #if USE(CF)
114 #if COMPILER(GCC) && !COMPILER(CLANG)
115     // FIXME: remove this once the EWS have been upgraded to LLVM.
116     // Work around a bug of GCC with strict-aliasing.
117     RetainPtr<CFStringRef> canUseJITKeyRetain = adoptCF(CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman));
118     CFStringRef canUseJITKey = canUseJITKeyRetain.get();
119 #else
120     CFStringRef canUseJITKey = CFSTR("JavaScriptCoreUseJIT");
121 #endif // COMPILER(GCC) && !COMPILER(CLANG)
122     RetainPtr<CFTypeRef> canUseJIT = adoptCF(CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication));
123     if (canUseJIT)
124         return kCFBooleanTrue == canUseJIT.get();
125 #endif
126
127 #if USE(CF) || OS(UNIX)
128     char* canUseJITString = getenv("JavaScriptCoreUseJIT");
129     return !canUseJITString || atoi(canUseJITString);
130 #else
131     return true;
132 #endif
133 }
134 #endif // ENABLE(!ASSEMBLER)
135
136 VM::VM(VMType vmType, HeapType heapType)
137     : m_apiLock(adoptRef(new JSLock(this)))
138 #if ENABLE(ASSEMBLER)
139     , executableAllocator(*this)
140 #endif
141     , heap(this, heapType)
142     , vmType(vmType)
143     , clientData(0)
144     , topCallFrame(CallFrame::noCaller())
145     , arrayConstructorTable(fastNew<HashTable>(JSC::arrayConstructorTable))
146     , arrayPrototypeTable(fastNew<HashTable>(JSC::arrayPrototypeTable))
147     , booleanPrototypeTable(fastNew<HashTable>(JSC::booleanPrototypeTable))
148     , dateTable(fastNew<HashTable>(JSC::dateTable))
149     , dateConstructorTable(fastNew<HashTable>(JSC::dateConstructorTable))
150     , errorPrototypeTable(fastNew<HashTable>(JSC::errorPrototypeTable))
151     , globalObjectTable(fastNew<HashTable>(JSC::globalObjectTable))
152     , jsonTable(fastNew<HashTable>(JSC::jsonTable))
153     , numberConstructorTable(fastNew<HashTable>(JSC::numberConstructorTable))
154     , numberPrototypeTable(fastNew<HashTable>(JSC::numberPrototypeTable))
155     , objectConstructorTable(fastNew<HashTable>(JSC::objectConstructorTable))
156     , privateNamePrototypeTable(fastNew<HashTable>(JSC::privateNamePrototypeTable))
157     , regExpTable(fastNew<HashTable>(JSC::regExpTable))
158     , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
159     , regExpPrototypeTable(fastNew<HashTable>(JSC::regExpPrototypeTable))
160     , stringConstructorTable(fastNew<HashTable>(JSC::stringConstructorTable))
161     , identifierTable(vmType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable())
162     , propertyNames(new CommonIdentifiers(this))
163     , emptyList(new MarkedArgumentBuffer)
164     , parserArena(adoptPtr(new ParserArena))
165     , keywords(adoptPtr(new Keywords(this)))
166     , interpreter(0)
167     , jsArrayClassInfo(JSArray::info())
168     , jsFinalObjectClassInfo(JSFinalObject::info())
169 #if ENABLE(DFG_JIT)
170     , sizeOfLastScratchBuffer(0)
171 #endif
172     , dynamicGlobalObject(0)
173     , m_enabledProfiler(0)
174     , m_regExpCache(new RegExpCache(this))
175 #if ENABLE(REGEXP_TRACING)
176     , m_rtTraceList(new RTTraceList())
177 #endif
178     , exclusiveThread(0)
179     , m_newStringsSinceLastHashCons(0)
180 #if ENABLE(ASSEMBLER)
181     , m_canUseAssembler(enableAssembler(executableAllocator))
182 #endif
183 #if ENABLE(JIT)
184     , m_canUseJIT(m_canUseAssembler && Options::useJIT())
185 #endif
186 #if ENABLE(YARR_JIT)
187     , m_canUseRegExpJIT(m_canUseAssembler && Options::useRegExpJIT())
188 #endif
189 #if ENABLE(GC_VALIDATION)
190     , m_initializingObjectClass(0)
191 #endif
192     , m_inDefineOwnProperty(false)
193     , m_codeCache(CodeCache::create())
194 {
195     interpreter = new Interpreter(*this);
196
197     // Need to be careful to keep everything consistent here
198     JSLockHolder lock(this);
199     IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable);
200     structureStructure.set(*this, Structure::createStructure(*this));
201     structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull()));
202     debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, 0, jsNull()));
203     terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull()));
204     stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull()));
205     notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull()));
206     propertyNameIteratorStructure.set(*this, JSPropertyNameIterator::createStructure(*this, 0, jsNull()));
207     getterSetterStructure.set(*this, GetterSetter::createStructure(*this, 0, jsNull()));
208     apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, 0, jsNull()));
209     JSScopeStructure.set(*this, JSScope::createStructure(*this, 0, jsNull()));
210     executableStructure.set(*this, ExecutableBase::createStructure(*this, 0, jsNull()));
211     nativeExecutableStructure.set(*this, NativeExecutable::createStructure(*this, 0, jsNull()));
212     evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, 0, jsNull()));
213     programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull()));
214     functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull()));
215     regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull()));
216     sharedSymbolTableStructure.set(*this, SharedSymbolTable::createStructure(*this, 0, jsNull()));
217     structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull()));
218     sparseArrayValueMapStructure.set(*this, SparseArrayValueMap::createStructure(*this, 0, jsNull()));
219     withScopeStructure.set(*this, JSWithScope::createStructure(*this, 0, jsNull()));
220     unlinkedFunctionExecutableStructure.set(*this, UnlinkedFunctionExecutable::createStructure(*this, 0, jsNull()));
221     unlinkedProgramCodeBlockStructure.set(*this, UnlinkedProgramCodeBlock::createStructure(*this, 0, jsNull()));
222     unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull()));
223     unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull()));
224     propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull()));
225     smallStrings.initializeCommonStrings(*this);
226
227     wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable);
228
229 #if ENABLE(JIT)
230     jitStubs = adoptPtr(new JITThunks());
231     performPlatformSpecificJITAssertions(this);
232 #endif
233     
234     interpreter->initialize(this->canUseJIT());
235     
236 #if ENABLE(JIT)
237     initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support.
238 #endif
239
240     heap.notifyIsSafeToCollect();
241
242     LLInt::Data::performAssertions(*this);
243     
244     if (Options::enableProfiler()) {
245         m_perBytecodeProfiler = adoptPtr(new Profiler::Database(*this));
246
247         StringPrintStream pathOut;
248 #if !OS(WINCE)
249         const char* profilerPath = getenv("JSC_PROFILER_PATH");
250         if (profilerPath)
251             pathOut.print(profilerPath, "/");
252 #endif
253         pathOut.print("JSCProfile-", getCurrentProcessID(), "-", m_perBytecodeProfiler->databaseID(), ".json");
254         m_perBytecodeProfiler->registerToSaveAtExit(pathOut.toCString().data());
255     }
256
257 #if ENABLE(DFG_JIT)
258     if (canUseJIT())
259         dfgState = adoptPtr(new DFG::LongLivedState());
260 #endif
261 }
262
263 VM::~VM()
264 {
265     // Never GC, ever again.
266     heap.incrementDeferralDepth();
267     
268 #if ENABLE(DFG_JIT)
269     // Make sure concurrent compilations are done, but don't install them, since there is
270     // no point to doing so.
271     if (worklist) {
272         worklist->waitUntilAllPlansForVMAreReady(*this);
273         worklist->removeAllReadyPlansForVM(*this);
274     }
275 #endif // ENABLE(DFG_JIT)
276     
277     // Clear this first to ensure that nobody tries to remove themselves from it.
278     m_perBytecodeProfiler.clear();
279     
280     ASSERT(m_apiLock->currentThreadIsHoldingLock());
281     m_apiLock->willDestroyVM(this);
282     heap.lastChanceToFinalize();
283
284     delete interpreter;
285 #ifndef NDEBUG
286     interpreter = reinterpret_cast<Interpreter*>(0xbbadbeef);
287 #endif
288
289     arrayPrototypeTable->deleteTable();
290     arrayConstructorTable->deleteTable();
291     booleanPrototypeTable->deleteTable();
292     dateTable->deleteTable();
293     dateConstructorTable->deleteTable();
294     errorPrototypeTable->deleteTable();
295     globalObjectTable->deleteTable();
296     jsonTable->deleteTable();
297     numberConstructorTable->deleteTable();
298     numberPrototypeTable->deleteTable();
299     objectConstructorTable->deleteTable();
300     privateNamePrototypeTable->deleteTable();
301     regExpTable->deleteTable();
302     regExpConstructorTable->deleteTable();
303     regExpPrototypeTable->deleteTable();
304     stringConstructorTable->deleteTable();
305
306     fastDelete(const_cast<HashTable*>(arrayConstructorTable));
307     fastDelete(const_cast<HashTable*>(arrayPrototypeTable));
308     fastDelete(const_cast<HashTable*>(booleanPrototypeTable));
309     fastDelete(const_cast<HashTable*>(dateTable));
310     fastDelete(const_cast<HashTable*>(dateConstructorTable));
311     fastDelete(const_cast<HashTable*>(errorPrototypeTable));
312     fastDelete(const_cast<HashTable*>(globalObjectTable));
313     fastDelete(const_cast<HashTable*>(jsonTable));
314     fastDelete(const_cast<HashTable*>(numberConstructorTable));
315     fastDelete(const_cast<HashTable*>(numberPrototypeTable));
316     fastDelete(const_cast<HashTable*>(objectConstructorTable));
317     fastDelete(const_cast<HashTable*>(privateNamePrototypeTable));
318     fastDelete(const_cast<HashTable*>(regExpTable));
319     fastDelete(const_cast<HashTable*>(regExpConstructorTable));
320     fastDelete(const_cast<HashTable*>(regExpPrototypeTable));
321     fastDelete(const_cast<HashTable*>(stringConstructorTable));
322
323     delete emptyList;
324
325     delete propertyNames;
326     if (vmType != Default)
327         deleteIdentifierTable(identifierTable);
328
329     delete clientData;
330     delete m_regExpCache;
331 #if ENABLE(REGEXP_TRACING)
332     delete m_rtTraceList;
333 #endif
334
335 #if ENABLE(DFG_JIT)
336     for (unsigned i = 0; i < scratchBuffers.size(); ++i)
337         fastFree(scratchBuffers[i]);
338 #endif
339 }
340
341 PassRefPtr<VM> VM::createContextGroup(HeapType heapType)
342 {
343     return adoptRef(new VM(APIContextGroup, heapType));
344 }
345
346 PassRefPtr<VM> VM::create(HeapType heapType)
347 {
348     return adoptRef(new VM(Default, heapType));
349 }
350
351 PassRefPtr<VM> VM::createLeaked(HeapType heapType)
352 {
353     return create(heapType);
354 }
355
356 bool VM::sharedInstanceExists()
357 {
358     return sharedInstanceInternal();
359 }
360
361 VM& VM::sharedInstance()
362 {
363     GlobalJSLock globalLock;
364     VM*& instance = sharedInstanceInternal();
365     if (!instance) {
366         instance = adoptRef(new VM(APIShared, SmallHeap)).leakRef();
367         instance->makeUsableFromMultipleThreads();
368     }
369     return *instance;
370 }
371
372 VM*& VM::sharedInstanceInternal()
373 {
374     static VM* sharedInstance;
375     return sharedInstance;
376 }
377
378 #if ENABLE(JIT)
379 static ThunkGenerator thunkGeneratorForIntrinsic(Intrinsic intrinsic)
380 {
381     switch (intrinsic) {
382     case CharCodeAtIntrinsic:
383         return charCodeAtThunkGenerator;
384     case CharAtIntrinsic:
385         return charAtThunkGenerator;
386     case FromCharCodeIntrinsic:
387         return fromCharCodeThunkGenerator;
388     case SqrtIntrinsic:
389         return sqrtThunkGenerator;
390     case PowIntrinsic:
391         return powThunkGenerator;
392     case AbsIntrinsic:
393         return absThunkGenerator;
394     case FloorIntrinsic:
395         return floorThunkGenerator;
396     case CeilIntrinsic:
397         return ceilThunkGenerator;
398     case RoundIntrinsic:
399         return roundThunkGenerator;
400     case ExpIntrinsic:
401         return expThunkGenerator;
402     case LogIntrinsic:
403         return logThunkGenerator;
404     case IMulIntrinsic:
405         return imulThunkGenerator;
406     default:
407         return 0;
408     }
409 }
410
411 NativeExecutable* VM::getHostFunction(NativeFunction function, NativeFunction constructor)
412 {
413     return jitStubs->hostFunctionStub(this, function, constructor);
414 }
415 NativeExecutable* VM::getHostFunction(NativeFunction function, Intrinsic intrinsic)
416 {
417     ASSERT(canUseJIT());
418     return jitStubs->hostFunctionStub(this, function, intrinsic != NoIntrinsic ? thunkGeneratorForIntrinsic(intrinsic) : 0, intrinsic);
419 }
420
421 #else // !ENABLE(JIT)
422 NativeExecutable* VM::getHostFunction(NativeFunction function, NativeFunction constructor)
423 {
424     return NativeExecutable::create(*this, function, constructor);
425 }
426 #endif // !ENABLE(JIT)
427
428 VM::ClientData::~ClientData()
429 {
430 }
431
432 void VM::resetDateCache()
433 {
434     localTimeOffsetCache.reset();
435     cachedDateString = String();
436     cachedDateStringValue = QNaN;
437     dateInstanceCache.reset();
438 }
439
440 void VM::startSampling()
441 {
442     interpreter->startSampling();
443 }
444
445 void VM::stopSampling()
446 {
447     interpreter->stopSampling();
448 }
449
450 void VM::prepareToDiscardCode()
451 {
452 #if ENABLE(DFG_JIT)
453     if (!worklist)
454         return;
455     
456     worklist->completeAllPlansForVM(*this);
457 #endif
458 }
459
460 void VM::discardAllCode()
461 {
462     prepareToDiscardCode();
463     m_codeCache->clear();
464     heap.deleteAllCompiledCode();
465     heap.reportAbandonedObjectGraph();
466 }
467
468 void VM::dumpSampleData(ExecState* exec)
469 {
470     interpreter->dumpSampleData(exec);
471 #if ENABLE(ASSEMBLER)
472     ExecutableAllocator::dumpProfile();
473 #endif
474 }
475
476 SourceProviderCache* VM::addSourceProviderCache(SourceProvider* sourceProvider)
477 {
478     SourceProviderCacheMap::AddResult addResult = sourceProviderCacheMap.add(sourceProvider, 0);
479     if (addResult.isNewEntry)
480         addResult.iterator->value = adoptRef(new SourceProviderCache);
481     return addResult.iterator->value.get();
482 }
483
484 void VM::clearSourceProviderCaches()
485 {
486     sourceProviderCacheMap.clear();
487 }
488
489 struct StackPreservingRecompiler : public MarkedBlock::VoidFunctor {
490     HashSet<FunctionExecutable*> currentlyExecutingFunctions;
491     void operator()(JSCell* cell)
492     {
493         if (!cell->inherits(FunctionExecutable::info()))
494             return;
495         FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell);
496         if (currentlyExecutingFunctions.contains(executable))
497             return;
498         executable->clearCodeIfNotCompiling();
499     }
500 };
501
502 void VM::releaseExecutableMemory()
503 {
504     prepareToDiscardCode();
505     
506     if (dynamicGlobalObject) {
507         StackPreservingRecompiler recompiler;
508         HashSet<JSCell*> roots;
509         heap.canonicalizeCellLivenessData();
510         heap.getConservativeRegisterRoots(roots);
511         HashSet<JSCell*>::iterator end = roots.end();
512         for (HashSet<JSCell*>::iterator ptr = roots.begin(); ptr != end; ++ptr) {
513             ScriptExecutable* executable = 0;
514             JSCell* cell = *ptr;
515             if (cell->inherits(ScriptExecutable::info()))
516                 executable = static_cast<ScriptExecutable*>(*ptr);
517             else if (cell->inherits(JSFunction::info())) {
518                 JSFunction* function = jsCast<JSFunction*>(*ptr);
519                 if (function->isHostFunction())
520                     continue;
521                 executable = function->jsExecutable();
522             } else
523                 continue;
524             ASSERT(executable->inherits(ScriptExecutable::info()));
525             executable->unlinkCalls();
526             if (executable->inherits(FunctionExecutable::info()))
527                 recompiler.currentlyExecutingFunctions.add(static_cast<FunctionExecutable*>(executable));
528                 
529         }
530         heap.objectSpace().forEachLiveCell<StackPreservingRecompiler>(recompiler);
531     }
532     m_regExpCache->invalidateCode();
533     heap.collectAllGarbage();
534 }
535
536 void VM::clearExceptionStack()
537 {
538     m_exceptionStack = RefCountedArray<StackFrame>();
539 }
540     
541 void releaseExecutableMemory(VM& vm)
542 {
543     vm.releaseExecutableMemory();
544 }
545
546 #if ENABLE(DFG_JIT)
547 void VM::gatherConservativeRoots(ConservativeRoots& conservativeRoots)
548 {
549     for (size_t i = 0; i < scratchBuffers.size(); i++) {
550         ScratchBuffer* scratchBuffer = scratchBuffers[i];
551         if (scratchBuffer->activeLength()) {
552             void* bufferStart = scratchBuffer->dataBuffer();
553             conservativeRoots.add(bufferStart, static_cast<void*>(static_cast<char*>(bufferStart) + scratchBuffer->activeLength()));
554         }
555     }
556 }
557 #endif
558
559 #if ENABLE(REGEXP_TRACING)
560 void VM::addRegExpToTrace(RegExp* regExp)
561 {
562     m_rtTraceList->add(regExp);
563 }
564
565 void VM::dumpRegExpTrace()
566 {
567     // The first RegExp object is ignored.  It is create by the RegExpPrototype ctor and not used.
568     RTTraceList::iterator iter = ++m_rtTraceList->begin();
569     
570     if (iter != m_rtTraceList->end()) {
571         dataLogF("\nRegExp Tracing\n");
572         dataLogF("                                                            match()    matches\n");
573         dataLogF("Regular Expression                          JIT Address      calls      found\n");
574         dataLogF("----------------------------------------+----------------+----------+----------\n");
575     
576         unsigned reCount = 0;
577     
578         for (; iter != m_rtTraceList->end(); ++iter, ++reCount)
579             (*iter)->printTraceData();
580
581         dataLogF("%d Regular Expressions\n", reCount);
582     }
583     
584     m_rtTraceList->clear();
585 }
586 #else
587 void VM::dumpRegExpTrace()
588 {
589 }
590 #endif
591
592 } // namespace JSC