void JSGlobalObject::haveABadTime(VM& vm) { ASSERT(&vm == &this->vm()); if (isHavingABadTime()) return; // Make sure that all allocations or indexed storage transitions that are inlining // the assumption that it's safe to transition to a non-SlowPut array storage don't // do so anymore. m_havingABadTimeWatchpoint->fireAll(); ASSERT(isHavingABadTime()); // The watchpoint is what tells us that we're having a bad time. // Make sure that all JSArray allocations that load the appropriate structure from // this object now load a structure that uses SlowPut. for (unsigned i = 0; i < NumberOfIndexingShapes; ++i) m_arrayStructureForIndexingShapeDuringAllocation[i].set(vm, this, originalArrayStructureForIndexingType(ArrayWithSlowPutArrayStorage)); // Make sure that all objects that have indexed storage switch to the slow kind of // indexed storage. MarkedArgumentBuffer foundObjects; // Use MarkedArgumentBuffer because switchToSlowPutArrayStorage() may GC. ObjectsWithBrokenIndexingFinder finder(foundObjects, this); { HeapIterationScope iterationScope(vm.heap); vm.heap.objectSpace().forEachLiveCell(iterationScope, finder); } while (!foundObjects.isEmpty()) { JSObject* object = asObject(foundObjects.last()); foundObjects.removeLast(); ASSERT(hasBrokenIndexing(object)); object->switchToSlowPutArrayStorage(vm); } }
void VM::releaseExecutableMemory() { prepareToDiscardCode(); if (entryScope) { StackPreservingRecompiler recompiler; HeapIterationScope iterationScope(heap); HashSet<JSCell*> roots; heap.getConservativeRegisterRoots(roots); HashSet<JSCell*>::iterator end = roots.end(); for (HashSet<JSCell*>::iterator ptr = roots.begin(); ptr != end; ++ptr) { ScriptExecutable* executable = 0; JSCell* cell = *ptr; if (cell->inherits(ScriptExecutable::info())) executable = static_cast<ScriptExecutable*>(*ptr); else if (cell->inherits(JSFunction::info())) { JSFunction* function = jsCast<JSFunction*>(*ptr); if (function->isHostFunction()) continue; executable = function->jsExecutable(); } else continue; ASSERT(executable->inherits(ScriptExecutable::info())); executable->unlinkCalls(); if (executable->inherits(FunctionExecutable::info())) recompiler.currentlyExecutingFunctions.add(static_cast<FunctionExecutable*>(executable)); } heap.objectSpace().forEachLiveCell<StackPreservingRecompiler>(iterationScope, recompiler); } m_regExpCache->invalidateCode(); heap.collectAllGarbage(); }
void Heap::zombifyDeadObjects() { // Sweep now because destructors will crash once we're zombified. m_objectSpace.sweep(); HeapIterationScope iterationScope(*this); m_objectSpace.forEachDeadCell<Zombify>(iterationScope); }
bool JSDollarVMPrototype::isValidCell(Heap* heap, JSCell* candidate) { HeapIterationScope iterationScope(*heap); CellAddressCheckFunctor functor(candidate); heap->objectSpace().forEachLiveCell(iterationScope, functor); return functor.found; }
void HeapStatistics::dumpObjectStatistics(Heap* heap) { dataLogF("\n=== Heap Statistics: ===\n"); dataLogF("size: %ldkB\n", static_cast<long>(heap->m_sizeAfterLastCollect / KB)); dataLogF("capacity: %ldkB\n", static_cast<long>(heap->capacity() / KB)); dataLogF("pause time: %lfs\n\n", heap->m_lastFullGCLength); StorageStatistics storageStatistics; { HeapIterationScope iterationScope(*heap); heap->m_objectSpace.forEachLiveCell(iterationScope, storageStatistics); } long wastedPropertyStorageBytes = 0; long wastedPropertyStoragePercent = 0; long objectWithOutOfLineStorageCount = 0; long objectsWithOutOfLineStoragePercent = 0; if ((storageStatistics.storageCapacity() > 0) && (storageStatistics.objectCount() > 0)) { wastedPropertyStorageBytes = static_cast<long>((storageStatistics.storageCapacity() - storageStatistics.storageSize()) / KB); wastedPropertyStoragePercent = static_cast<long>( (storageStatistics.storageCapacity() - storageStatistics.storageSize()) * 100 / storageStatistics.storageCapacity()); objectWithOutOfLineStorageCount = static_cast<long>(storageStatistics.objectWithOutOfLineStorageCount()); objectsWithOutOfLineStoragePercent = objectWithOutOfLineStorageCount * 100 / storageStatistics.objectCount(); } dataLogF("wasted .property storage: %ldkB (%ld%%)\n", wastedPropertyStorageBytes, wastedPropertyStoragePercent); dataLogF("objects with out-of-line .property storage: %ld (%ld%%)\n", objectWithOutOfLineStorageCount, objectsWithOutOfLineStoragePercent); }
void HeapStatistics::showObjectStatistics(Heap* heap) { dataLogF("\n=== Heap Statistics: ===\n"); dataLogF("size: %ldkB\n", static_cast<long>(heap->m_sizeAfterLastCollect / KB)); dataLogF("capacity: %ldkB\n", static_cast<long>(heap->capacity() / KB)); dataLogF("pause time: %lfms\n\n", heap->m_lastGCLength); StorageStatistics storageStatistics; { HeapIterationScope iterationScope(*heap); heap->m_objectSpace.forEachLiveCell(iterationScope, storageStatistics); } dataLogF("wasted .property storage: %ldkB (%ld%%)\n", static_cast<long>( (storageStatistics.storageCapacity() - storageStatistics.storageSize()) / KB), static_cast<long>( (storageStatistics.storageCapacity() - storageStatistics.storageSize()) * 100 / storageStatistics.storageCapacity())); dataLogF("objects with out-of-line .property storage: %ld (%ld%%)\n", static_cast<long>( storageStatistics.objectWithOutOfLineStorageCount()), static_cast<long>( storageStatistics.objectWithOutOfLineStorageCount() * 100 / storageStatistics.objectCount())); }
void HeapVerifier::gatherLiveObjects(HeapVerifier::Phase phase) { Heap* heap = m_heap; LiveObjectList& list = *liveObjectListForGathering(phase); HeapIterationScope iterationScope(*heap); list.reset(); GatherLiveObjFunctor functor(list); heap->m_objectSpace.forEachLiveCell(iterationScope, functor); }
void Heap::zombifyDeadObjects() { // Sweep now because destructors will crash once we're zombified. { SamplingRegion samplingRegion("Garbage Collection: Sweeping"); m_objectSpace.zombifySweep(); } HeapIterationScope iterationScope(*this); m_objectSpace.forEachDeadCell<Zombify>(iterationScope); }
static void recompileAllJSFunctionsForTypeProfiling(VM& vm, bool shouldEnableTypeProfiling) { vm.prepareToDiscardCode(); bool needsToRecompile = (shouldEnableTypeProfiling ? vm.enableTypeProfiler() : vm.disableTypeProfiler()); if (needsToRecompile) { TypeRecompiler recompiler; HeapIterationScope iterationScope(vm.heap); vm.heap.objectSpace().forEachLiveCell(iterationScope, recompiler); } }
static void recompileAllJSFunctionsForTypeProfiling(VM& vm, bool shouldEnableTypeProfiling) { bool shouldRecompileFromTypeProfiler = (shouldEnableTypeProfiling ? vm.enableTypeProfiler() : vm.disableTypeProfiler()); bool shouldRecompileFromControlFlowProfiler = (shouldEnableTypeProfiling ? vm.enableControlFlowProfiler() : vm.disableControlFlowProfiler()); bool needsToRecompile = shouldRecompileFromTypeProfiler || shouldRecompileFromControlFlowProfiler; if (needsToRecompile) { vm.prepareToDeleteCode(); TypeRecompiler recompiler; HeapIterationScope iterationScope(vm.heap); vm.heap.objectSpace().forEachLiveCell(iterationScope, recompiler); } }
void Debugger::recompileAllJSFunctions(VM* vm) { // If JavaScript is running, it's not safe to recompile, since we'll end // up throwing away code that is live on the stack. ASSERT(!vm->dynamicGlobalObject); if (vm->dynamicGlobalObject) return; vm->prepareToDiscardCode(); Recompiler recompiler(this); HeapIterationScope iterationScope(vm->heap); vm->heap.objectSpace().forEachLiveCell(iterationScope, recompiler); }
void Debugger::recompileAllJSFunctions(VM* vm) { // If JavaScript is running, it's not safe to recompile, since we'll end // up throwing away code that is live on the stack. if (vm->entryScope) { vm->entryScope->setRecompilationNeeded(true); return; } vm->prepareToDiscardCode(); Recompiler recompiler(this); HeapIterationScope iterationScope(vm->heap); vm->heap.objectSpace().forEachLiveCell(iterationScope, recompiler); }
void Debugger::attach(JSGlobalObject* globalObject) { ASSERT(!globalObject->debugger()); globalObject->setDebugger(this); m_globalObjects.add(globalObject); // Call sourceParsed() because it will execute JavaScript in the inspector. GatherSourceProviders gatherSourceProviders(this); { HeapIterationScope iterationScope(m_vm.heap); m_vm.heap.objectSpace().forEachLiveCell(iterationScope, gatherSourceProviders); } for (auto* sourceProvider : gatherSourceProviders.sourceProviders) sourceParsed(globalObject->globalExec(), sourceProvider, -1, String()); }
void Debugger::recompileAllJSFunctions(VM* vm) { // If JavaScript is running, it's not safe to recompile, since we'll end // up throwing away code that is live on the stack. if (vm->entryScope) { auto listener = [] (VM& vm, JSGlobalObject* globalObject) { if (Debugger* debugger = globalObject->debugger()) debugger->recompileAllJSFunctions(&vm); }; vm->entryScope->setEntryScopeDidPopListener(this, listener); return; } vm->prepareToDiscardCode(); Recompiler recompiler(this); HeapIterationScope iterationScope(vm->heap); vm->heap.objectSpace().forEachLiveCell(iterationScope, recompiler); }
void Heap::markDeadObjects() { HeapIterationScope iterationScope(*this); m_objectSpace.forEachDeadCell<MarkObject>(iterationScope); }
PassOwnPtr<TypeCountSet> Heap::objectTypeCounts() { HeapIterationScope iterationScope(*this); return m_objectSpace.forEachLiveCell<RecordType>(iterationScope); }
size_t Heap::globalObjectCount() { HeapIterationScope iterationScope(*this); return m_objectSpace.forEachLiveCell<CountIfGlobalObject>(iterationScope); }