docs: function() {
        var SCHEDULING_STATE = tr.model.SCHEDULING_STATE;
  
        // Push the cpu slices to the threads that they run on.
        for (var cpuNumber in this.model_.kernel.cpus) {
          var cpu = this.model_.kernel.cpus[cpuNumber];
  
          for (var i = 0; i < cpu.slices.length; i++) {
            var cpuSlice = cpu.slices[i];
  
            var thread = this.threadsByLinuxPid[cpuSlice.args.tid];
            if (!thread)
              continue;
  
            cpuSlice.threadThatWasRunning = thread;
  
            if (!thread.tempCpuSlices)
              thread.tempCpuSlices = [];
            thread.tempCpuSlices.push(cpuSlice);
          }
        }
  
        for (var i in this.wakeups_) {
          var wakeup = this.wakeups_[i];
          var thread = this.threadsByLinuxPid[wakeup.tid];
          if (!thread)
            continue;
          thread.tempWakeups = thread.tempWakeups || [];
          thread.tempWakeups.push(wakeup);
        }
        for (var i in this.blocked_reasons_) {
          var reason = this.blocked_reasons_[i];
          var thread = this.threadsByLinuxPid[reason.tid];
          if (!thread)
            continue;
          thread.tempBlockedReasons = thread.tempBlockedReasons || [];
          thread.tempBlockedReasons.push(reason);
        }
  
        // Create slices for when the thread is not running.
        this.model_.getAllThreads().forEach(function(thread) {
          if (thread.tempCpuSlices === undefined)
            return;
          var origSlices = thread.tempCpuSlices;
          delete thread.tempCpuSlices;
  
          origSlices.sort(function(x, y) {
            return x.start - y.start;
          });
  
          var wakeups = thread.tempWakeups || [];
          delete thread.tempWakeups;
          wakeups.sort(function(x, y) {
            return x.ts - y.ts;
          });
  
          var reasons = thread.tempBlockedReasons || [];
          delete thread.tempBlockedReasons;
          reasons.sort(function(x, y) {
            return x.ts - y.ts;
          });
  
          // Walk the slice list and put slices between each original slice to
          // show when the thread isn't running.
          var slices = [];
  
          if (origSlices.length) {
            var slice = origSlices[0];
  
            if (wakeups.length && wakeups[0].ts < slice.start) {
              var wakeup = wakeups.shift();
              var wakeupDuration = slice.start - wakeup.ts;
              var args = {'wakeup from tid': wakeup.fromTid};
              slices.push(new tr.model.ThreadTimeSlice(
                  thread, SCHEDULING_STATE.RUNNABLE, '',
                  wakeup.ts, args, wakeupDuration));
            }
  
            var runningSlice = new tr.model.ThreadTimeSlice(
                thread, SCHEDULING_STATE.RUNNING, '',
                slice.start, {}, slice.duration);
            runningSlice.cpuOnWhichThreadWasRunning = slice.cpu;
            slices.push(runningSlice);
          }
  
          var wakeup = undefined;
          for (var i = 1; i < origSlices.length; i++) {
            var prevSlice = origSlices[i - 1];
            var nextSlice = origSlices[i];
            var midDuration = nextSlice.start - prevSlice.end;
            while (wakeups.length && wakeups[0].ts < nextSlice.start) {
              var w = wakeups.shift();
              if (wakeup === undefined && w.ts > prevSlice.end) {
                wakeup = w;
              }
            }
            var blocked_reason = undefined;
            while (reasons.length && reasons[0].ts < prevSlice.end) {
              var r = reasons.shift();
            }
            if (wakeup !== undefined &&
                reasons.length &&
                reasons[0].ts < wakeup.ts) {
              blocked_reason = reasons.shift();
            }
  
            // Push a sleep slice onto the slices list, interrupting it with a
            // wakeup if appropriate.
            var pushSleep = function(state) {
              if (wakeup !== undefined) {
                midDuration = wakeup.ts - prevSlice.end;
              }
  
              if (blocked_reason !== undefined) {
                var args = {
                  'kernel callsite when blocked:' : blocked_reason.caller
                };
                if (blocked_reason.iowait) {
                  switch (state) {
                    case SCHEDULING_STATE.UNINTR_SLEEP:
                      state = SCHEDULING_STATE.UNINTR_SLEEP_IO;
                      break;
                    case SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL:
                      state = SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL_IO;
                      break;
                    case SCHEDULING_STATE.UNINTR_SLEEP_WAKING:
                      state = SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL_IO;
                      break;
                    default:
                  }
                }
                slices.push(new tr.model.ThreadTimeSlice(
                    thread,
                    state, '', prevSlice.end, args, midDuration));
              } else {
                slices.push(new tr.model.ThreadTimeSlice(
                    thread,
                    state, '', prevSlice.end, {}, midDuration));
              }
              if (wakeup !== undefined) {
                var wakeupDuration = nextSlice.start - wakeup.ts;
                var args = {'wakeup from tid': wakeup.fromTid};
                slices.push(new tr.model.ThreadTimeSlice(
                    thread, SCHEDULING_STATE.RUNNABLE, '',
                    wakeup.ts, args, wakeupDuration));
                wakeup = undefined;
              }
            };
  
            if (prevSlice.args.stateWhenDescheduled == 'S') {
              pushSleep(SCHEDULING_STATE.SLEEPING);
            } else if (prevSlice.args.stateWhenDescheduled == 'R' ||
                       prevSlice.args.stateWhenDescheduled == 'R+') {
              slices.push(new tr.model.ThreadTimeSlice(
                  thread, SCHEDULING_STATE.RUNNABLE, '',
                  prevSlice.end, {}, midDuration));
            } else if (prevSlice.args.stateWhenDescheduled == 'D') {
              pushSleep(SCHEDULING_STATE.UNINTR_SLEEP);
            } else if (prevSlice.args.stateWhenDescheduled == 'T') {
              slices.push(new tr.model.ThreadTimeSlice(
                  thread, SCHEDULING_STATE.STOPPED, '',
                  prevSlice.end, {}, midDuration));
            } else if (prevSlice.args.stateWhenDescheduled == 't') {
              slices.push(new tr.model.ThreadTimeSlice(
                  thread, SCHEDULING_STATE.DEBUG, '',
                  prevSlice.end, {}, midDuration));
            } else if (prevSlice.args.stateWhenDescheduled == 'Z') {
              slices.push(new tr.model.ThreadTimeSlice(
                  thread, SCHEDULING_STATE.ZOMBIE, '', ioWaitId,
                  prevSlice.end, {}, midDuration));
            } else if (prevSlice.args.stateWhenDescheduled == 'X') {
              slices.push(new tr.model.ThreadTimeSlice(
                  thread, SCHEDULING_STATE.EXIT_DEAD, '',
                  prevSlice.end, {}, midDuration));
            } else if (prevSlice.args.stateWhenDescheduled == 'x') {
              slices.push(new tr.model.ThreadTimeSlice(
                  thread, SCHEDULING_STATE.TASK_DEAD, '',
                  prevSlice.end, {}, midDuration));
            } else if (prevSlice.args.stateWhenDescheduled == 'K') {
              slices.push(new tr.model.ThreadTimeSlice(
                  thread, SCHEDULING_STATE.WAKE_KILL, '',
                  prevSlice.end, {}, midDuration));
            } else if (prevSlice.args.stateWhenDescheduled == 'W') {
              slices.push(new tr.model.ThreadTimeSlice(
                  thread, SCHEDULING_STATE.WAKING, '',
                  prevSlice.end, {}, midDuration));
            } else if (prevSlice.args.stateWhenDescheduled == 'D|K') {
              pushSleep(SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL);
            } else if (prevSlice.args.stateWhenDescheduled == 'D|W') {
              pushSleep(SCHEDULING_STATE.UNINTR_SLEEP_WAKING);
            } else {
              slices.push(new tr.model.ThreadTimeSlice(
                  thread, SCHEDULING_STATE.UNKNOWN, '',
                  prevSlice.end, {}, midDuration));
              this.model_.importWarning({
                type: 'parse_error',
                message: 'Unrecognized sleep state: ' +
                    prevSlice.args.stateWhenDescheduled
              });
            }
  
            var runningSlice = new tr.model.ThreadTimeSlice(
                thread, SCHEDULING_STATE.RUNNING, '',
                nextSlice.start, {}, nextSlice.duration);
            runningSlice.cpuOnWhichThreadWasRunning = prevSlice.cpu;
            slices.push(runningSlice);
          }
          thread.timeSlices = slices;
        }, this);
      }