VM.cpp 21 KB

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