public VmTraceData build() {
      for (int i = 0; i < mStackReconstructors.size(); i++) {
        int threadId = mStackReconstructors.keyAt(i);
        CallStackReconstructor reconstructor = mStackReconstructors.valueAt(i);
        mTopLevelCalls.put(threadId, reconstructor.getTopLevel());
      }

      return new VmTraceData(this);
    }
    public void addMethodAction(
        int threadId, long methodId, TraceAction methodAction, int threadTime, int globalTime) {
      // create thread info if it doesn't exist
      if (mThreads.get(threadId) == null) {
        mThreads.put(threadId, String.format("Thread id: %1$d", threadId));
      }

      // create method info if it doesn't exist
      if (mMethods.get(methodId) == null) {
        MethodInfo info = new MethodInfo(methodId, "unknown", "unknown", "unknown", "unknown", -1);
        mMethods.put(methodId, info);
      }

      if (DEBUG) {
        MethodInfo methodInfo = mMethods.get(methodId);
        System.out.println(
            methodId
                + ": "
                + methodAction
                + ": thread: "
                + mThreads.get(threadId)
                + ", method: "
                + methodInfo.className
                + "/"
                + methodInfo.methodName
                + ":"
                + methodInfo.signature);
      }

      CallStackReconstructor reconstructor = mStackReconstructors.get(threadId);
      if (reconstructor == null) {
        long topLevelCallId = createUniqueMethodIdForThread(threadId);
        reconstructor = new CallStackReconstructor(topLevelCallId);
        mStackReconstructors.put(threadId, reconstructor);
      }

      reconstructor.addTraceAction(methodId, methodAction, threadTime, globalTime);
    }