예제 #1
0
void TraceLoader::parseTrace()
{
    QList<ApiTraceFrame*> frames;
    ApiTraceFrame *currentFrame = 0;
    int frameCount = 0;
    QVector<ApiTraceCall*> calls;
    quint64 binaryDataSize = 0;

    int lastPercentReport = 0;

    trace::Call *call = m_parser.parse_call();
    while (call) {
        //std::cout << *call;
        if (!currentFrame) {
            currentFrame = new ApiTraceFrame();
            currentFrame->number = frameCount;
            ++frameCount;
        }
        ApiTraceCall *apiCall =
            apiCallFromTraceCall(call, m_helpHash, currentFrame, this);
        calls.append(apiCall);
        if (apiCall->hasBinaryData()) {
            QByteArray data =
                apiCall->arguments()[apiCall->binaryDataIndex()].toByteArray();
            binaryDataSize += data.size();
        }
        if (ApiTrace::isCallAFrameMarker(apiCall,
                                         m_frameMarker)) {
            calls.squeeze();
            currentFrame->setCalls(calls, binaryDataSize);
            calls.clear();
            frames.append(currentFrame);
            currentFrame = 0;
            binaryDataSize = 0;
            if (frames.count() >= FRAMES_TO_CACHE) {
                emit framesLoaded(frames);
                frames.clear();
            }
            if (m_parser.percentRead() - lastPercentReport >= 5) {
                emit parsed(m_parser.percentRead());
                lastPercentReport = m_parser.percentRead();
            }
        }
        delete call;
        call = m_parser.parse_call();
    }

    //last frames won't have markers
    //  it's just a bunch of Delete calls for every object
    //  after the last SwapBuffers
    if (currentFrame) {
        calls.squeeze();
        currentFrame->setCalls(calls, binaryDataSize);
        frames.append(currentFrame);
        currentFrame = 0;
    }
    if (frames.count()) {
        emit framesLoaded(frames);
    }
}
예제 #2
0
void MainWindow::callItemSelected(const QModelIndex &index)
{
    ApiTraceEvent *event =
        index.data(ApiTraceModel::EventRole).value<ApiTraceEvent*>();

    if (event && event->type() == ApiTraceEvent::Call) {
        ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
        m_ui.detailsDock->setWindowTitle(
            tr("Details View. Frame %1, Call %2")
            .arg(call->parentFrame() ? call->parentFrame()->number : 0)
            .arg(call->index()));
        m_ui.detailsWebView->setHtml(call->toHtml());
        m_ui.detailsDock->show();
        m_ui.callView->scrollTo(index);
        if (call->hasBinaryData()) {
            QByteArray data =
                call->arguments()[call->binaryDataIndex()].toByteArray();
            m_vdataInterpreter->setData(data);

            QVector<QVariant> args = call->arguments();
            for (int i = 0; i < call->argNames().count(); ++i) {
                QString name = call->argNames()[i];
                if (name == QLatin1String("stride")) {
                    int stride = args[i].toInt();
                    m_ui.vertexStrideSB->setValue(stride);
                } else if (name == QLatin1String("size")) {
                    int components = args[i].toInt();
                    m_ui.vertexComponentsSB->setValue(components);
                } else if (name == QLatin1String("type")) {
                    QString val = args[i].toString();
                    int textIndex = m_ui.vertexTypeCB->findText(val);
                    if (textIndex >= 0) {
                        m_ui.vertexTypeCB->setCurrentIndex(textIndex);
                    }
                }
            }
        }
        m_ui.backtraceBrowser->setText(call->backtrace());
        m_ui.backtraceDock->setVisible(!call->backtrace().isNull());
        m_ui.vertexDataDock->setVisible(call->hasBinaryData());
        m_selectedEvent = call;
    } else {
        if (event && event->type() == ApiTraceEvent::Frame) {
            m_selectedEvent = static_cast<ApiTraceFrame*>(event);
        } else {
            m_selectedEvent = 0;
        }
        m_ui.detailsDock->hide();
        m_ui.backtraceDock->hide();
        m_ui.vertexDataDock->hide();
    }
    if (m_selectedEvent && m_selectedEvent->hasState()) {
        fillStateForFrame();
    } else {
        m_ui.stateDock->hide();
    }
}
예제 #3
0
QVector<ApiTraceCall*>
TraceLoader::fetchFrameContents(ApiTraceFrame *currentFrame)
{
    Q_ASSERT(currentFrame);

    if (currentFrame->isLoaded()) {
        return currentFrame->calls();
    }

    if (m_parser.supportsOffsets()) {
        unsigned frameIdx = currentFrame->number;
        int numOfCalls = numberOfCallsInFrame(frameIdx);

        if (numOfCalls) {
            quint64 binaryDataSize = 0;
            QVector<ApiTraceCall*> calls(numOfCalls);
            const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx];

            m_parser.setBookmark(frameBookmark.start);

            trace::Call *call;
            int parsedCalls = 0;
            while ((call = m_parser.parse_call())) {
                ApiTraceCall *apiCall =
                    apiCallFromTraceCall(call, m_helpHash,
                                         currentFrame, this);
                calls[parsedCalls] = apiCall;
                Q_ASSERT(calls[parsedCalls]);
                if (apiCall->hasBinaryData()) {
                    QByteArray data =
                        apiCall->arguments()[
                            apiCall->binaryDataIndex()].toByteArray();
                    binaryDataSize += data.size();
                }

                ++parsedCalls;

                delete call;

                if (apiCall->flags() & trace::CALL_FLAG_END_FRAME) {
                    break;
                }

            }
            assert(parsedCalls == numOfCalls);
            Q_ASSERT(parsedCalls == calls.size());
            calls.squeeze();

            Q_ASSERT(parsedCalls == currentFrame->numChildrenToLoad());
            emit frameContentsLoaded(currentFrame,
                                     calls, binaryDataSize);
            return calls;
        }
    }
    return QVector<ApiTraceCall*>();
}
예제 #4
0
bool
TraceLoader::FrameContents::load(TraceLoader   *loader,
                               ApiTraceFrame *currentFrame, 
                               QHash<QString, QUrl> helpHash,
                               trace::Parser &parser)
{
    bool bEndFrameReached = false;
    int initNumOfCalls = m_allCalls.count();
    trace::Call  *call;
    ApiTraceCall *apiCall = NULL;

    while ((call = parser.parse_call())) {

        apiCall = apiCallFromTraceCall(call, helpHash, currentFrame,
                                       m_groups.isEmpty() ? 0 : m_groups.top(),
                                       loader);
        Q_ASSERT(apiCall);
        if (initNumOfCalls) {
            Q_ASSERT(m_parsedCalls < m_allCalls.size());
            m_allCalls[m_parsedCalls++] = apiCall;
        } else {
            m_allCalls.append(apiCall);
        }
        if (m_groups.count() == 0) {
            m_topLevelItems.append(apiCall);
        } else {
            m_groups.top()->addChild(apiCall);
        }
        if (call->flags & trace::CALL_FLAG_MARKER_PUSH) {
            m_groups.push(apiCall);
        } else if (call->flags & trace::CALL_FLAG_MARKER_POP) {
            if (m_groups.count()) {
                m_groups.top()->finishedAddingChildren();
                m_groups.pop();
            }
        }
        if (apiCall->hasBinaryData()) {
            QByteArray data =
                apiCall->arguments()[apiCall->binaryDataIndex()].
                                                  toByteArray();
            m_binaryDataSize += data.size();
        }

        delete call;

        if (apiCall->flags() & trace::CALL_FLAG_END_FRAME) {
            bEndFrameReached = true;
            break;
        }
    }
    if (initNumOfCalls) {
        // There can be fewer parsed calls when call in different
        // threads cross the frame boundary
        Q_ASSERT(m_parsedCalls <= initNumOfCalls);
        Q_ASSERT(m_parsedCalls <= m_allCalls.size());
        m_allCalls.resize(m_parsedCalls);
        Q_ASSERT(m_parsedCalls <= currentFrame->numChildrenToLoad());
    }
    m_allCalls.squeeze();
    m_topLevelItems.squeeze();

    return bEndFrameReached;
}
예제 #5
0
QVector<ApiTraceCall*>
TraceLoader::fetchFrameContents(ApiTraceFrame *currentFrame)
{
    Q_ASSERT(currentFrame);

    if (currentFrame->isLoaded()) {
        return currentFrame->calls();
    }

    if (m_parser.supportsOffsets()) {
        unsigned frameIdx = currentFrame->number;
        int numOfCalls = numberOfCallsInFrame(frameIdx);

        if (numOfCalls) {
            quint64 binaryDataSize = 0;
            QStack<ApiTraceCall*> groups;
            QVector<ApiTraceCall*> topLevelItems;
            QVector<ApiTraceCall*> allCalls(numOfCalls);
            const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx];

            m_parser.setBookmark(frameBookmark.start);

            trace::Call *call;
            int parsedCalls = 0;
            while ((call = m_parser.parse_call())) {
                ApiTraceCall *apiCall =
                    apiCallFromTraceCall(call, m_helpHash,
                                         currentFrame, groups.isEmpty() ? 0 : groups.top(), this);
                Q_ASSERT(apiCall);
                Q_ASSERT(parsedCalls < allCalls.size());
                allCalls[parsedCalls++] = apiCall;
                if (groups.count() == 0) {
                    topLevelItems.append(apiCall);
                } else {
                    groups.top()->addChild(apiCall);
                }
                if (call->flags & trace::CALL_FLAG_MARKER_PUSH) {
                    groups.push(apiCall);
                } else if (call->flags & trace::CALL_FLAG_MARKER_POP) {
                    if (groups.count()) {
                        groups.top()->finishedAddingChildren();
                        groups.pop();
                    }
                }
                if (apiCall->hasBinaryData()) {
                    QByteArray data =
                        apiCall->arguments()[
                            apiCall->binaryDataIndex()].toByteArray();
                    binaryDataSize += data.size();
                }

                delete call;

                if (apiCall->flags() & trace::CALL_FLAG_END_FRAME) {
                    break;
                }

            }
            // There can be fewer parsed calls when call in different
            // threads cross the frame boundary
            Q_ASSERT(parsedCalls <= numOfCalls);
            Q_ASSERT(parsedCalls <= allCalls.size());
            allCalls.resize(parsedCalls);
            allCalls.squeeze();

            Q_ASSERT(parsedCalls <= currentFrame->numChildrenToLoad());
            if (topLevelItems.count() == allCalls.count()) {
                emit frameContentsLoaded(currentFrame, allCalls,
                                         allCalls, binaryDataSize);
            } else {
                emit frameContentsLoaded(currentFrame, topLevelItems,
                                         allCalls, binaryDataSize);
            }
            return allCalls;
        }
    }
    return QVector<ApiTraceCall*>();
}
예제 #6
0
void TraceLoader::parseTrace()
{
    QList<ApiTraceFrame*> frames;
    ApiTraceFrame *currentFrame = 0;
    int frameCount = 0;
    QStack<ApiTraceCall*> groups;
    QVector<ApiTraceCall*> topLevelItems;
    QVector<ApiTraceCall*> allCalls;
    quint64 binaryDataSize = 0;

    int lastPercentReport = 0;

    trace::Call *call = m_parser.parse_call();
    while (call) {
        //std::cout << *call;
        if (!currentFrame) {
            currentFrame = new ApiTraceFrame();
            currentFrame->number = frameCount;
            ++frameCount;
        }
        ApiTraceCall *apiCall =
            apiCallFromTraceCall(call, m_helpHash, currentFrame, groups.isEmpty() ? 0 : groups.top(), this);
        allCalls.append(apiCall);
        if (groups.count() == 0) {
            topLevelItems.append(apiCall);
        }
        if (call->flags & trace::CALL_FLAG_MARKER_PUSH) {
            groups.push(apiCall);
        } else if (call->flags & trace::CALL_FLAG_MARKER_POP) {
            groups.top()->finishedAddingChildren();
            groups.pop();
        }
        if (!groups.isEmpty()) {
            groups.top()->addChild(apiCall);
        }
        if (apiCall->hasBinaryData()) {
            QByteArray data =
                apiCall->arguments()[apiCall->binaryDataIndex()].toByteArray();
            binaryDataSize += data.size();
        }
        if (call->flags & trace::CALL_FLAG_END_FRAME) {
            allCalls.squeeze();
            topLevelItems.squeeze();
            if (topLevelItems.count() == allCalls.count()) {
                currentFrame->setCalls(allCalls, allCalls, binaryDataSize);
            } else {
                currentFrame->setCalls(topLevelItems, allCalls, binaryDataSize);
            }
            allCalls.clear();
            groups.clear();
            topLevelItems.clear();
            frames.append(currentFrame);
            currentFrame = 0;
            binaryDataSize = 0;
            if (frames.count() >= FRAMES_TO_CACHE) {
                emit framesLoaded(frames);
                frames.clear();
            }
            if (m_parser.percentRead() - lastPercentReport >= 5) {
                emit parsed(m_parser.percentRead());
                lastPercentReport = m_parser.percentRead();
            }
        }
        delete call;
        call = m_parser.parse_call();
    }

    //last frames won't have markers
    //  it's just a bunch of Delete calls for every object
    //  after the last SwapBuffers
    if (currentFrame) {
        allCalls.squeeze();
        if (topLevelItems.count() == allCalls.count()) {
            currentFrame->setCalls(allCalls, allCalls, binaryDataSize);
        } else {
            currentFrame->setCalls(topLevelItems, allCalls, binaryDataSize);
        }
        frames.append(currentFrame);
        currentFrame = 0;
    }
    if (frames.count()) {
        emit framesLoaded(frames);
    }
}