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