Ejemplo n.º 1
0
void SamplingProfiler::dispatchIfNecessary(const LockHolder& locker)
{
    if (m_isActive && !m_hasDispatchedFunction && m_jscExecutionThread && m_vm.entryScope) {
        ref(); // Matching deref() is inside m_handler when m_handler stops recursing.
        dispatchFunction(locker);
    }
}
void BatchingUIManager::measure(folly::dynamic&& args, facebook::xplat::module::CxxModule::Callback cb)
{
  auto manager = shared_from_this();
  dispatchFunction([manager, args, cb]()
  {
    static_cast<IUIManager*>(manager.get())->measure(jsArgAsInt(args, 0), cb);
  });
}
void BatchingUIManager::removeRootView(folly::dynamic&& args)
{
  auto manager = std::static_pointer_cast<UIManager>(shared_from_this());
  dispatchFunction([manager, args]()
  {
    manager->removeRootView(jsArgAsInt(args, 0));
  });
}
void BatchingUIManager::replaceExistingNonRootView(folly::dynamic&& args)
{
  auto manager = shared_from_this();
  dispatchFunction([manager, args]()
  {
    static_cast<IUIManager*>(manager.get())->replaceExistingNonRootView(jsArgAsInt(args, 0), jsArgAsInt(args, 1));
  });
}
void BatchingUIManager::removeSubviewsFromContainerWithID(folly::dynamic&& args)
{
  auto manager = shared_from_this();
  dispatchFunction([manager, args]()
  {
    static_cast<IUIManager*>(manager.get())->removeSubviewsFromContainerWithID(jsArgAsInt(args, 0));
  });
}
void BatchingUIManager::createView(folly::dynamic&& args)
{
  auto manager = shared_from_this();
  dispatchFunction([manager, args]()
  {
    auto arg3 = jsArgAsDynamic(args, 3);
    static_cast<IUIManager*>(manager.get())->createView(jsArgAsInt(args, 0), jsArgAsString(args, 1), jsArgAsInt(args, 2), std::move(arg3));
  });
}
void BatchingUIManager::configureNextLayoutAnimation(folly::dynamic&& args, facebook::xplat::module::CxxModule::Callback success, facebook::xplat::module::CxxModule::Callback error)
{
  auto manager = shared_from_this();
  dispatchFunction([manager, args, success, error]()
  {
    auto config = jsArgAsDynamic(args, 3);
    manager->configureNextLayoutAnimation(std::move(config), success, error);
  });
}
void BatchingUIManager::dispatchViewManagerCommand(folly::dynamic&& args)
{
  auto manager = shared_from_this();
  dispatchFunction([manager, args]()
  {
    auto arg2 = jsArgAsDynamic(args, 2);
    static_cast<IUIManager*>(manager.get())->dispatchViewManagerCommand(jsArgAsInt(args, 0), jsArgAsInt(args, 1), std::move(arg2));
  });
}
void BatchingUIManager::setChildren(folly::dynamic&& args)
{
  auto manager = shared_from_this();
  dispatchFunction([manager, args]()
  {
    auto arg1 = jsArgAsArray(args, 1);
    static_cast<IUIManager*>(manager.get())->setChildren(jsArgAsInt(args, 0), std::move(arg1));
  });
}
void BatchingUIManager::manageChildren(folly::dynamic&& args)
{
  auto manager = shared_from_this();
  dispatchFunction([manager, args]()
  {
    auto arg1 = jsArgAsDynamic(args, 1);
    auto arg2 = jsArgAsDynamic(args, 2);
    auto arg3 = jsArgAsDynamic(args, 3);
    auto arg4 = jsArgAsDynamic(args, 4);
    auto arg5 = jsArgAsDynamic(args, 5);
    static_cast<IUIManager*>(manager.get())->manageChildren(jsArgAsInt(args, 0), arg1, arg2, arg3, arg4, arg5);
  });
}
Ejemplo n.º 11
0
SamplingProfiler::SamplingProfiler(VM& vm, RefPtr<Stopwatch>&& stopwatch)
    : m_vm(vm)
    , m_stopwatch(WTFMove(stopwatch))
    , m_indexOfNextStackTraceToVerify(0)
    , m_timingInterval(std::chrono::microseconds(1000))
    , m_totalTime(0)
    , m_timerQueue(WorkQueue::create("jsc.sampling-profiler.queue", WorkQueue::Type::Serial, WorkQueue::QOS::UserInteractive))
    , m_jscExecutionThread(nullptr)
    , m_isActive(false)
    , m_isPaused(false)
    , m_hasDispatchedFunction(false)
{
    if (sReportStats) {
        sNumTotalWalks = 0;
        sNumFailedWalks = 0;
    }

    m_currentFrames.grow(256);

    m_handler = [this] () {
        LockHolder samplingProfilerLocker(m_lock);
        if (!m_isActive || !m_jscExecutionThread || m_isPaused) {
            m_hasDispatchedFunction = false;
            deref();
            return;
        }

        if (m_vm.entryScope) {
            double nowTime = m_stopwatch->elapsedTime();

            LockHolder machineThreadsLocker(m_vm.heap.machineThreads().getLock());
            LockHolder codeBlockSetLocker(m_vm.heap.codeBlockSet().getLock());
            LockHolder executableAllocatorLocker(m_vm.executableAllocator.getLock());

            bool didSuspend = m_jscExecutionThread->suspend();
            if (didSuspend) {
                // While the JSC thread is suspended, we can't do things like malloc because the JSC thread
                // may be holding the malloc lock.
                ExecState* callFrame;
                void* pc;
                {
                    MachineThreads::Thread::Registers registers;
                    m_jscExecutionThread->getRegisters(registers);
                    callFrame = static_cast<ExecState*>(registers.framePointer());
                    pc = registers.instructionPointer();
                    m_jscExecutionThread->freeRegisters(registers);
                }
                // FIXME: Lets have a way of detecting when we're parsing code.
                // https://bugs.webkit.org/show_bug.cgi?id=152761
                if (m_vm.executableAllocator.isValidExecutableMemory(executableAllocatorLocker, pc)) {
                    if (m_vm.isExecutingInRegExpJIT) {
                        // FIXME: We're executing a regexp. Lets gather more intersting data.
                        // https://bugs.webkit.org/show_bug.cgi?id=152729
                        callFrame = m_vm.topCallFrame; // We need to do this or else we'd fail our backtrace validation b/c this isn't a JS frame.
                    }
                } else if (LLInt::isLLIntPC(pc)) {
                    // We're okay to take a normal stack trace when the PC
                    // is in LLInt code.
                } else {
                    // We resort to topCallFrame to see if we can get anything
                    // useful. We usually get here when we're executing C code.
                    callFrame = m_vm.topCallFrame;
                }

                size_t walkSize;
                bool wasValidWalk;
                bool didRunOutOfVectorSpace;
                bool stacktraceNeedsVerification;
                {
                    FrameWalker walker(callFrame, m_vm, codeBlockSetLocker, machineThreadsLocker);
                    walkSize = walker.walk(m_currentFrames, didRunOutOfVectorSpace, stacktraceNeedsVerification);
                    wasValidWalk = walker.wasValidWalk();
                }

                m_jscExecutionThread->resume();

                // We can now use data structures that malloc, and do other interesting things, again.

                // FIXME: It'd be interesting to take data about the program's state when
                // we fail to take a stack trace: https://bugs.webkit.org/show_bug.cgi?id=152758
                if (wasValidWalk && walkSize) {
                    if (sReportStats) {
                        sNumTotalStackTraces++;
                        if (stacktraceNeedsVerification)
                            sNumUnverifiedStackTraces++;
                    }
                    Vector<StackFrame> stackTrace;
                    stackTrace.reserveInitialCapacity(walkSize);
                    for (size_t i = 0; i < walkSize; i++) {
                        StackFrame frame = m_currentFrames[i];
                        stackTrace.uncheckedAppend(frame); 
                        if (frame.frameType == FrameType::VerifiedExecutable)
                            m_seenExecutables.add(frame.u.verifiedExecutable);
                    }

                    m_stackTraces.append(StackTrace{ stacktraceNeedsVerification, nowTime, WTFMove(stackTrace) });

                    if (didRunOutOfVectorSpace)
                        m_currentFrames.grow(m_currentFrames.size() * 1.25);

                    m_totalTime += nowTime - m_lastTime;
                }
            }
        }

        m_lastTime = m_stopwatch->elapsedTime();

        dispatchFunction(samplingProfilerLocker);
    };
}