Register* JSStack::highAddress() const { ASSERT(wtfThreadData().stack().isGrowingDownward()); return reinterpret_cast<Register*>(wtfThreadData().stack().origin()); }
void Heap::collect(SweepToggle sweepToggle) { SamplingRegion samplingRegion("Garbage Collection"); GCPHASE(Collect); ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); ASSERT(m_isSafeToCollect); JAVASCRIPTCORE_GC_BEGIN(); m_activityCallback->willCollect(); double lastGCStartTime = WTF::currentTime(); if (lastGCStartTime - m_lastCodeDiscardTime > minute) { discardAllCompiledCode(); m_lastCodeDiscardTime = WTF::currentTime(); } #if ENABLE(GGC) bool fullGC = sweepToggle == DoSweep; if (!fullGC) fullGC = (capacity() > 4 * m_sizeAfterLastCollect); #else bool fullGC = true; #endif { GCPHASE(Canonicalize); canonicalizeCellLivenessData(); } markRoots(fullGC); { GCPHASE(FinalizeUnconditionalFinalizers); finalizeUnconditionalFinalizers(); } { GCPHASE(FinalizeWeakHandles); m_weakSet.sweep(); m_globalData->smallStrings.finalizeSmallStrings(); } JAVASCRIPTCORE_GC_MARKED(); { GCPHASE(ResetAllocator); resetAllocators(); } { GCPHASE(DeleteCodeBlocks); m_dfgCodeBlocks.deleteUnmarkedJettisonedCodeBlocks(); } if (sweepToggle == DoSweep) { SamplingRegion samplingRegion("Garbage Collection: Sweeping"); GCPHASE(Sweeping); sweep(); m_objectSpace.shrink(); m_weakSet.shrink(); } // To avoid pathological GC churn in large heaps, we set the new allocation // limit to be the current size of the heap. This heuristic // is a bit arbitrary. Using the current size of the heap after this // collection gives us a 2X multiplier, which is a 1:1 (heap size : // new bytes allocated) proportion, and seems to work well in benchmarks. size_t newSize = size(); if (fullGC) { m_sizeAfterLastCollect = newSize; m_bytesAllocatedLimit = max(newSize, m_minBytesPerCycle); } m_bytesAllocated = 0; double lastGCEndTime = WTF::currentTime(); m_lastGCLength = lastGCEndTime - lastGCStartTime; JAVASCRIPTCORE_GC_END(); }
Register* JSStack::lowAddress() const { ASSERT(wtfThreadData().stack().isGrowingDownward()); return reinterpret_cast<Register*>(m_vm.stackLimit()); }
JSGlueAPICallback::~JSGlueAPICallback() { wtfThreadData().setCurrentIdentifierTable(getThreadGlobalData()->identifierTable); }
StackStats::LayoutCheckPoint::LayoutCheckPoint() { // While a layout checkpoint is not necessarily a checkpoint where we // we will do a recursion check, it is a convenient spot for doing a // probe to measure the height of stack usage. // // We'll do this probe before we commence with the layout checkpoint. // This is because the probe also locks the sharedLock. By calling the // probe first, we can avoid re-entering the lock. StackStats::probe(); MutexLocker locker(*StackStats::s_sharedLock); WTFThreadData* threadData = const_cast<WTFThreadData*>(&wtfThreadData()); StackStats::PerThreadStats& t = threadData->stackStats(); const StackBounds& stack = threadData->stack(); // Push this checkpoint: m_prev = StackStats::s_topLayoutCheckPoint; if (m_prev) m_depth = m_prev->m_depth + 1; else { StackStats::s_firstLayoutCheckPoint = this; m_depth = 0; } StackStats::s_topLayoutCheckPoint = this; // char* current = reinterpret_cast<char*>(this); char* last = reinterpret_cast<char*>(m_prev); char* root = reinterpret_cast<char*>(StackStats::s_firstLayoutCheckPoint); bool needToLog = false; int diff = last - current; if (!last) diff = 0; int totalDiff = root - current; if (!root) totalDiff = 0; // Update the stack height stats: int height = t.m_stackStart - current; if (height > StackStats::s_maxStackHeight) { StackStats::s_maxStackHeight = height; needToLog = true; } // Update the layout checkpoint diff stats: if (diff > StackStats::s_maxLayoutCheckPointDiff) { StackStats::s_maxLayoutCheckPointDiff = diff; needToLog = true; } // Update the total layout checkpoint diff stats: if (totalDiff > StackStats::s_maxTotalLayoutCheckPointDiff) { StackStats::s_maxTotalLayoutCheckPointDiff = totalDiff; needToLog = true; } #if ENABLE(VERBOSE_STACK_STATS) needToLog = true; // always log. #endif if (needToLog) dataLogF(" LAYOUT %p diff %d/%.1fk/max %.1fk | reentry %d/max %d | height %.1fk/max %.1fk | stack %p size %.1fk\n", current, diff, diff / 1024.0, StackStats::s_maxLayoutCheckPointDiff / 1024.0, m_depth, StackStats::s_maxLayoutReentryDepth, totalDiff / 1024.0, StackStats::s_maxTotalLayoutCheckPointDiff / 1024.0, stack.origin(), stack.size() / 1024.0); }
void Heap::collect(SweepToggle sweepToggle) { #if ENABLE(ALLOCATION_LOGGING) dataLogF("JSC GC starting collection.\n"); #endif double before = 0; if (Options::logGC()) { dataLog("[GC", sweepToggle == DoSweep ? " (eager sweep)" : "", ": "); before = currentTimeMS(); } SamplingRegion samplingRegion("Garbage Collection"); RELEASE_ASSERT(!m_deferralDepth); GCPHASE(Collect); ASSERT(vm()->currentThreadIsHoldingAPILock()); RELEASE_ASSERT(vm()->identifierTable == wtfThreadData().currentIdentifierTable()); ASSERT(m_isSafeToCollect); JAVASCRIPTCORE_GC_BEGIN(); RELEASE_ASSERT(m_operationInProgress == NoOperation); m_deferralDepth++; // Make sure that we don't GC in this call. m_vm->prepareToDiscardCode(); m_deferralDepth--; // Decrement deferal manually, so we don't GC when we do so, since we are already GCing!. m_operationInProgress = Collection; m_extraMemoryUsage = 0; m_activityCallback->willCollect(); double lastGCStartTime = WTF::monotonicallyIncreasingTime(); if (lastGCStartTime - m_lastCodeDiscardTime > minute) { deleteAllCompiledCode(); m_lastCodeDiscardTime = WTF::monotonicallyIncreasingTime(); } { GCPHASE(Canonicalize); m_objectSpace.canonicalizeCellLivenessData(); } markRoots(); { GCPHASE(ReapingWeakHandles); m_objectSpace.reapWeakSets(); } JAVASCRIPTCORE_GC_MARKED(); { GCPHASE(SweepingArrayBuffers); m_arrayBuffers.sweep(); } { m_blockSnapshot.resize(m_objectSpace.blocks().set().size()); MarkedBlockSnapshotFunctor functor(m_blockSnapshot); m_objectSpace.forEachBlock(functor); } copyBackingStores(); { GCPHASE(FinalizeUnconditionalFinalizers); finalizeUnconditionalFinalizers(); } { GCPHASE(DeleteCodeBlocks); deleteUnmarkedCompiledCode(); } { GCPHASE(DeleteSourceProviderCaches); m_vm->clearSourceProviderCaches(); } if (sweepToggle == DoSweep) { SamplingRegion samplingRegion("Garbage Collection: Sweeping"); GCPHASE(Sweeping); m_objectSpace.sweep(); m_objectSpace.shrink(); } m_sweeper->startSweeping(m_blockSnapshot); m_bytesAbandoned = 0; { GCPHASE(ResetAllocators); m_objectSpace.resetAllocators(); } size_t currentHeapSize = sizeAfterCollect(); if (Options::gcMaxHeapSize() && currentHeapSize > Options::gcMaxHeapSize()) HeapStatistics::exitWithFailure(); m_sizeAfterLastCollect = currentHeapSize; // To avoid pathological GC churn in very small and very large heaps, we set // the new allocation limit based on the current size of the heap, with a // fixed minimum. size_t maxHeapSize = max(minHeapSize(m_heapType, m_ramSize), proportionalHeapSize(currentHeapSize, m_ramSize)); m_bytesAllocatedLimit = maxHeapSize - currentHeapSize; m_bytesAllocated = 0; double lastGCEndTime = WTF::monotonicallyIncreasingTime(); m_lastGCLength = lastGCEndTime - lastGCStartTime; if (Options::recordGCPauseTimes()) HeapStatistics::recordGCPauseTime(lastGCStartTime, lastGCEndTime); RELEASE_ASSERT(m_operationInProgress == Collection); m_operationInProgress = NoOperation; JAVASCRIPTCORE_GC_END(); if (Options::useZombieMode()) zombifyDeadObjects(); if (Options::objectsAreImmortal()) markDeadObjects(); if (Options::showObjectStatistics()) HeapStatistics::showObjectStatistics(this); if (Options::logGC()) { double after = currentTimeMS(); dataLog(after - before, " ms, ", currentHeapSize / 1024, " kb]\n"); } #if ENABLE(ALLOCATION_LOGGING) dataLogF("JSC GC finishing collection.\n"); #endif }
static Thread* createForCurrentThread() { return new Thread(getCurrentPlatformThread(), wtfThreadData().stack().origin()); }
VM::VM(VMType vmType, HeapType heapType) : m_apiLock(adoptRef(new JSLock(this))) #if ENABLE(ASSEMBLER) , executableAllocator(*this) #endif , heap(this, heapType) , vmType(vmType) , clientData(0) , topVMEntryFrame(nullptr) , topCallFrame(CallFrame::noCaller()) , m_atomicStringTable(vmType == Default ? wtfThreadData().atomicStringTable() : new AtomicStringTable) , propertyNames(nullptr) , emptyList(new MarkedArgumentBuffer) , stringCache(*this) , prototypeMap(*this) , keywords(std::make_unique<Keywords>(*this)) , interpreter(0) , jsArrayClassInfo(JSArray::info()) , jsFinalObjectClassInfo(JSFinalObject::info()) , sizeOfLastScratchBuffer(0) , entryScope(0) , m_regExpCache(new RegExpCache(this)) #if ENABLE(REGEXP_TRACING) , m_rtTraceList(new RTTraceList()) #endif , m_newStringsSinceLastHashCons(0) #if ENABLE(ASSEMBLER) , m_canUseAssembler(enableAssembler(executableAllocator)) #endif #if ENABLE(JIT) , m_canUseJIT(m_canUseAssembler && Options::useJIT()) #endif #if ENABLE(YARR_JIT) , m_canUseRegExpJIT(m_canUseAssembler && Options::useRegExpJIT()) #endif #if ENABLE(GC_VALIDATION) , m_initializingObjectClass(0) #endif , m_stackPointerAtVMEntry(0) , m_stackLimit(0) #if !ENABLE(JIT) , m_jsStackLimit(0) #endif #if ENABLE(FTL_JIT) , m_ftlStackLimit(0) , m_largestFTLStackSize(0) #endif , m_inDefineOwnProperty(false) , m_codeCache(std::make_unique<CodeCache>()) , m_enabledProfiler(nullptr) , m_builtinExecutables(std::make_unique<BuiltinExecutables>(*this)) , m_typeProfilerEnabledCount(0) , m_controlFlowProfilerEnabledCount(0) { interpreter = new Interpreter(*this); StackBounds stack = wtfThreadData().stack(); updateReservedZoneSize(Options::reservedZoneSize()); #if !ENABLE(JIT) interpreter->stack().setReservedZoneSize(Options::reservedZoneSize()); #endif setLastStackTop(stack.origin()); // Need to be careful to keep everything consistent here JSLockHolder lock(this); AtomicStringTable* existingEntryAtomicStringTable = wtfThreadData().setCurrentAtomicStringTable(m_atomicStringTable); propertyNames = new CommonIdentifiers(this); structureStructure.set(*this, Structure::createStructure(*this)); structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull())); terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull())); stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull())); notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull())); propertyNameEnumeratorStructure.set(*this, JSPropertyNameEnumerator::createStructure(*this, 0, jsNull())); getterSetterStructure.set(*this, GetterSetter::createStructure(*this, 0, jsNull())); customGetterSetterStructure.set(*this, CustomGetterSetter::createStructure(*this, 0, jsNull())); apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, 0, jsNull())); JSScopeStructure.set(*this, JSScope::createStructure(*this, 0, jsNull())); executableStructure.set(*this, ExecutableBase::createStructure(*this, 0, jsNull())); nativeExecutableStructure.set(*this, NativeExecutable::createStructure(*this, 0, jsNull())); evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, 0, jsNull())); programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull())); functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull())); regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull())); symbolStructure.set(*this, Symbol::createStructure(*this, 0, jsNull())); symbolTableStructure.set(*this, SymbolTable::createStructure(*this, 0, jsNull())); structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull())); sparseArrayValueMapStructure.set(*this, SparseArrayValueMap::createStructure(*this, 0, jsNull())); arrayBufferNeuteringWatchpointStructure.set(*this, ArrayBufferNeuteringWatchpoint::createStructure(*this)); unlinkedFunctionExecutableStructure.set(*this, UnlinkedFunctionExecutable::createStructure(*this, 0, jsNull())); unlinkedProgramCodeBlockStructure.set(*this, UnlinkedProgramCodeBlock::createStructure(*this, 0, jsNull())); unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull())); unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull())); propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull())); mapDataStructure.set(*this, MapData::createStructure(*this, 0, jsNull())); weakMapDataStructure.set(*this, WeakMapData::createStructure(*this, 0, jsNull())); #if ENABLE(PROMISES) promiseDeferredStructure.set(*this, JSPromiseDeferred::createStructure(*this, 0, jsNull())); promiseReactionStructure.set(*this, JSPromiseReaction::createStructure(*this, 0, jsNull())); #endif iterationTerminator.set(*this, JSFinalObject::create(*this, JSFinalObject::createStructure(*this, 0, jsNull(), 1))); smallStrings.initializeCommonStrings(*this); wtfThreadData().setCurrentAtomicStringTable(existingEntryAtomicStringTable); #if ENABLE(JIT) jitStubs = std::make_unique<JITThunks>(); arityCheckFailReturnThunks = std::make_unique<ArityCheckFailReturnThunks>(); #endif arityCheckData = std::make_unique<CommonSlowPaths::ArityCheckData>(); #if ENABLE(FTL_JIT) ftlThunks = std::make_unique<FTL::Thunks>(); #endif // ENABLE(FTL_JIT) interpreter->initialize(this->canUseJIT()); #if ENABLE(JIT) initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support. #endif heap.notifyIsSafeToCollect(); LLInt::Data::performAssertions(*this); if (Options::enableProfiler()) { m_perBytecodeProfiler = std::make_unique<Profiler::Database>(*this); StringPrintStream pathOut; const char* profilerPath = getenv("JSC_PROFILER_PATH"); if (profilerPath) pathOut.print(profilerPath, "/"); pathOut.print("JSCProfile-", getCurrentProcessID(), "-", m_perBytecodeProfiler->databaseID(), ".json"); m_perBytecodeProfiler->registerToSaveAtExit(pathOut.toCString().data()); } #if ENABLE(DFG_JIT) if (canUseJIT()) dfgState = std::make_unique<DFG::LongLivedState>(); #endif // Initialize this last, as a free way of asserting that VM initialization itself // won't use this. m_typedArrayController = adoptRef(new SimpleTypedArrayController()); if (Options::enableTypeProfiler()) enableTypeProfiler(); if (Options::enableControlFlowProfiler()) enableControlFlowProfiler(); }
JSGlueAPIEntry::JSGlueAPIEntry() : m_lock(LockForReal) , m_storedIdentifierTable(wtfThreadData().currentIdentifierTable()) { wtfThreadData().setCurrentIdentifierTable(getThreadGlobalData()->identifierTable); }
JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType) : globalDataType(globalDataType) , clientData(0) , arrayTable(fastNew<HashTable>(JSC::arrayTable)) , dateTable(fastNew<HashTable>(JSC::dateTable)) , jsonTable(fastNew<HashTable>(JSC::jsonTable)) , mathTable(fastNew<HashTable>(JSC::mathTable)) , numberTable(fastNew<HashTable>(JSC::numberTable)) , objectConstructorTable(fastNew<HashTable>(JSC::objectConstructorTable)) , regExpTable(fastNew<HashTable>(JSC::regExpTable)) , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable)) , stringTable(fastNew<HashTable>(JSC::stringTable)) , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable()) , propertyNames(new CommonIdentifiers(this)) , emptyList(new MarkedArgumentBuffer) , lexer(new Lexer(this)) , parser(new Parser) , interpreter(0) , heap(this) , globalObjectCount(0) , dynamicGlobalObject(0) , cachedUTCOffset(NaN) , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth) , m_regExpCache(new RegExpCache(this)) #if ENABLE(REGEXP_TRACING) , m_rtTraceList(new RTTraceList()) #endif #ifndef NDEBUG , exclusiveThread(0) #endif { activationStructure = JSActivation::createStructure(*this, jsNull()); interruptedExecutionErrorStructure = JSNonFinalObject::createStructure(*this, jsNull()); terminatedExecutionErrorStructure = JSNonFinalObject::createStructure(*this, jsNull()); staticScopeStructure = JSStaticScopeObject::createStructure(*this, jsNull()); strictEvalActivationStructure = StrictEvalActivation::createStructure(*this, jsNull()); stringStructure = JSString::createStructure(*this, jsNull()); notAnObjectStructure = JSNotAnObject::createStructure(*this, jsNull()); propertyNameIteratorStructure = JSPropertyNameIterator::createStructure(*this, jsNull()); getterSetterStructure = GetterSetter::createStructure(*this, jsNull()); apiWrapperStructure = JSAPIValueWrapper::createStructure(*this, jsNull()); scopeChainNodeStructure = ScopeChainNode::createStructure(*this, jsNull()); executableStructure = ExecutableBase::createStructure(*this, jsNull()); evalExecutableStructure = EvalExecutable::createStructure(*this, jsNull()); programExecutableStructure = ProgramExecutable::createStructure(*this, jsNull()); functionExecutableStructure = FunctionExecutable::createStructure(*this, jsNull()); dummyMarkableCellStructure = JSCell::createDummyStructure(*this); interpreter = new Interpreter(*this); if (globalDataType == Default) m_stack = wtfThreadData().stack(); #if PLATFORM(MAC) //startProfilerServerIfNeeded(); #endif #if ENABLE(JIT) && ENABLE(INTERPRETER) #if USE(CF) CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman); CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication); if (canUseJIT) { m_canUseJIT = kCFBooleanTrue == canUseJIT; CFRelease(canUseJIT); } else { char* canUseJITString = getenv("JavaScriptCoreUseJIT"); m_canUseJIT = !canUseJITString || atoi(canUseJITString); } CFRelease(canUseJITKey); #elif OS(UNIX) char* canUseJITString = getenv("JavaScriptCoreUseJIT"); m_canUseJIT = !canUseJITString || atoi(canUseJITString); #else m_canUseJIT = true; #endif #endif #if ENABLE(JIT) #if ENABLE(INTERPRETER) if (m_canUseJIT) m_canUseJIT = executableAllocator.isValid(); #endif jitStubs = new JITThunks(this); #endif }
bool checkSyntax(VM& vm, const SourceCode& source, ParserError& error) { JSLockHolder lock(vm); RELEASE_ASSERT(vm.atomicStringTable() == wtfThreadData().atomicStringTable()); return !!parse<ProgramNode>(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error); }
VM::VM(VMType vmType, HeapType heapType) : m_apiLock(adoptRef(new JSLock(this))) #if ENABLE(ASSEMBLER) , executableAllocator(*this) #endif , heap(this, heapType) , vmType(vmType) , clientData(0) , topCallFrame(CallFrame::noCaller()->removeHostCallFrameFlag()) , arrayConstructorTable(adoptPtr(new HashTable(JSC::arrayConstructorTable))) , arrayPrototypeTable(adoptPtr(new HashTable(JSC::arrayPrototypeTable))) , booleanPrototypeTable(adoptPtr(new HashTable(JSC::booleanPrototypeTable))) , dataViewTable(adoptPtr(new HashTable(JSC::dataViewTable))) , dateTable(adoptPtr(new HashTable(JSC::dateTable))) , dateConstructorTable(adoptPtr(new HashTable(JSC::dateConstructorTable))) , errorPrototypeTable(adoptPtr(new HashTable(JSC::errorPrototypeTable))) , globalObjectTable(adoptPtr(new HashTable(JSC::globalObjectTable))) , jsonTable(adoptPtr(new HashTable(JSC::jsonTable))) , numberConstructorTable(adoptPtr(new HashTable(JSC::numberConstructorTable))) , numberPrototypeTable(adoptPtr(new HashTable(JSC::numberPrototypeTable))) , objectConstructorTable(adoptPtr(new HashTable(JSC::objectConstructorTable))) , privateNamePrototypeTable(adoptPtr(new HashTable(JSC::privateNamePrototypeTable))) , regExpTable(adoptPtr(new HashTable(JSC::regExpTable))) , regExpConstructorTable(adoptPtr(new HashTable(JSC::regExpConstructorTable))) , regExpPrototypeTable(adoptPtr(new HashTable(JSC::regExpPrototypeTable))) , stringConstructorTable(adoptPtr(new HashTable(JSC::stringConstructorTable))) #if ENABLE(PROMISES) , promisePrototypeTable(adoptPtr(new HashTable(JSC::promisePrototypeTable))) , promiseConstructorTable(adoptPtr(new HashTable(JSC::promiseConstructorTable))) , promiseResolverPrototypeTable(adoptPtr(new HashTable(JSC::promiseResolverPrototypeTable))) #endif , identifierTable(vmType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable()) , propertyNames(new CommonIdentifiers(this)) , emptyList(new MarkedArgumentBuffer) , parserArena(adoptPtr(new ParserArena)) , keywords(adoptPtr(new Keywords(this))) , interpreter(0) , jsArrayClassInfo(JSArray::info()) , jsFinalObjectClassInfo(JSFinalObject::info()) #if ENABLE(DFG_JIT) , sizeOfLastScratchBuffer(0) #endif , dynamicGlobalObject(0) , m_enabledProfiler(0) , m_regExpCache(new RegExpCache(this)) #if ENABLE(REGEXP_TRACING) , m_rtTraceList(new RTTraceList()) #endif , exclusiveThread(0) , m_newStringsSinceLastHashCons(0) #if ENABLE(ASSEMBLER) , m_canUseAssembler(enableAssembler(executableAllocator)) #endif #if ENABLE(JIT) , m_canUseJIT(m_canUseAssembler && Options::useJIT()) #endif #if ENABLE(YARR_JIT) , m_canUseRegExpJIT(m_canUseAssembler && Options::useRegExpJIT()) #endif #if ENABLE(GC_VALIDATION) , m_initializingObjectClass(0) #endif , m_inDefineOwnProperty(false) , m_codeCache(CodeCache::create()) { interpreter = new Interpreter(*this); // Need to be careful to keep everything consistent here JSLockHolder lock(this); IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable); structureStructure.set(*this, Structure::createStructure(*this)); structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull())); debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, 0, jsNull())); terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull())); stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull())); notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull())); propertyNameIteratorStructure.set(*this, JSPropertyNameIterator::createStructure(*this, 0, jsNull())); getterSetterStructure.set(*this, GetterSetter::createStructure(*this, 0, jsNull())); apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, 0, jsNull())); JSScopeStructure.set(*this, JSScope::createStructure(*this, 0, jsNull())); executableStructure.set(*this, ExecutableBase::createStructure(*this, 0, jsNull())); nativeExecutableStructure.set(*this, NativeExecutable::createStructure(*this, 0, jsNull())); evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, 0, jsNull())); programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull())); functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull())); regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull())); sharedSymbolTableStructure.set(*this, SharedSymbolTable::createStructure(*this, 0, jsNull())); structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull())); sparseArrayValueMapStructure.set(*this, SparseArrayValueMap::createStructure(*this, 0, jsNull())); withScopeStructure.set(*this, JSWithScope::createStructure(*this, 0, jsNull())); unlinkedFunctionExecutableStructure.set(*this, UnlinkedFunctionExecutable::createStructure(*this, 0, jsNull())); unlinkedProgramCodeBlockStructure.set(*this, UnlinkedProgramCodeBlock::createStructure(*this, 0, jsNull())); unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull())); unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull())); propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull())); smallStrings.initializeCommonStrings(*this); wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable); #if ENABLE(JIT) jitStubs = adoptPtr(new JITThunks()); performPlatformSpecificJITAssertions(this); #endif interpreter->initialize(this->canUseJIT()); #if ENABLE(JIT) initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support. #endif heap.notifyIsSafeToCollect(); LLInt::Data::performAssertions(*this); if (Options::enableProfiler()) { m_perBytecodeProfiler = adoptPtr(new Profiler::Database(*this)); StringPrintStream pathOut; #if !OS(WINCE) const char* profilerPath = getenv("JSC_PROFILER_PATH"); if (profilerPath) pathOut.print(profilerPath, "/"); #endif pathOut.print("JSCProfile-", getCurrentProcessID(), "-", m_perBytecodeProfiler->databaseID(), ".json"); m_perBytecodeProfiler->registerToSaveAtExit(pathOut.toCString().data()); } #if ENABLE(DFG_JIT) if (canUseJIT()) dfgState = adoptPtr(new DFG::LongLivedState()); #endif // Initialize this last, as a free way of asserting that VM initialization itself // won't use this. m_typedArrayController = adoptRef(new SimpleTypedArrayController()); }
NEVER_INLINE void Heap::collectImpl(HeapOperation collectionType, void* stackOrigin, void* stackTop, MachineThreads::RegisterState& calleeSavedRegisters) { #if ENABLE(ALLOCATION_LOGGING) dataLogF("JSC GC starting collection.\n"); #endif double before = 0; if (Options::logGC()) { dataLog("[GC: "); before = currentTimeMS(); } SamplingRegion samplingRegion("Garbage Collection"); if (vm()->typeProfiler()) { DeferGCForAWhile awhile(*this); vm()->typeProfilerLog()->processLogEntries(ASCIILiteral("GC")); } RELEASE_ASSERT(!m_deferralDepth); ASSERT(vm()->currentThreadIsHoldingAPILock()); RELEASE_ASSERT(vm()->atomicStringTable() == wtfThreadData().atomicStringTable()); ASSERT(m_isSafeToCollect); JAVASCRIPTCORE_GC_BEGIN(); RELEASE_ASSERT(m_operationInProgress == NoOperation); suspendCompilerThreads(); willStartCollection(collectionType); GCPHASE(Collect); double gcStartTime = WTF::monotonicallyIncreasingTime(); if (m_verifier) { // Verify that live objects from the last GC cycle haven't been corrupted by // mutators before we begin this new GC cycle. m_verifier->verify(HeapVerifier::Phase::BeforeGC); m_verifier->initializeGCCycle(); m_verifier->gatherLiveObjects(HeapVerifier::Phase::BeforeMarking); } flushOldStructureIDTables(); stopAllocation(); flushWriteBarrierBuffer(); markRoots(gcStartTime, stackOrigin, stackTop, calleeSavedRegisters); if (m_verifier) { m_verifier->gatherLiveObjects(HeapVerifier::Phase::AfterMarking); m_verifier->verify(HeapVerifier::Phase::AfterMarking); } JAVASCRIPTCORE_GC_MARKED(); if (vm()->typeProfiler()) vm()->typeProfiler()->invalidateTypeSetCache(); reapWeakHandles(); pruneStaleEntriesFromWeakGCMaps(); sweepArrayBuffers(); snapshotMarkedSpace(); copyBackingStores(); finalizeUnconditionalFinalizers(); removeDeadCompilerWorklistEntries(); deleteUnmarkedCompiledCode(); deleteSourceProviderCaches(); notifyIncrementalSweeper(); rememberCurrentlyExecutingCodeBlocks(); resetAllocators(); updateAllocationLimits(); didFinishCollection(gcStartTime); resumeCompilerThreads(); if (m_verifier) { m_verifier->trimDeadObjects(); m_verifier->verify(HeapVerifier::Phase::AfterGC); } if (Options::logGC()) { double after = currentTimeMS(); dataLog(after - before, " ms]\n"); } }
void Identifier::checkCurrentIdentifierTable(JSGlobalData* globalData) { // Check the identifier table accessible through the threadspecific matches the // globalData's identifier table. ASSERT_UNUSED(globalData, globalData->identifierTable == wtfThreadData().currentIdentifierTable()); }
JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType, HeapSize heapSize) : globalDataType(globalDataType) , clientData(0) , topCallFrame(CallFrame::noCaller()) , arrayConstructorTable(fastNew<HashTable>(JSC::arrayConstructorTable)) , arrayPrototypeTable(fastNew<HashTable>(JSC::arrayPrototypeTable)) , booleanPrototypeTable(fastNew<HashTable>(JSC::booleanPrototypeTable)) , dateTable(fastNew<HashTable>(JSC::dateTable)) , dateConstructorTable(fastNew<HashTable>(JSC::dateConstructorTable)) , errorPrototypeTable(fastNew<HashTable>(JSC::errorPrototypeTable)) , globalObjectTable(fastNew<HashTable>(JSC::globalObjectTable)) , jsonTable(fastNew<HashTable>(JSC::jsonTable)) , mathTable(fastNew<HashTable>(JSC::mathTable)) , numberConstructorTable(fastNew<HashTable>(JSC::numberConstructorTable)) , numberPrototypeTable(fastNew<HashTable>(JSC::numberPrototypeTable)) , objectConstructorTable(fastNew<HashTable>(JSC::objectConstructorTable)) , objectPrototypeTable(fastNew<HashTable>(JSC::objectPrototypeTable)) , regExpTable(fastNew<HashTable>(JSC::regExpTable)) , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable)) , regExpPrototypeTable(fastNew<HashTable>(JSC::regExpPrototypeTable)) , stringTable(fastNew<HashTable>(JSC::stringTable)) , stringConstructorTable(fastNew<HashTable>(JSC::stringConstructorTable)) , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable()) , propertyNames(new CommonIdentifiers(this)) , emptyList(new MarkedArgumentBuffer) #if ENABLE(ASSEMBLER) , executableAllocator(*this) #endif , parserArena(adoptPtr(new ParserArena)) , keywords(adoptPtr(new Keywords(this))) , interpreter(0) , heap(this, heapSize) #if ENABLE(DFG_JIT) , sizeOfLastScratchBuffer(0) #endif , dynamicGlobalObject(0) , cachedUTCOffset(std::numeric_limits<double>::quiet_NaN()) , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth) , m_regExpCache(new RegExpCache(this)) #if ENABLE(REGEXP_TRACING) , m_rtTraceList(new RTTraceList()) #endif #ifndef NDEBUG , exclusiveThread(0) #endif #if CPU(X86) && ENABLE(JIT) , m_timeoutCount(512) #endif #if ENABLE(GC_VALIDATION) , m_isInitializingObject(false) #endif { interpreter = new Interpreter; if (globalDataType == Default) m_stack = wtfThreadData().stack(); // Need to be careful to keep everything consistent here IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable); JSLock lock(SilenceAssertionsOnly); structureStructure.set(*this, Structure::createStructure(*this)); debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, 0, jsNull())); activationStructure.set(*this, JSActivation::createStructure(*this, 0, jsNull())); interruptedExecutionErrorStructure.set(*this, InterruptedExecutionError::createStructure(*this, 0, jsNull())); terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull())); staticScopeStructure.set(*this, JSStaticScopeObject::createStructure(*this, 0, jsNull())); strictEvalActivationStructure.set(*this, StrictEvalActivation::createStructure(*this, 0, jsNull())); stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull())); notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull())); propertyNameIteratorStructure.set(*this, JSPropertyNameIterator::createStructure(*this, 0, jsNull())); getterSetterStructure.set(*this, GetterSetter::createStructure(*this, 0, jsNull())); apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, 0, jsNull())); scopeChainNodeStructure.set(*this, ScopeChainNode::createStructure(*this, 0, jsNull())); executableStructure.set(*this, ExecutableBase::createStructure(*this, 0, jsNull())); nativeExecutableStructure.set(*this, NativeExecutable::createStructure(*this, 0, jsNull())); evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, 0, jsNull())); programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull())); functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull())); regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull())); structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull())); wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable); #if ENABLE(JIT) && ENABLE(INTERPRETER) #if USE(CF) CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman); CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication); if (canUseJIT) { m_canUseJIT = kCFBooleanTrue == canUseJIT; CFRelease(canUseJIT); } else { char* canUseJITString = getenv("JavaScriptCoreUseJIT"); m_canUseJIT = !canUseJITString || atoi(canUseJITString); } CFRelease(canUseJITKey); #elif OS(UNIX) char* canUseJITString = getenv("JavaScriptCoreUseJIT"); m_canUseJIT = !canUseJITString || atoi(canUseJITString); #else m_canUseJIT = true; #endif #endif #if ENABLE(JIT) #if ENABLE(INTERPRETER) if (m_canUseJIT) m_canUseJIT = executableAllocator.isValid(); #endif jitStubs = adoptPtr(new JITThunks(this)); #endif interpreter->initialize(this->canUseJIT()); heap.notifyIsSafeToCollect(); }
JSGlueAPIEntry::~JSGlueAPIEntry() { wtfThreadData().setCurrentIdentifierTable(m_storedIdentifierTable); }
JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType) : #if ENABLE(ASSEMBLER) executableAllocator(*this), #endif heap(this, heapType) , globalDataType(globalDataType) , clientData(0) , topCallFrame(CallFrame::noCaller()) , arrayConstructorTable(fastNew<HashTable>(JSC::arrayConstructorTable)) , arrayPrototypeTable(fastNew<HashTable>(JSC::arrayPrototypeTable)) , booleanPrototypeTable(fastNew<HashTable>(JSC::booleanPrototypeTable)) , dateTable(fastNew<HashTable>(JSC::dateTable)) , dateConstructorTable(fastNew<HashTable>(JSC::dateConstructorTable)) , errorPrototypeTable(fastNew<HashTable>(JSC::errorPrototypeTable)) , globalObjectTable(fastNew<HashTable>(JSC::globalObjectTable)) , jsonTable(fastNew<HashTable>(JSC::jsonTable)) , mathTable(fastNew<HashTable>(JSC::mathTable)) , numberConstructorTable(fastNew<HashTable>(JSC::numberConstructorTable)) , numberPrototypeTable(fastNew<HashTable>(JSC::numberPrototypeTable)) , objectConstructorTable(fastNew<HashTable>(JSC::objectConstructorTable)) , objectPrototypeTable(fastNew<HashTable>(JSC::objectPrototypeTable)) , privateNamePrototypeTable(fastNew<HashTable>(JSC::privateNamePrototypeTable)) , regExpTable(fastNew<HashTable>(JSC::regExpTable)) , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable)) , regExpPrototypeTable(fastNew<HashTable>(JSC::regExpPrototypeTable)) , stringTable(fastNew<HashTable>(JSC::stringTable)) , stringConstructorTable(fastNew<HashTable>(JSC::stringConstructorTable)) , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable()) , propertyNames(new CommonIdentifiers(this)) , emptyList(new MarkedArgumentBuffer) , parserArena(adoptPtr(new ParserArena)) , keywords(adoptPtr(new Keywords(this))) , interpreter(0) , jsArrayClassInfo(&JSArray::s_info) , jsFinalObjectClassInfo(&JSFinalObject::s_info) #if ENABLE(DFG_JIT) , sizeOfLastScratchBuffer(0) #endif , dynamicGlobalObject(0) , cachedUTCOffset(QNaN) , m_enabledProfiler(0) , m_regExpCache(new RegExpCache(this)) #if ENABLE(REGEXP_TRACING) , m_rtTraceList(new RTTraceList()) #endif #ifndef NDEBUG , exclusiveThread(0) #endif #if CPU(X86) && ENABLE(JIT) , m_timeoutCount(512) #endif , m_newStringsSinceLastHashConst(0) #if ENABLE(ASSEMBLER) , m_canUseAssembler(enableAssembler(executableAllocator)) #endif #if ENABLE(JIT) , m_canUseJIT(m_canUseAssembler && Options::useJIT()) #endif #if ENABLE(YARR_JIT) , m_canUseRegExpJIT(m_canUseAssembler && Options::useRegExpJIT()) #endif #if ENABLE(GC_VALIDATION) , m_initializingObjectClass(0) #endif , m_inDefineOwnProperty(false) , m_codeCache(CodeCache::create()) { interpreter = new Interpreter(*this); // Need to be careful to keep everything consistent here JSLockHolder lock(this); IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable); structureStructure.set(*this, Structure::createStructure(*this)); debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, 0, jsNull())); interruptedExecutionErrorStructure.set(*this, InterruptedExecutionError::createStructure(*this, 0, jsNull())); terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull())); stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull())); notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull())); propertyNameIteratorStructure.set(*this, JSPropertyNameIterator::createStructure(*this, 0, jsNull())); getterSetterStructure.set(*this, GetterSetter::createStructure(*this, 0, jsNull())); apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, 0, jsNull())); JSScopeStructure.set(*this, JSScope::createStructure(*this, 0, jsNull())); executableStructure.set(*this, ExecutableBase::createStructure(*this, 0, jsNull())); nativeExecutableStructure.set(*this, NativeExecutable::createStructure(*this, 0, jsNull())); evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, 0, jsNull())); programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull())); functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull())); regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull())); sharedSymbolTableStructure.set(*this, SharedSymbolTable::createStructure(*this, 0, jsNull())); structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull())); sparseArrayValueMapStructure.set(*this, SparseArrayValueMap::createStructure(*this, 0, jsNull())); withScopeStructure.set(*this, JSWithScope::createStructure(*this, 0, jsNull())); unlinkedFunctionExecutableStructure.set(*this, UnlinkedFunctionExecutable::createStructure(*this, 0, jsNull())); unlinkedProgramCodeBlockStructure.set(*this, UnlinkedProgramCodeBlock::createStructure(*this, 0, jsNull())); unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull())); unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull())); wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable); #if ENABLE(JIT) jitStubs = adoptPtr(new JITThunks(this)); #endif interpreter->initialize(this->canUseJIT()); #if ENABLE(JIT) initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support. #endif heap.notifyIsSafeToCollect(); LLInt::Data::performAssertions(*this); if (Options::enableProfiler()) m_perBytecodeProfiler = adoptPtr(new Profiler::Database(*this)); }
JSGlueAPICallback::JSGlueAPICallback(ExecState* exec) : m_dropLocks(exec) { wtfThreadData().resetCurrentIdentifierTable(); }
void Heap::collect(SweepToggle sweepToggle) { SamplingRegion samplingRegion("Garbage Collection"); GCPHASE(Collect); ASSERT(globalData()->apiLock().currentThreadIsHoldingLock()); RELEASE_ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); ASSERT(m_isSafeToCollect); JAVASCRIPTCORE_GC_BEGIN(); RELEASE_ASSERT(m_operationInProgress == NoOperation); m_operationInProgress = Collection; m_activityCallback->willCollect(); double lastGCStartTime = WTF::currentTime(); if (lastGCStartTime - m_lastCodeDiscardTime > minute) { deleteAllCompiledCode(); m_lastCodeDiscardTime = WTF::currentTime(); } { GCPHASE(Canonicalize); m_objectSpace.canonicalizeCellLivenessData(); } markRoots(); { GCPHASE(ReapingWeakHandles); m_objectSpace.reapWeakSets(); } JAVASCRIPTCORE_GC_MARKED(); { m_blockSnapshot.resize(m_objectSpace.blocks().set().size()); MarkedBlockSnapshotFunctor functor(m_blockSnapshot); m_objectSpace.forEachBlock(functor); } copyBackingStores(); { GCPHASE(FinalizeUnconditionalFinalizers); finalizeUnconditionalFinalizers(); } { GCPHASE(finalizeSmallStrings); m_globalData->smallStrings.finalizeSmallStrings(); } { GCPHASE(DeleteCodeBlocks); deleteUnmarkedCompiledCode(); } { GCPHASE(DeleteSourceProviderCaches); m_globalData->clearSourceProviderCaches(); } if (sweepToggle == DoSweep) { SamplingRegion samplingRegion("Garbage Collection: Sweeping"); GCPHASE(Sweeping); m_objectSpace.sweep(); m_objectSpace.shrink(); } m_sweeper->startSweeping(m_blockSnapshot); m_bytesAbandoned = 0; { GCPHASE(ResetAllocators); m_objectSpace.resetAllocators(); } size_t currentHeapSize = size(); if (Options::gcMaxHeapSize() && currentHeapSize > Options::gcMaxHeapSize()) HeapStatistics::exitWithFailure(); m_sizeAfterLastCollect = currentHeapSize; // To avoid pathological GC churn in very small and very large heaps, we set // the new allocation limit based on the current size of the heap, with a // fixed minimum. size_t maxHeapSize = max(minHeapSize(m_heapType, m_ramSize), proportionalHeapSize(currentHeapSize, m_ramSize)); m_bytesAllocatedLimit = maxHeapSize - currentHeapSize; m_bytesAllocated = 0; double lastGCEndTime = WTF::currentTime(); m_lastGCLength = lastGCEndTime - lastGCStartTime; if (Options::recordGCPauseTimes()) HeapStatistics::recordGCPauseTime(lastGCStartTime, lastGCEndTime); RELEASE_ASSERT(m_operationInProgress == Collection); m_operationInProgress = NoOperation; JAVASCRIPTCORE_GC_END(); if (Options::useZombieMode()) zombifyDeadObjects(); if (Options::objectsAreImmortal()) markDeadObjects(); if (Options::showObjectStatistics()) HeapStatistics::showObjectStatistics(this); }
JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType, HeapSize heapSize) : heap(this, heapSize) , globalDataType(globalDataType) , clientData(0) , topCallFrame(CallFrame::noCaller()) , arrayConstructorTable(fastNew<HashTable>(JSC::arrayConstructorTable)) , arrayPrototypeTable(fastNew<HashTable>(JSC::arrayPrototypeTable)) , booleanPrototypeTable(fastNew<HashTable>(JSC::booleanPrototypeTable)) , dateTable(fastNew<HashTable>(JSC::dateTable)) , dateConstructorTable(fastNew<HashTable>(JSC::dateConstructorTable)) , errorPrototypeTable(fastNew<HashTable>(JSC::errorPrototypeTable)) , globalObjectTable(fastNew<HashTable>(JSC::globalObjectTable)) , jsonTable(fastNew<HashTable>(JSC::jsonTable)) , mathTable(fastNew<HashTable>(JSC::mathTable)) , numberConstructorTable(fastNew<HashTable>(JSC::numberConstructorTable)) , numberPrototypeTable(fastNew<HashTable>(JSC::numberPrototypeTable)) , objectConstructorTable(fastNew<HashTable>(JSC::objectConstructorTable)) , objectPrototypeTable(fastNew<HashTable>(JSC::objectPrototypeTable)) , regExpTable(fastNew<HashTable>(JSC::regExpTable)) , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable)) , regExpPrototypeTable(fastNew<HashTable>(JSC::regExpPrototypeTable)) , stringTable(fastNew<HashTable>(JSC::stringTable)) , stringConstructorTable(fastNew<HashTable>(JSC::stringConstructorTable)) , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable()) , propertyNames(new CommonIdentifiers(this)) , emptyList(new MarkedArgumentBuffer) #if ENABLE(ASSEMBLER) , executableAllocator(*this) #endif , parserArena(adoptPtr(new ParserArena)) , keywords(adoptPtr(new Keywords(this))) , interpreter(0) , jsArrayClassInfo(&JSArray::s_info) , jsFinalObjectClassInfo(&JSFinalObject::s_info) #if ENABLE(DFG_JIT) , sizeOfLastScratchBuffer(0) #endif , dynamicGlobalObject(0) , cachedUTCOffset(std::numeric_limits<double>::quiet_NaN()) , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth) , m_regExpCache(new RegExpCache(this)) #if ENABLE(REGEXP_TRACING) , m_rtTraceList(new RTTraceList()) #endif #ifndef NDEBUG , exclusiveThread(0) #endif #if CPU(X86) && ENABLE(JIT) , m_timeoutCount(512) #endif #if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) , m_canUseAssembler(enableAssembler(executableAllocator)) #endif #if ENABLE(GC_VALIDATION) , m_initializingObjectClass(0) #endif , m_inDefineOwnProperty(false) { interpreter = new Interpreter; if (isSharedInstance()) turnOffVerifier(); // Need to be careful to keep everything consistent here IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable); JSLock lock(SilenceAssertionsOnly); structureStructure.set(*this, Structure::createStructure(*this)); debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, 0, jsNull())); activationStructure.set(*this, JSActivation::createStructure(*this, 0, jsNull())); interruptedExecutionErrorStructure.set(*this, InterruptedExecutionError::createStructure(*this, 0, jsNull())); terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull())); staticScopeStructure.set(*this, JSStaticScopeObject::createStructure(*this, 0, jsNull())); strictEvalActivationStructure.set(*this, StrictEvalActivation::createStructure(*this, 0, jsNull())); stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull())); notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull())); propertyNameIteratorStructure.set(*this, JSPropertyNameIterator::createStructure(*this, 0, jsNull())); getterSetterStructure.set(*this, GetterSetter::createStructure(*this, 0, jsNull())); apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, 0, jsNull())); scopeChainNodeStructure.set(*this, ScopeChainNode::createStructure(*this, 0, jsNull())); executableStructure.set(*this, ExecutableBase::createStructure(*this, 0, jsNull())); nativeExecutableStructure.set(*this, NativeExecutable::createStructure(*this, 0, jsNull())); evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, 0, jsNull())); programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull())); functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull())); regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull())); structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull())); wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable); #if ENABLE(JIT) jitStubs = adoptPtr(new JITThunks(this)); #endif interpreter->initialize(&llintData, this->canUseJIT()); initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support. heap.notifyIsSafeToCollect(); llintData.performAssertions(*this); }