Merge "Do not do left shift on negative value."
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index eabbce9..322de1f 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -52,6 +52,12 @@
   } else {
     perfetto_watchdog = "0"
   }
+  if (enable_perfetto_tools) {
+    perfetto_local_symbolizer = "PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX()"
+  } else {
+    perfetto_local_symbolizer = "0"
+  }
+
   response_file_contents = [
     "--flags",  # Keep this marker first.
     "PERFETTO_ANDROID_BUILD=$perfetto_build_with_android",
@@ -67,6 +73,7 @@
     "PERFETTO_TP_LINENOISE=$enable_perfetto_trace_processor_linenoise",
     "PERFETTO_TP_JSON=$enable_perfetto_trace_processor_json",
     "PERFETTO_TP_PERCENTILE=$enable_perfetto_trace_processor_percentile",
+    "PERFETTO_LOCAL_SYMBOLIZER=$perfetto_local_symbolizer",
   ]
 
   rel_out_path = rebase_path(gen_header_path, "$root_build_dir")
diff --git a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
index f0594ab..5fc2e58 100644
--- a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
@@ -18,6 +18,7 @@
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_LINENOISE() (0)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (0)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_PERCENTILE() (0)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LOCAL_SYMBOLIZER() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX())
 
 // clang-format on
 #endif  // GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
diff --git a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
index 92250a0..7834fa8 100644
--- a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
@@ -18,6 +18,7 @@
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_LINENOISE() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (1)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_PERCENTILE() (1)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LOCAL_SYMBOLIZER() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX())
 
 // clang-format on
 #endif  // GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
diff --git a/src/trace_processor/export_json.cc b/src/trace_processor/export_json.cc
index 2ff1f6e..d54165d 100644
--- a/src/trace_processor/export_json.cc
+++ b/src/trace_processor/export_json.cc
@@ -323,8 +323,6 @@
             virtual_track_slices.thread_timestamp_ns()[*vtrack_slice_row];
         thread_duration_ns =
             virtual_track_slices.thread_duration_ns()[*vtrack_slice_row];
-        thread_ts_ns =
-            virtual_track_slices.thread_timestamp_ns()[*vtrack_slice_row];
         thread_instruction_count =
             virtual_track_slices.thread_instruction_counts()[*vtrack_slice_row];
         thread_instruction_delta =
diff --git a/src/trace_processor/heap_profile_tracker.cc b/src/trace_processor/heap_profile_tracker.cc
index 6816c33..bdc6254 100644
--- a/src/trace_processor/heap_profile_tracker.cc
+++ b/src/trace_processor/heap_profile_tracker.cc
@@ -29,6 +29,14 @@
 
 HeapProfileTracker::~HeapProfileTracker() = default;
 
+void HeapProfileTracker::SetProfilePacketIndex(uint64_t index) {
+  if (last_profile_packet_index_ != 0 &&
+      last_profile_packet_index_ + 1 != index) {
+    context_->storage->IncrementStats(stats::heapprofd_missing_packet);
+  }
+  last_profile_packet_index_ = index;
+}
+
 void HeapProfileTracker::AddAllocation(
     const SourceAllocation& alloc,
     const StackProfileTracker::InternLookup* intern_lookup) {
diff --git a/src/trace_processor/heap_profile_tracker.h b/src/trace_processor/heap_profile_tracker.h
index 4890a57..0662f8c 100644
--- a/src/trace_processor/heap_profile_tracker.h
+++ b/src/trace_processor/heap_profile_tracker.h
@@ -45,6 +45,8 @@
     uint64_t free_count = 0;
   };
 
+  void SetProfilePacketIndex(uint64_t id);
+
   explicit HeapProfileTracker(TraceProcessorContext* context);
 
   void StoreAllocation(SourceAllocation);
@@ -75,6 +77,7 @@
       prev_free_;
 
   TraceProcessorContext* const context_;
+  uint64_t last_profile_packet_index_ = 0;
   const StringId empty_;
 };
 
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
index db964bf..74d4e5e 100644
--- a/src/trace_processor/proto_trace_parser.cc
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -1477,6 +1477,7 @@
     ProtoIncrementalState::PacketSequenceState* sequence_state,
     ConstBytes blob) {
   protos::pbzero::ProfilePacket::Decoder packet(blob.data, blob.size);
+  context_->heap_profile_tracker->SetProfilePacketIndex(packet.index());
 
   for (auto it = packet.strings(); it; ++it) {
     protos::pbzero::InternedString::Decoder entry(it->data(), it->size());
diff --git a/src/trace_processor/stats.h b/src/trace_processor/stats.h
index 1282a7c..0287926 100644
--- a/src/trace_processor/stats.h
+++ b/src/trace_processor/stats.h
@@ -112,6 +112,7 @@
   F(heap_graph_missing_packet,                kIndexed, kDataLoss, kTrace),    \
   F(heapprofd_buffer_corrupted,               kIndexed, kError,    kTrace),    \
   F(heapprofd_buffer_overran,                 kIndexed, kDataLoss, kTrace),    \
+  F(heapprofd_missing_packet,                 kSingle,  kError,    kTrace),    \
   F(heapprofd_rejected_concurrent,            kIndexed, kError,    kTrace),    \
   F(metatrace_overruns,                       kSingle,  kError,    kTrace),    \
   F(packages_list_has_parse_errors,           kSingle,  kError,    kTrace),    \
diff --git a/src/trace_processor/trace_processor_shell.cc b/src/trace_processor/trace_processor_shell.cc
index d8eb471..f37b5ab 100644
--- a/src/trace_processor/trace_processor_shell.cc
+++ b/src/trace_processor/trace_processor_shell.cc
@@ -744,6 +744,7 @@
 
   if (argc == 2) {
     command_line_options.trace_file_path = argv[1];
+    command_line_options.launch_shell = true;
   } else if (argc == 4) {
     if (strcmp(argv[1], "-q") != 0) {
       PrintUsage(argv);
diff --git a/tools/trace_to_text/BUILD.gn b/tools/trace_to_text/BUILD.gn
index 44126e7..563ec2e 100644
--- a/tools/trace_to_text/BUILD.gn
+++ b/tools/trace_to_text/BUILD.gn
@@ -123,6 +123,7 @@
 # executable) and by the "lite" version (the WASM module for the UI).
 source_set("common") {
   deps = [
+    ":local_symbolizer",
     ":pprofbuilder",
     ":symbolizer",
     ":utils",
@@ -151,12 +152,6 @@
     "trace_to_systrace.h",
     "trace_to_text.h",
   ]
-  defines = []
-  if (is_linux || is_android) {
-    deps += [ ":local_symbolizer" ]
-  } else {
-    defines += [ "PERFETTO_NOLOCALSYMBOLIZE" ]
-  }
   if (enable_perfetto_version_gen) {
     deps += [ "//gn/standalone:gen_git_revision" ]
   }
diff --git a/tools/trace_to_text/local_symbolizer.cc b/tools/trace_to_text/local_symbolizer.cc
index b52cd43..3daa0be 100644
--- a/tools/trace_to_text/local_symbolizer.cc
+++ b/tools/trace_to_text/local_symbolizer.cc
@@ -15,6 +15,11 @@
  * limitations under the License.
  */
 
+#include "perfetto/base/build_config.h"
+
+// This translation unit is built only on Linux. See //gn/BUILD.gn.
+#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
+
 #include "tools/trace_to_text/local_symbolizer.h"
 
 #include "perfetto/ext/base/string_splitter.h"
@@ -399,3 +404,5 @@
 
 }  // namespace trace_to_text
 }  // namespace perfetto
+
+#endif  // PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
diff --git a/tools/trace_to_text/pprof_builder.cc b/tools/trace_to_text/pprof_builder.cc
index 6f699ac..4c61eb3 100644
--- a/tools/trace_to_text/pprof_builder.cc
+++ b/tools/trace_to_text/pprof_builder.cc
@@ -232,7 +232,9 @@
       std::string query = "SELECT hpa.callsite_id ";
       query += ", " + std::string(v.aggregator) +
                " FROM heap_profile_allocation hpa ";
-      query += "WHERE hpa.upid = " + std::to_string(upid) + " ";
+      // TODO(fmayer): Figure out where negative callsite_id comes from.
+      query += "WHERE hpa.callsite_id >= 0 ";
+      query += "AND hpa.upid = " + std::to_string(upid) + " ";
       query += "AND hpa.ts <= " + std::to_string(ts) + " ";
       if (v.filter)
         query += "AND " + std::string(v.filter) + " ";
@@ -451,7 +453,10 @@
   }
 
   const std::vector<int64_t>& FramesForCallstack(int64_t callstack_id) {
-    return callsite_to_frames_[static_cast<size_t>(callstack_id)];
+    size_t callsite_idx = static_cast<size_t>(callstack_id);
+    PERFETTO_CHECK(callstack_id >= 0 &&
+                   callsite_idx < callsite_to_frames_.size());
+    return callsite_to_frames_[callsite_idx];
   }
 
   const std::vector<Line>& LineForSymbolSetId(int64_t symbol_set_id) {
@@ -540,8 +545,8 @@
   }
 
   int64_t max_symbol_id = max_symbol_id_it.Get(0).long_value;
-  auto callsite_to_frames = GetCallsiteToFrames(tp);
-  auto symbol_set_id_to_lines = GetSymbolSetIdToLines(tp);
+  const auto callsite_to_frames = GetCallsiteToFrames(tp);
+  const auto symbol_set_id_to_lines = GetSymbolSetIdToLines(tp);
 
   bool any_fail = false;
   Iterator it = tp->ExecuteQuery(kQueryProfiles);
diff --git a/tools/trace_to_text/symbolize_profile.cc b/tools/trace_to_text/symbolize_profile.cc
index aa7c2ef..cb8f1e2 100644
--- a/tools/trace_to_text/symbolize_profile.cc
+++ b/tools/trace_to_text/symbolize_profile.cc
@@ -21,8 +21,8 @@
 #include "perfetto/base/logging.h"
 #include "perfetto/profiling/symbolizer.h"
 
-#ifndef PERFETTO_NOLOCALSYMBOLIZE
-#include "tools/trace_to_text/local_symbolizer.h"  // nogncheck
+#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
+#include "tools/trace_to_text/local_symbolizer.h"
 #endif
 
 #include "protos/perfetto/trace/trace.pbzero.h"
@@ -54,7 +54,7 @@
   std::unique_ptr<Symbolizer> symbolizer;
   auto binary_path = GetPerfettoBinaryPath();
   if (!binary_path.empty()) {
-#ifndef PERFETTO_NOLOCALSYMBOLIZE
+#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
     symbolizer.reset(new LocalSymbolizer(GetPerfettoBinaryPath()));
 #else
     PERFETTO_FATAL("This build does not support local symbolization.");
diff --git a/tools/trace_to_text/trace_to_profile.cc b/tools/trace_to_text/trace_to_profile.cc
index cc00194..4f5f1ec 100644
--- a/tools/trace_to_text/trace_to_profile.cc
+++ b/tools/trace_to_text/trace_to_profile.cc
@@ -19,8 +19,10 @@
 #include <string>
 #include <vector>
 
-#ifndef PERFETTO_NOLOCALSYMBOLIZE
-#include "tools/trace_to_text/local_symbolizer.h"  // nogncheck
+#include "perfetto/base/build_config.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
+#include "tools/trace_to_text/local_symbolizer.h"
 #endif
 #include "tools/trace_to_text/utils.h"
 
@@ -54,7 +56,7 @@
   std::unique_ptr<Symbolizer> symbolizer;
   auto binary_path = GetPerfettoBinaryPath();
   if (!binary_path.empty()) {
-#ifndef PERFETTO_NOLOCALSYMBOLIZE
+#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
     symbolizer.reset(new LocalSymbolizer(GetPerfettoBinaryPath()));
 #else
     PERFETTO_ELOG(
diff --git a/ui/src/controller/adb.ts b/ui/src/controller/adb.ts
index a304416..a20776c 100644
--- a/ui/src/controller/adb.ts
+++ b/ui/src/controller/adb.ts
@@ -125,7 +125,7 @@
     if (!this.dev) return;
 
     new Map(this.streams).forEach((stream, _id) => stream.setClosed());
-    console.assert(this.streams.size == 0);
+    console.assert(this.streams.size === 0);
     this.dev = undefined;
   }
 
diff --git a/ui/src/controller/search_controller.ts b/ui/src/controller/search_controller.ts
index 8f08ec3..0edaa53 100644
--- a/ui/src/controller/search_controller.ts
+++ b/ui/src/controller/search_controller.ts
@@ -184,18 +184,14 @@
     // TODO(hjd): we should avoid recomputing this every time. This will be
     // easier once the track table has entries for all the tracks.
     const cpuToTrackId = new Map();
-    const utidToTrackId = new Map();
     const engineTrackIdToTrackId = new Map();
     for (const track of Object.values(this.app.state.tracks)) {
-      if (track.kind === 'ChromeSliceTrack') {
-        utidToTrackId.set((track.config as {utid: number}).utid, track.id);
-        continue;
-      }
       if (track.kind === 'CpuSliceTrack') {
         cpuToTrackId.set((track.config as {cpu: number}).cpu, track.id);
         continue;
       }
-      if (track.kind === 'AsyncSliceTrack') {
+      if (track.kind === 'ChromeSliceTrack' ||
+          track.kind === 'AsyncSliceTrack') {
         engineTrackIdToTrackId.set(
             (track.config as {trackId: number}).trackId, track.id);
         continue;
@@ -211,7 +207,7 @@
     select
       row_id as slice_id,
       ts,
-      'cpu' as ref_type,
+      'cpu' as source,
       cpu as ref,
       utid
     from sched where utid in (${utids.join(',')})
@@ -219,12 +215,12 @@
     select
       slice_id,
       ts,
-      ref_type,
-      ref,
+      'track' as source,
+      track_id as ref,
       0 as utid
-      from internal_slice
-      where (ref_type = 'utid' or ref_type == 'track')
-      and name like '%${search}%'
+      from slice
+      inner join track on slice.track_id = track.id
+      and slice.name like '%${search}%'
     order by ts`);
 
     const numRows = +rawResult.numRecords;
@@ -240,14 +236,12 @@
 
     const columns = rawResult.columns;
     for (let row = 0; row < numRows; row++) {
-      const refType = columns[2].stringValues![row];
+      const source = columns[2].stringValues![row];
       const ref = +columns[3].longValues![row];
       let trackId = undefined;
-      if (refType === 'cpu') {
+      if (source === 'cpu') {
         trackId = cpuToTrackId.get(ref);
-      } else if (refType === 'utid') {
-        trackId = utidToTrackId.get(ref);
-      } else if (refType === 'track') {
+      } else if (source === 'track') {
         trackId = engineTrackIdToTrackId.get(ref);
       }
 
@@ -257,7 +251,7 @@
       }
 
       searchResults.trackIds.push(trackId);
-      searchResults.refTypes.push(refType);
+      searchResults.refTypes.push(source);
       searchResults.sliceIds[row] = +columns[0].longValues![row];
       searchResults.tsStarts[row] = +columns[1].longValues![row];
       searchResults.utids[row] = +columns[4].longValues![row];
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index cfa03f2..b7ee307 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -58,6 +58,11 @@
 declare var FileReaderSync:
     {prototype: FileReaderSync; new (): FileReaderSync;};
 
+interface ThreadSliceTrack {
+  maxDepth: number;
+  trackId: number;
+}
+
 // TraceController handles handshakes with the frontend for everything that
 // concerns a single trace. It owns the WASM trace processor engine, handles
 // tracks data and SQL queries. There is one TraceController instance for each
@@ -310,13 +315,10 @@
 
     const upidToProcessTracks = new Map();
     const rawProcessTracks = await engine.query(`
-      select id, upid, name, maxDepth
+      select id, upid, name, max(depth) as maxDepth
       from process_track
-      join (
-        select ref as id, max(depth) as maxDepth
-        from slice
-        where ref_type = 'track' group by ref
-      ) using(id)
+      inner join slice on slice.track_id = process_track.id
+      group by track_id
     `);
     for (let i = 0; i < rawProcessTracks.numRecords; i++) {
       const trackId = rawProcessTracks.columns[0].longValues![i];
@@ -424,14 +426,19 @@
 
     // Local experiments shows getting maxDepth separately is ~2x faster than
     // joining with threads and processes.
-    const maxDepthQuery =
-        await engine.query('select utid, max(depth) from slices group by utid');
+    const maxDepthQuery = await engine.query(`
+          select thread_track.utid, thread_track.id, max(depth) as maxDepth
+          from slice
+          inner join thread_track on slice.track_id = thread_track.id
+          group by thread_track.id
+        `);
 
-    const utidToMaxDepth = new Map<number, number>();
+    const utidToThreadTrack = new Map<number, ThreadSliceTrack>();
     for (let i = 0; i < maxDepthQuery.numRecords; i++) {
       const utid = maxDepthQuery.columns[0].longValues![i] as number;
-      const maxDepth = maxDepthQuery.columns[1].longValues![i] as number;
-      utidToMaxDepth.set(utid, maxDepth);
+      const trackId = maxDepthQuery.columns[1].longValues![i] as number;
+      const maxDepth = maxDepthQuery.columns[2].longValues![i] as number;
+      utidToThreadTrack.set(utid, {maxDepth, trackId});
     }
 
     // Return all threads
@@ -481,8 +488,9 @@
           await engine.query(`select count(1) from sched where utid = ${utid}`);
       const threadHasSched = threadSched.columns[0].longValues![0] > 0;
 
-      const maxDepth = utid === null ? undefined : utidToMaxDepth.get(utid);
-      if (maxDepth === undefined &&
+      const threadTrack =
+          utid === null ? undefined : utidToThreadTrack.get(utid);
+      if (threadTrack === undefined &&
           (upid === null || counterUpids[upid] === undefined) &&
           counterUtids[utid] === undefined && !threadHasSched) {
         continue;
@@ -580,13 +588,18 @@
         });
       }
 
-      if (maxDepth !== undefined) {
+      if (threadTrack !== undefined) {
         tracksToAdd.push({
           engineId: this.engineId,
           kind: SLICE_TRACK_KIND,
           name: `${threadName} [${tid}]`,
           trackGroup: pUuid,
-          config: {upid, utid, maxDepth},
+          config: {
+            upid,
+            utid,
+            maxDepth: threadTrack.maxDepth,
+            trackId: threadTrack.trackId
+          },
         });
       }
     }
@@ -664,13 +677,21 @@
     // Slices overview.
     const traceStartNs = toNs(traceTime.start);
     const stepSecNs = toNs(stepSec);
-    const sliceSummaryQuery = await engine.query(
-        `select bucket, upid, sum(utid_sum) / cast(${stepSecNs} as float) ` +
-        `as upid_sum from thread inner join ` +
-        `(select cast((ts - ${traceStartNs})/${stepSecNs} as int) as bucket, ` +
-        `sum(dur) as utid_sum, ref as utid from internal_slice ` +
-        `where ref_type = 'utid' group by bucket, ref) ` +
-        `using(utid) group by bucket, upid`);
+    const sliceSummaryQuery = await engine.query(`select
+           bucket,
+           upid,
+           sum(utid_sum) / cast(${stepSecNs} as float) as upid_sum
+         from thread
+         inner join (
+           select
+             cast((ts - ${traceStartNs})/${stepSecNs} as int) as bucket
+             sum(dur) as utid_sum,
+             utid
+           from slice
+           inner join thread_track on slice.track_id = thread_track.id
+           group by bucket, utid
+         ) using(utid)
+         group by bucket, upid`);
 
     const slicesData: {[key: string]: QuantizedLoad[]} = {};
     for (let i = 0; i < sliceSummaryQuery.numRecords; i++) {
diff --git a/ui/src/frontend/keyboard_event_handler.ts b/ui/src/frontend/keyboard_event_handler.ts
index 3ad39f4..a068687 100644
--- a/ui/src/frontend/keyboard_event_handler.ts
+++ b/ui/src/frontend/keyboard_event_handler.ts
@@ -21,7 +21,8 @@
 
 // Handles all key events than are not handled by the
 // pan and zoom handler.
-export function handleKey(key: string, down: boolean, isShiftDown: boolean) {
+export function handleKey(e: KeyboardEvent, down: boolean) {
+  const key = e.key;
   if (down && 'm' === key) {
     selectSliceSpan();
   }
@@ -43,7 +44,8 @@
     toggleHelp();
   }
   if (down && 'Enter' === key) {
-    executeSearch(isShiftDown);
+    e.preventDefault();
+    executeSearch(e.shiftKey);
   }
 }
 
diff --git a/ui/src/frontend/pan_and_zoom_handler.ts b/ui/src/frontend/pan_and_zoom_handler.ts
index a6353e0..34cda3f 100644
--- a/ui/src/frontend/pan_and_zoom_handler.ts
+++ b/ui/src/frontend/pan_and_zoom_handler.ts
@@ -217,7 +217,7 @@
     }
 
     // Handle key events that are not pan or zoom.
-    handleKey(e.key, true, this.shiftDown);
+    handleKey(e, true);
   }
 
   private onKeyUp(e: KeyboardEvent) {
@@ -230,7 +230,7 @@
     }
 
     // Handle key events that are not pan or zoom.
-    handleKey(e.key, false, this.shiftDown);
+    handleKey(e, false);
   }
 
   private updateShift(down: boolean) {
diff --git a/ui/src/tracks/async_slices/controller.ts b/ui/src/tracks/async_slices/controller.ts
index e56999b..709223e 100644
--- a/ui/src/tracks/async_slices/controller.ts
+++ b/ui/src/tracks/async_slices/controller.ts
@@ -39,8 +39,7 @@
       await this.query(
           `create view ${this.tableName('small')} as ` +
           `select ts,dur,depth,name,slice_id from slice ` +
-          `where ref_type = 'track' ` +
-          `and ref = ${this.config.trackId} ` +
+          `and track_id = ${this.config.trackId} ` +
           `and dur < ${minNs} ` +
           `order by ts;`);
 
@@ -65,16 +64,14 @@
     await this.query(
         `create view ${this.tableName('small')} as ` +
         `select ts,dur,depth,name, slice_id from slice ` +
-        `where ref_type = 'track' ` +
-        `and ref = ${this.config.trackId} ` +
+        `and track_id = ${this.config.trackId} ` +
         `and dur < ${minNs} ` +
         `order by ts `);
 
     await this.query(
         `create view ${this.tableName('big')} as ` +
         `select ts,dur,depth,name, slice_id from slice ` +
-        `where ref_type = 'track' ` +
-        `and ref = ${this.config.trackId} ` +
+        `and track_id = ${this.config.trackId} ` +
         `and ts >= ${startNs} - dur ` +
         `and ts <= ${endNs} ` +
         `and dur >= ${minNs} ` +
diff --git a/ui/src/tracks/chrome_slices/common.ts b/ui/src/tracks/chrome_slices/common.ts
index 68653da..faa40c3 100644
--- a/ui/src/tracks/chrome_slices/common.ts
+++ b/ui/src/tracks/chrome_slices/common.ts
@@ -20,6 +20,7 @@
   maxDepth: number;
   upid: number;
   utid: number;
+  trackId: number;
 }
 
 export interface Data extends TrackData {
diff --git a/ui/src/tracks/chrome_slices/controller.ts b/ui/src/tracks/chrome_slices/controller.ts
index cbe6486..09abcd9 100644
--- a/ui/src/tracks/chrome_slices/controller.ts
+++ b/ui/src/tracks/chrome_slices/controller.ts
@@ -39,7 +39,7 @@
       await this.query(
           `create view ${this.tableName('small')} as ` +
           `select ts,dur,depth,name,slice_id from slice ` +
-          `where utid = ${this.config.utid} ` +
+          `where track_id = ${this.config.trackId} ` +
           `and dur < ${minNs} ` +
           `order by ts;`);
 
@@ -64,14 +64,14 @@
     await this.query(
         `create view ${this.tableName('small')} as ` +
         `select ts,dur,depth,name,slice_id from slice ` +
-        `where utid = ${this.config.utid} ` +
+        `where track_id = ${this.config.trackId} ` +
         `and dur < ${minNs} ` +
         `order by ts `);
 
     await this.query(
         `create view ${this.tableName('big')} as ` +
         `select ts,dur,depth,name,slice_id from slice ` +
-        `where utid = ${this.config.utid} ` +
+        `where track_id = ${this.config.trackId} ` +
         `and ts >= ${startNs} - dur ` +
         `and ts <= ${endNs} ` +
         `and dur >= ${minNs} ` +