Bug 1178892 - Split the profiler into Core & Gecko files and break apart monolithic headers. r=mstange
authorBenoit Girard <b56girard@gmail.com>
Tue, 30 Jun 2015 15:03:45 -0400
changeset 251392 94714c206f188a4587bdcb4d00ec72019c0925ca
parent 251391 65b6fc37a39af74a36ff3553e4802959aa53beae
child 251393 8d0a3fbad02749213a9f3522c35417def8d52e36
push id28996
push userphilringnalda@gmail.com
push dateSat, 04 Jul 2015 18:07:47 +0000
treeherdermozilla-central@5fe7988b5632 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1178892
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1178892 - Split the profiler into Core & Gecko files and break apart monolithic headers. r=mstange
CLOBBER
tools/profiler/AutoObjectMapper.cpp
tools/profiler/AutoObjectMapper.h
tools/profiler/EHABIStackWalk.cpp
tools/profiler/EHABIStackWalk.h
tools/profiler/GeckoProfiler.h
tools/profiler/GeckoProfilerFunc.h
tools/profiler/GeckoProfilerImpl.h
tools/profiler/GeckoTaskTracer.cpp
tools/profiler/GeckoTaskTracer.h
tools/profiler/GeckoTaskTracerImpl.h
tools/profiler/IntelPowerGadget.cpp
tools/profiler/IntelPowerGadget.h
tools/profiler/LulCommon.cpp
tools/profiler/LulCommonExt.h
tools/profiler/LulDwarf.cpp
tools/profiler/LulDwarfExt.h
tools/profiler/LulDwarfInt.h
tools/profiler/LulDwarfSummariser.cpp
tools/profiler/LulDwarfSummariser.h
tools/profiler/LulElf.cpp
tools/profiler/LulElfExt.h
tools/profiler/LulElfInt.h
tools/profiler/LulMain.cpp
tools/profiler/LulMain.h
tools/profiler/LulMainInt.h
tools/profiler/LulPlatformMacros.h
tools/profiler/PlatformMacros.h
tools/profiler/ProfileEntry.cpp
tools/profiler/ProfileEntry.h
tools/profiler/ProfileGatherer.cpp
tools/profiler/ProfileGatherer.h
tools/profiler/ProfileJSONWriter.cpp
tools/profiler/ProfileJSONWriter.h
tools/profiler/Profiler.jsm
tools/profiler/ProfilerBacktrace.cpp
tools/profiler/ProfilerBacktrace.h
tools/profiler/ProfilerIOInterposeObserver.cpp
tools/profiler/ProfilerIOInterposeObserver.h
tools/profiler/ProfilerMarkers.cpp
tools/profiler/ProfilerMarkers.h
tools/profiler/PseudoStack.h
tools/profiler/SaveProfileTask.cpp
tools/profiler/SaveProfileTask.h
tools/profiler/SourceEventTypeMap.h
tools/profiler/SyncProfile.cpp
tools/profiler/SyncProfile.h
tools/profiler/TableTicker.cpp
tools/profiler/TableTicker.h
tools/profiler/ThreadResponsiveness.cpp
tools/profiler/ThreadResponsiveness.h
tools/profiler/TracedTaskCommon.cpp
tools/profiler/TracedTaskCommon.h
tools/profiler/core/EHABIStackWalk.cpp
tools/profiler/core/EHABIStackWalk.h
tools/profiler/core/GeckoSampler.cpp
tools/profiler/core/GeckoSampler.h
tools/profiler/core/IntelPowerGadget.cpp
tools/profiler/core/IntelPowerGadget.h
tools/profiler/core/PlatformMacros.h
tools/profiler/core/ProfileBuffer.cpp
tools/profiler/core/ProfileBuffer.h
tools/profiler/core/ProfileEntry.cpp
tools/profiler/core/ProfileEntry.h
tools/profiler/core/ProfileJSONWriter.cpp
tools/profiler/core/ProfileJSONWriter.h
tools/profiler/core/ProfilerBacktrace.cpp
tools/profiler/core/ProfilerMarkers.cpp
tools/profiler/core/SyncProfile.cpp
tools/profiler/core/SyncProfile.h
tools/profiler/core/ThreadInfo.cpp
tools/profiler/core/ThreadInfo.h
tools/profiler/core/ThreadProfile.cpp
tools/profiler/core/ThreadProfile.h
tools/profiler/core/platform-linux.cc
tools/profiler/core/platform-macos.cc
tools/profiler/core/platform-win32.cc
tools/profiler/core/platform.cpp
tools/profiler/core/platform.h
tools/profiler/core/shared-libraries-linux.cc
tools/profiler/core/shared-libraries-macos.cc
tools/profiler/core/shared-libraries-win32.cc
tools/profiler/core/shim_mac_dump_syms.h
tools/profiler/core/shim_mac_dump_syms.mm
tools/profiler/core/v8-support.h
tools/profiler/gecko/ProfileGatherer.cpp
tools/profiler/gecko/Profiler.jsm
tools/profiler/gecko/ProfilerIOInterposeObserver.cpp
tools/profiler/gecko/ProfilerIOInterposeObserver.h
tools/profiler/gecko/SaveProfileTask.cpp
tools/profiler/gecko/SaveProfileTask.h
tools/profiler/gecko/ThreadResponsiveness.cpp
tools/profiler/gecko/ThreadResponsiveness.h
tools/profiler/gecko/local_debug_info_symbolizer.cc
tools/profiler/gecko/local_debug_info_symbolizer.h
tools/profiler/gecko/nsIProfileSaveEvent.idl
tools/profiler/gecko/nsIProfiler.idl
tools/profiler/gecko/nsProfiler.cpp
tools/profiler/gecko/nsProfiler.h
tools/profiler/gecko/nsProfilerCIID.h
tools/profiler/gecko/nsProfilerFactory.cpp
tools/profiler/gecko/nsProfilerStartParams.cpp
tools/profiler/gecko/nsProfilerStartParams.h
tools/profiler/local_debug_info_symbolizer.cc
tools/profiler/local_debug_info_symbolizer.h
tools/profiler/lul/AutoObjectMapper.cpp
tools/profiler/lul/AutoObjectMapper.h
tools/profiler/lul/LulCommon.cpp
tools/profiler/lul/LulCommonExt.h
tools/profiler/lul/LulDwarf.cpp
tools/profiler/lul/LulDwarfExt.h
tools/profiler/lul/LulDwarfInt.h
tools/profiler/lul/LulDwarfSummariser.cpp
tools/profiler/lul/LulDwarfSummariser.h
tools/profiler/lul/LulElf.cpp
tools/profiler/lul/LulElfExt.h
tools/profiler/lul/LulElfInt.h
tools/profiler/lul/LulMain.cpp
tools/profiler/lul/LulMain.h
tools/profiler/lul/LulMainInt.h
tools/profiler/lul/LulPlatformMacros.h
tools/profiler/lul/platform-linux-lul.cpp
tools/profiler/lul/platform-linux-lul.h
tools/profiler/moz.build
tools/profiler/nsIProfileSaveEvent.idl
tools/profiler/nsIProfiler.idl
tools/profiler/nsProfiler.cpp
tools/profiler/nsProfiler.h
tools/profiler/nsProfilerCIID.h
tools/profiler/nsProfilerFactory.cpp
tools/profiler/nsProfilerStartParams.cpp
tools/profiler/nsProfilerStartParams.h
tools/profiler/platform-linux-lul.cpp
tools/profiler/platform-linux-lul.h
tools/profiler/platform-linux.cc
tools/profiler/platform-macos.cc
tools/profiler/platform-win32.cc
tools/profiler/platform.cpp
tools/profiler/platform.h
tools/profiler/public/GeckoProfiler.h
tools/profiler/public/GeckoProfilerFunc.h
tools/profiler/public/GeckoProfilerImpl.h
tools/profiler/public/ProfileGatherer.h
tools/profiler/public/ProfilerBacktrace.h
tools/profiler/public/ProfilerMarkers.h
tools/profiler/public/PseudoStack.h
tools/profiler/public/shared-libraries.h
tools/profiler/shared-libraries-linux.cc
tools/profiler/shared-libraries-macos.cc
tools/profiler/shared-libraries-win32.cc
tools/profiler/shared-libraries.h
tools/profiler/shim_mac_dump_syms.h
tools/profiler/shim_mac_dump_syms.mm
tools/profiler/tasktracer/GeckoTaskTracer.cpp
tools/profiler/tasktracer/GeckoTaskTracer.h
tools/profiler/tasktracer/GeckoTaskTracerImpl.h
tools/profiler/tasktracer/SourceEventTypeMap.h
tools/profiler/tasktracer/TracedTaskCommon.cpp
tools/profiler/tasktracer/TracedTaskCommon.h
tools/profiler/tests/gtest/ThreadProfileTest.cpp
tools/profiler/tests/gtest/moz.build
tools/profiler/v8-support.h
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1178215 requires clobber for libvpx file moves.
+Bug 1178892 requires clobber for profiler file moves.
rename from tools/profiler/EHABIStackWalk.cpp
rename to tools/profiler/core/EHABIStackWalk.cpp
rename from tools/profiler/EHABIStackWalk.h
rename to tools/profiler/core/EHABIStackWalk.h
rename from tools/profiler/TableTicker.cpp
rename to tools/profiler/core/GeckoSampler.cpp
--- a/tools/profiler/TableTicker.cpp
+++ b/tools/profiler/core/GeckoSampler.cpp
@@ -16,17 +16,17 @@
 #include "prtime.h"
 #include "nsXULAppAPI.h"
 #endif
 #include "ProfileEntry.h"
 #include "SyncProfile.h"
 #include "platform.h"
 #include "shared-libraries.h"
 #include "mozilla/StackWalk.h"
-#include "TableTicker.h"
+#include "GeckoSampler.h"
 
 // JSON
 #include "ProfileJSONWriter.h"
 
 #ifndef SPS_STANDALONE
 // Meta
 #include "nsXPCOM.h"
 #include "nsXPCOMCID.h"
@@ -35,16 +35,18 @@
 #include "nsIXULRuntime.h"
 #include "nsIXULAppInfo.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "PlatformMacros.h"
 #include "nsTArray.h"
+
+#include "mozilla/ProfileGatherer.h"
 #endif
 
 #if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
   #include "AndroidBridge.h"
 #endif
 
 #ifndef SPS_STANDALONE
 // JS
@@ -74,18 +76,18 @@ pid_t gettid();
 #endif
 #ifdef USE_EHABI_STACKWALK
  #include "EHABIStackWalk.h"
 #endif
 
 #ifndef SPS_STANDALONE
 #if defined(SPS_PLAT_amd64_linux) || defined(SPS_PLAT_x86_linux)
 # define USE_LUL_STACKWALK
-# include "LulMain.h"
-# include "platform-linux-lul.h"
+# include "lul/LulMain.h"
+# include "lul/platform-linux-lul.h"
 #endif
 #endif
 
 using std::string;
 using namespace mozilla;
 
 #ifndef MAXPATHLEN
  #ifdef PATH_MAX
@@ -171,17 +173,17 @@ static bool
 hasFeature(const char** aFeatures, uint32_t aFeatureCount, const char* aFeature) {
   for(size_t i = 0; i < aFeatureCount; i++) {
     if (strcmp(aFeatures[i], aFeature) == 0)
       return true;
   }
   return false;
 }
 
-TableTicker::TableTicker(double aInterval, int aEntrySize,
+GeckoSampler::GeckoSampler(double aInterval, int aEntrySize,
                          const char** aFeatures, uint32_t aFeatureCount,
                          const char** aThreadNameFilters, uint32_t aFilterCount)
   : Sampler(aInterval, true, aEntrySize)
   , mPrimaryThreadProfile(nullptr)
   , mBuffer(new ProfileBuffer(aEntrySize))
   , mSaveRequested(false)
 #if defined(XP_WIN)
   , mIntelPowerGadget(nullptr)
@@ -236,17 +238,17 @@ TableTicker::TableTicker(double aInterva
 
 #ifdef MOZ_TASK_TRACER
   if (mTaskTracer) {
     mozilla::tasktracer::StartLogging();
   }
 #endif
 }
 
-TableTicker::~TableTicker()
+GeckoSampler::~GeckoSampler()
 {
   if (IsActive())
     Stop();
 
   SetActiveSampler(nullptr);
 
   // Destroy ThreadProfile for all threads
   {
@@ -268,36 +270,36 @@ TableTicker::~TableTicker()
       }
     }
   }
 #if defined(XP_WIN)
   delete mIntelPowerGadget;
 #endif
 }
 
-void TableTicker::HandleSaveRequest()
+void GeckoSampler::HandleSaveRequest()
 {
   if (!mSaveRequested)
     return;
   mSaveRequested = false;
 
 #ifndef SPS_STANDALONE
   // TODO: Use use the ipc/chromium Tasks here to support processes
   // without XPCOM.
   nsCOMPtr<nsIRunnable> runnable = new SaveProfileTask();
   NS_DispatchToMainThread(runnable);
 #endif
 }
 
-void TableTicker::DeleteExpiredMarkers()
+void GeckoSampler::DeleteExpiredMarkers()
 {
   mBuffer->deleteExpiredStoredMarkers();
 }
 
-void TableTicker::StreamTaskTracer(SpliceableJSONWriter& aWriter)
+void GeckoSampler::StreamTaskTracer(SpliceableJSONWriter& aWriter)
 {
 #ifdef MOZ_TASK_TRACER
   aWriter.StartArrayProperty("data");
     nsAutoPtr<nsTArray<nsCString>> data(mozilla::tasktracer::GetLoggedData(sStartTime));
     for (uint32_t i = 0; i < data->Length(); ++i) {
       aWriter.StringElement((data->ElementAt(i)).get());
     }
   aWriter.EndArray();
@@ -319,17 +321,17 @@ void TableTicker::StreamTaskTracer(Splic
     }
   aWriter.EndArray();
 
   aWriter.DoubleProperty("start", static_cast<double>(mozilla::tasktracer::GetStartTime()));
 #endif
 }
 
 
-void TableTicker::StreamMetaJSCustomObject(SpliceableJSONWriter& aWriter)
+void GeckoSampler::StreamMetaJSCustomObject(SpliceableJSONWriter& aWriter)
 {
   aWriter.IntProperty("version", 3);
   aWriter.DoubleProperty("interval", interval());
   aWriter.IntProperty("stackwalk", mUseStackWalk);
 
 #ifndef SPS_STANDALONE
   mozilla::TimeDuration delta = mozilla::TimeStamp::Now() - sStartTime;
   aWriter.DoubleProperty("startTime", static_cast<double>(PR_Now()/1000.0 - delta.ToMilliseconds()));
@@ -373,55 +375,55 @@ void TableTicker::StreamMetaJSCustomObje
 
     res = appInfo->GetName(string);
     if (!NS_FAILED(res))
       aWriter.StringProperty("product", string.Data());
   }
 #endif
 }
 
-void TableTicker::ToStreamAsJSON(std::ostream& stream, double aSinceTime)
+void GeckoSampler::ToStreamAsJSON(std::ostream& stream, double aSinceTime)
 {
   SpliceableJSONWriter b(mozilla::MakeUnique<OStreamJSONWriteFunc>(stream));
   StreamJSON(b, aSinceTime);
 }
 
 #ifndef SPS_STANDALONE
-JSObject* TableTicker::ToJSObject(JSContext *aCx, double aSinceTime)
+JSObject* GeckoSampler::ToJSObject(JSContext *aCx, double aSinceTime)
 {
   JS::RootedValue val(aCx);
   {
     UniquePtr<char[]> buf = ToJSON(aSinceTime);
     NS_ConvertUTF8toUTF16 js_string(nsDependentCString(buf.get()));
     MOZ_ALWAYS_TRUE(JS_ParseJSON(aCx, static_cast<const char16_t*>(js_string.get()),
                                  js_string.Length(), &val));
   }
   return &val.toObject();
 }
 #endif
 
-UniquePtr<char[]> TableTicker::ToJSON(double aSinceTime)
+UniquePtr<char[]> GeckoSampler::ToJSON(double aSinceTime)
 {
   SpliceableChunkedJSONWriter b;
   StreamJSON(b, aSinceTime);
   return b.WriteFunc()->CopyData();
 }
 
-void TableTicker::ToJSObjectAsync(double aSinceTime,
-                                  Promise* aPromise)
+void GeckoSampler::ToJSObjectAsync(double aSinceTime,
+                                  mozilla::dom::Promise* aPromise)
 {
   if (NS_WARN_IF(mGatherer)) {
     return;
   }
 
-  mGatherer = new ProfileGatherer(this, aSinceTime, aPromise);
+  mGatherer = new mozilla::ProfileGatherer(this, aSinceTime, aPromise);
   mGatherer->Start();
 }
 
-void TableTicker::ProfileGathered()
+void GeckoSampler::ProfileGathered()
 {
   mGatherer = nullptr;
 }
 
 struct SubprocessClosure {
   explicit SubprocessClosure(SpliceableJSONWriter* aWriter)
     : mWriter(aWriter)
   {}
@@ -486,17 +488,17 @@ void BuildJavaThreadJSObject(SpliceableJ
         break;
       }
     }
 
   aWriter.EndArray();
 }
 #endif
 
-void TableTicker::StreamJSON(SpliceableJSONWriter& aWriter, double aSinceTime)
+void GeckoSampler::StreamJSON(SpliceableJSONWriter& aWriter, double aSinceTime)
 {
   aWriter.Start(SpliceableJSONWriter::SingleLineStyle);
   {
     // Put shared library info
     aWriter.StringProperty("libs", GetSharedLibraryInfoStringInternal().c_str());
 
     // Put meta data
     aWriter.StartObjectProperty("meta");
@@ -556,17 +558,17 @@ void TableTicker::StreamJSON(SpliceableJ
 
       SetPaused(false);
     }
     aWriter.EndArray();
   }
   aWriter.End();
 }
 
-void TableTicker::FlushOnJSShutdown(JSRuntime* aRuntime)
+void GeckoSampler::FlushOnJSShutdown(JSRuntime* aRuntime)
 {
 #ifndef SPS_STANDALONE
   SetPaused(true);
 
   {
     ::MutexAutoLock lock(*sRegisteredThreadsMutex);
 
     for (size_t i = 0; i < sRegisteredThreads->size(); i++) {
@@ -589,17 +591,17 @@ void TableTicker::FlushOnJSShutdown(JSRu
   SetPaused(false);
 #endif
 }
 
 void PseudoStack::flushSamplerOnJSShutdown()
 {
 #ifndef SPS_STANDALONE
   MOZ_ASSERT(mRuntime);
-  TableTicker* t = tlsTicker.get();
+  GeckoSampler* t = tlsTicker.get();
   if (t) {
     t->FlushOnJSShutdown(mRuntime);
   }
 #endif
 }
 
 // END SaveProfileTask et al
 ////////////////////////////////////////////////////////////////////////
@@ -916,17 +918,17 @@ void StackWalkCallback(uint32_t aFrameNu
 {
   NativeStack* nativeStack = static_cast<NativeStack*>(aClosure);
   MOZ_ASSERT(nativeStack->count < nativeStack->size);
   nativeStack->sp_array[nativeStack->count] = aSP;
   nativeStack->pc_array[nativeStack->count] = aPC;
   nativeStack->count++;
 }
 
-void TableTicker::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample)
+void GeckoSampler::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample)
 {
 #ifndef XP_MACOSX
   uintptr_t thread = GetThreadHandle(aSample->threadProfile->GetPlatformData());
   MOZ_ASSERT(thread);
 #endif
   void* pc_array[1000];
   void* sp_array[1000];
   NativeStack nativeStack = {
@@ -969,17 +971,17 @@ void TableTicker::doNativeBacktrace(Thre
 #endif
   if (rv)
     mergeStacksIntoProfile(aProfile, aSample, nativeStack);
 }
 #endif
 
 
 #ifdef USE_EHABI_STACKWALK
-void TableTicker::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample)
+void GeckoSampler::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample)
 {
   void *pc_array[1000];
   void *sp_array[1000];
   NativeStack nativeStack = {
     pc_array,
     sp_array,
     mozilla::ArrayLength(pc_array),
     0
@@ -1037,17 +1039,17 @@ void TableTicker::doNativeBacktrace(Thre
                                       nativeStack.size - nativeStack.count);
 
   mergeStacksIntoProfile(aProfile, aSample, nativeStack);
 }
 #endif
 
 
 #ifdef USE_LUL_STACKWALK
-void TableTicker::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample)
+void GeckoSampler::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample)
 {
   const mcontext_t* mc
     = &reinterpret_cast<ucontext_t *>(aSample->context)->uc_mcontext;
 
   lul::UnwindRegs startRegs;
   memset(&startRegs, 0, sizeof(startRegs));
 
 # if defined(SPS_PLAT_amd64_linux)
@@ -1157,23 +1159,23 @@ void doSampleStackTrace(ThreadProfile &a
     aProfile.addTag(ProfileEntry('l', (void*)aSample->pc));
 #ifdef ENABLE_ARM_LR_SAVING
     aProfile.addTag(ProfileEntry('L', (void*)aSample->lr));
 #endif
   }
 #endif
 }
 
-void TableTicker::Tick(TickSample* sample)
+void GeckoSampler::Tick(TickSample* sample)
 {
   // Don't allow for ticks to happen within other ticks.
   InplaceTick(sample);
 }
 
-void TableTicker::InplaceTick(TickSample* sample)
+void GeckoSampler::InplaceTick(TickSample* sample)
 {
   ThreadProfile& currThreadProfile = *sample->threadProfile;
 
   currThreadProfile.addTag(ProfileEntry('T', currThreadProfile.ThreadId()));
 
   if (sample) {
     mozilla::TimeDuration delta = sample->timestamp - sStartTime;
     currThreadProfile.addTag(ProfileEntry('t', delta.ToMilliseconds()));
@@ -1246,17 +1248,17 @@ SyncProfile* NewSyncProfile()
 
   ThreadInfo* info = new ThreadInfo("SyncProfile", tid, false, stack, nullptr);
   SyncProfile* profile = new SyncProfile(info, GET_BACKTRACE_DEFAULT_ENTRY);
   return profile;
 }
 
 } // anonymous namespace
 
-SyncProfile* TableTicker::GetBacktrace()
+SyncProfile* GeckoSampler::GetBacktrace()
 {
   SyncProfile* profile = NewSyncProfile();
 
   TickSample sample;
   sample.threadProfile = profile;
 
 #if defined(HAVE_NATIVE_UNWIND)
 #if defined(XP_WIN) || defined(LINUX)
@@ -1273,14 +1275,14 @@ SyncProfile* TableTicker::GetBacktrace()
   profile->BeginUnwind();
   Tick(&sample);
   profile->EndUnwind();
 
   return profile;
 }
 
 void
-TableTicker::GetBufferInfo(uint32_t *aCurrentPosition, uint32_t *aTotalSize, uint32_t *aGeneration)
+GeckoSampler::GetBufferInfo(uint32_t *aCurrentPosition, uint32_t *aTotalSize, uint32_t *aGeneration)
 {
   *aCurrentPosition = mBuffer->mWritePos;
   *aTotalSize = mBuffer->mEntrySize;
   *aGeneration = mBuffer->mGeneration;
 }
rename from tools/profiler/TableTicker.h
rename to tools/profiler/core/GeckoSampler.h
--- a/tools/profiler/TableTicker.h
+++ b/tools/profiler/core/GeckoSampler.h
@@ -1,19 +1,21 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef TableTicker_h
-#define TableTicker_h
+#ifndef GeckoSampler_h
+#define GeckoSampler_h
 
 #include "platform.h"
 #include "ProfileEntry.h"
 #include "mozilla/Vector.h"
+#include "ThreadProfile.h"
+#include "ThreadInfo.h"
 #ifndef SPS_STANDALONE
 #include "IntelPowerGadget.h"
 #endif
 #ifdef MOZ_TASK_TRACER
 #include "GeckoTaskTracer.h"
 #endif
 
 namespace mozilla {
@@ -36,22 +38,22 @@ threadSelected(ThreadInfo* aInfo, const 
 
   return false;
 }
 
 extern mozilla::TimeStamp sLastTracerEvent;
 extern int sFrameNumber;
 extern int sLastFrameNumber;
 
-class TableTicker: public Sampler {
+class GeckoSampler: public Sampler {
  public:
-  TableTicker(double aInterval, int aEntrySize,
+  GeckoSampler(double aInterval, int aEntrySize,
               const char** aFeatures, uint32_t aFeatureCount,
               const char** aThreadNameFilters, uint32_t aFilterCount);
-  ~TableTicker();
+  ~GeckoSampler();
 
   void RegisterThread(ThreadInfo* aInfo) {
     if (!aInfo->IsMainThread() && !mProfileThreads) {
       return;
     }
 
     if (!threadSelected(aInfo, mThreadNameFilters)) {
       return;
rename from tools/profiler/IntelPowerGadget.cpp
rename to tools/profiler/core/IntelPowerGadget.cpp
rename from tools/profiler/IntelPowerGadget.h
rename to tools/profiler/core/IntelPowerGadget.h
rename from tools/profiler/PlatformMacros.h
rename to tools/profiler/core/PlatformMacros.h
new file mode 100644
--- /dev/null
+++ b/tools/profiler/core/ProfileBuffer.cpp
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ProfileBuffer.h"
+
+ProfileBuffer::ProfileBuffer(int aEntrySize)
+  : mEntries(MakeUnique<ProfileEntry[]>(aEntrySize))
+  , mWritePos(0)
+  , mReadPos(0)
+  , mEntrySize(aEntrySize)
+  , mGeneration(0)
+{
+}
+
+ProfileBuffer::~ProfileBuffer()
+{
+  while (mStoredMarkers.peek()) {
+    delete mStoredMarkers.popHead();
+  }
+}
+
+// Called from signal, call only reentrant functions
+void ProfileBuffer::addTag(const ProfileEntry& aTag)
+{
+  mEntries[mWritePos++] = aTag;
+  if (mWritePos == mEntrySize) {
+    // Wrapping around may result in things referenced in the buffer (e.g.,
+    // JIT code addresses and markers) being incorrectly collected.
+    MOZ_ASSERT(mGeneration != UINT32_MAX);
+    mGeneration++;
+    mWritePos = 0;
+  }
+  if (mWritePos == mReadPos) {
+    // Keep one slot open.
+    mEntries[mReadPos] = ProfileEntry();
+    mReadPos = (mReadPos + 1) % mEntrySize;
+  }
+}
+
+void ProfileBuffer::addStoredMarker(ProfilerMarker *aStoredMarker) {
+  aStoredMarker->SetGeneration(mGeneration);
+  mStoredMarkers.insert(aStoredMarker);
+}
+
+void ProfileBuffer::deleteExpiredStoredMarkers() {
+  // Delete markers of samples that have been overwritten due to circular
+  // buffer wraparound.
+  uint32_t generation = mGeneration;
+  while (mStoredMarkers.peek() &&
+         mStoredMarkers.peek()->HasExpired(generation)) {
+    delete mStoredMarkers.popHead();
+  }
+}
+
+void ProfileBuffer::reset() {
+  mGeneration += 2;
+  mReadPos = mWritePos = 0;
+}
+
+#define DYNAMIC_MAX_STRING 8192
+
+char* ProfileBuffer::processDynamicTag(int readPos,
+                                       int* tagsConsumed, char* tagBuff)
+{
+  int readAheadPos = (readPos + 1) % mEntrySize;
+  int tagBuffPos = 0;
+
+  // Read the string stored in mTagData until the null character is seen
+  bool seenNullByte = false;
+  while (readAheadPos != mWritePos && !seenNullByte) {
+    (*tagsConsumed)++;
+    ProfileEntry readAheadEntry = mEntries[readAheadPos];
+    for (size_t pos = 0; pos < sizeof(void*); pos++) {
+      tagBuff[tagBuffPos] = readAheadEntry.mTagChars[pos];
+      if (tagBuff[tagBuffPos] == '\0' || tagBuffPos == DYNAMIC_MAX_STRING-2) {
+        seenNullByte = true;
+        break;
+      }
+      tagBuffPos++;
+    }
+    if (!seenNullByte)
+      readAheadPos = (readAheadPos + 1) % mEntrySize;
+  }
+  return tagBuff;
+}
+
+
new file mode 100644
--- /dev/null
+++ b/tools/profiler/core/ProfileBuffer.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZ_PROFILE_BUFFER_H
+#define MOZ_PROFILE_BUFFER_H
+
+#include "ProfileEntry.h"
+#include "platform.h"
+#include "ProfileJSONWriter.h"
+#include "mozilla/RefPtr.h"
+
+class ProfileBuffer : public mozilla::RefCounted<ProfileBuffer> {
+public:
+  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ProfileBuffer)
+
+  explicit ProfileBuffer(int aEntrySize);
+
+  virtual ~ProfileBuffer();
+
+  void addTag(const ProfileEntry& aTag);
+  void StreamSamplesToJSON(SpliceableJSONWriter& aWriter, int aThreadId, double aSinceTime,
+                           JSRuntime* rt, UniqueStacks& aUniqueStacks);
+  void StreamMarkersToJSON(SpliceableJSONWriter& aWriter, int aThreadId, double aSinceTime,
+                           UniqueStacks& aUniqueStacks);
+  void DuplicateLastSample(int aThreadId);
+
+  void addStoredMarker(ProfilerMarker* aStoredMarker);
+
+  // The following two methods are not signal safe! They delete markers.
+  void deleteExpiredStoredMarkers();
+  void reset();
+
+protected:
+  char* processDynamicTag(int readPos, int* tagsConsumed, char* tagBuff);
+  int FindLastSampleOfThread(int aThreadId);
+
+public:
+  // Circular buffer 'Keep One Slot Open' implementation for simplicity
+  mozilla::UniquePtr<ProfileEntry[]> mEntries;
+
+  // Points to the next entry we will write to, which is also the one at which
+  // we need to stop reading.
+  int mWritePos;
+
+  // Points to the entry at which we can start reading.
+  int mReadPos;
+
+  // The number of entries in our buffer.
+  int mEntrySize;
+
+  // How many times mWritePos has wrapped around.
+  uint32_t mGeneration;
+
+  // Markers that marker entries in the buffer might refer to.
+  ProfilerMarkerLinkedList mStoredMarkers;
+};
+
+#endif
rename from tools/profiler/ProfileEntry.cpp
rename to tools/profiler/core/ProfileEntry.cpp
--- a/tools/profiler/ProfileEntry.cpp
+++ b/tools/profiler/core/ProfileEntry.cpp
@@ -96,101 +96,16 @@ bool ProfileEntry::is_ent(char tagChar) 
 void* ProfileEntry::get_tagPtr() {
   // No consistency checking.  Oh well.
   return mTagPtr;
 }
 
 // END ProfileEntry
 ////////////////////////////////////////////////////////////////////////
 
-
-////////////////////////////////////////////////////////////////////////
-// BEGIN ProfileBuffer
-
-ProfileBuffer::ProfileBuffer(int aEntrySize)
-  : mEntries(MakeUnique<ProfileEntry[]>(aEntrySize))
-  , mWritePos(0)
-  , mReadPos(0)
-  , mEntrySize(aEntrySize)
-  , mGeneration(0)
-{
-}
-
-ProfileBuffer::~ProfileBuffer()
-{
-  while (mStoredMarkers.peek()) {
-    delete mStoredMarkers.popHead();
-  }
-}
-
-// Called from signal, call only reentrant functions
-void ProfileBuffer::addTag(const ProfileEntry& aTag)
-{
-  mEntries[mWritePos++] = aTag;
-  if (mWritePos == mEntrySize) {
-    // Wrapping around may result in things referenced in the buffer (e.g.,
-    // JIT code addresses and markers) being incorrectly collected.
-    MOZ_ASSERT(mGeneration != UINT32_MAX);
-    mGeneration++;
-    mWritePos = 0;
-  }
-  if (mWritePos == mReadPos) {
-    // Keep one slot open.
-    mEntries[mReadPos] = ProfileEntry();
-    mReadPos = (mReadPos + 1) % mEntrySize;
-  }
-}
-
-void ProfileBuffer::addStoredMarker(ProfilerMarker *aStoredMarker) {
-  aStoredMarker->SetGeneration(mGeneration);
-  mStoredMarkers.insert(aStoredMarker);
-}
-
-void ProfileBuffer::deleteExpiredStoredMarkers() {
-  // Delete markers of samples that have been overwritten due to circular
-  // buffer wraparound.
-  uint32_t generation = mGeneration;
-  while (mStoredMarkers.peek() &&
-         mStoredMarkers.peek()->HasExpired(generation)) {
-    delete mStoredMarkers.popHead();
-  }
-}
-
-void ProfileBuffer::reset() {
-  mGeneration += 2;
-  mReadPos = mWritePos = 0;
-}
-
-#define DYNAMIC_MAX_STRING 8192
-
-char* ProfileBuffer::processDynamicTag(int readPos,
-                                       int* tagsConsumed, char* tagBuff)
-{
-  int readAheadPos = (readPos + 1) % mEntrySize;
-  int tagBuffPos = 0;
-
-  // Read the string stored in mTagData until the null character is seen
-  bool seenNullByte = false;
-  while (readAheadPos != mWritePos && !seenNullByte) {
-    (*tagsConsumed)++;
-    ProfileEntry readAheadEntry = mEntries[readAheadPos];
-    for (size_t pos = 0; pos < sizeof(void*); pos++) {
-      tagBuff[tagBuffPos] = readAheadEntry.mTagChars[pos];
-      if (tagBuff[tagBuffPos] == '\0' || tagBuffPos == DYNAMIC_MAX_STRING-2) {
-        seenNullByte = true;
-        break;
-      }
-      tagBuffPos++;
-    }
-    if (!seenNullByte)
-      readAheadPos = (readAheadPos + 1) % mEntrySize;
-  }
-  return tagBuff;
-}
-
 class JSONSchemaWriter
 {
   JSONWriter& mWriter;
   uint32_t mIndex;
 
 public:
   explicit JSONSchemaWriter(JSONWriter& aWriter)
    : mWriter(aWriter)
@@ -908,264 +823,10 @@ void ProfileBuffer::DuplicateLastSample(
 
 // END ProfileBuffer
 ////////////////////////////////////////////////////////////////////////
 
 
 ////////////////////////////////////////////////////////////////////////
 // BEGIN ThreadProfile
 
-ThreadProfile::ThreadProfile(ThreadInfo* aInfo, ProfileBuffer* aBuffer)
-  : mThreadInfo(aInfo)
-  , mBuffer(aBuffer)
-  , mPseudoStack(aInfo->Stack())
-  , mMutex(OS::CreateMutex("ThreadProfile::mMutex"))
-  , mThreadId(int(aInfo->ThreadId()))
-  , mIsMainThread(aInfo->IsMainThread())
-  , mPlatformData(aInfo->GetPlatformData())
-  , mStackTop(aInfo->StackTop())
-#ifndef SPS_STANDALONE
-  , mRespInfo(this)
-#endif
-#ifdef XP_LINUX
-  , mRssMemory(0)
-  , mUssMemory(0)
-#endif
-{
-  MOZ_COUNT_CTOR(ThreadProfile);
-  MOZ_ASSERT(aBuffer);
-
-  // I don't know if we can assert this. But we should warn.
-  MOZ_ASSERT(aInfo->ThreadId() >= 0, "native thread ID is < 0");
-  MOZ_ASSERT(aInfo->ThreadId() <= INT32_MAX, "native thread ID is > INT32_MAX");
-}
-
-ThreadProfile::~ThreadProfile()
-{
-  MOZ_COUNT_DTOR(ThreadProfile);
-}
-
-void ThreadProfile::addTag(const ProfileEntry& aTag)
-{
-  mBuffer->addTag(aTag);
-}
-
-void ThreadProfile::addStoredMarker(ProfilerMarker *aStoredMarker) {
-  mBuffer->addStoredMarker(aStoredMarker);
-}
-
-void ThreadProfile::StreamJSON(SpliceableJSONWriter& aWriter, double aSinceTime)
-{
-  // mUniqueStacks may already be emplaced from FlushSamplesAndMarkers.
-  if (!mUniqueStacks.isSome()) {
-#ifndef SPS_STANDALONE
-    mUniqueStacks.emplace(mPseudoStack->mRuntime);
-#else
-    mUniqueStacks.emplace(nullptr);
-#endif
-  }
-
-  aWriter.Start(SpliceableJSONWriter::SingleLineStyle);
-  {
-    StreamSamplesAndMarkers(aWriter, aSinceTime, *mUniqueStacks);
-
-    aWriter.StartObjectProperty("stackTable");
-    {
-      {
-        JSONSchemaWriter schema(aWriter);
-        schema.WriteField("prefix");
-        schema.WriteField("frame");
-      }
-
-      aWriter.StartArrayProperty("data");
-      {
-        mUniqueStacks->SpliceStackTableElements(aWriter);
-      }
-      aWriter.EndArray();
-    }
-    aWriter.EndObject();
-
-    aWriter.StartObjectProperty("frameTable");
-    {
-      {
-        JSONSchemaWriter schema(aWriter);
-        schema.WriteField("location");
-        schema.WriteField("implementation");
-        schema.WriteField("optimizations");
-        schema.WriteField("line");
-        schema.WriteField("category");
-      }
-
-      aWriter.StartArrayProperty("data");
-      {
-        mUniqueStacks->SpliceFrameTableElements(aWriter);
-      }
-      aWriter.EndArray();
-    }
-    aWriter.EndObject();
-
-    aWriter.StartArrayProperty("stringTable");
-    {
-      mUniqueStacks->mUniqueStrings.SpliceStringTableElements(aWriter);
-    }
-    aWriter.EndArray();
-  }
-  aWriter.End();
-
-  mUniqueStacks.reset();
-}
-
-void ThreadProfile::StreamSamplesAndMarkers(SpliceableJSONWriter& aWriter, double aSinceTime,
-                                            UniqueStacks& aUniqueStacks)
-{
-#ifndef SPS_STANDALONE
-  // Thread meta data
-  if (XRE_GetProcessType() == GeckoProcessType_Plugin) {
-    // TODO Add the proper plugin name
-    aWriter.StringProperty("name", "Plugin");
-  } else if (XRE_GetProcessType() == GeckoProcessType_Content) {
-    // This isn't going to really help once we have multiple content
-    // processes, but it'll do for now.
-    aWriter.StringProperty("name", "Content");
-  } else {
-    aWriter.StringProperty("name", Name());
-  }
-#else
-  aWriter.StringProperty("name", Name());
-#endif
-
-  aWriter.IntProperty("tid", static_cast<int>(mThreadId));
-
-  aWriter.StartObjectProperty("samples");
-  {
-    {
-      JSONSchemaWriter schema(aWriter);
-      schema.WriteField("stack");
-      schema.WriteField("time");
-      schema.WriteField("responsiveness");
-      schema.WriteField("rss");
-      schema.WriteField("uss");
-      schema.WriteField("frameNumber");
-      schema.WriteField("power");
-    }
-
-    aWriter.StartArrayProperty("data");
-    {
-      if (mSavedStreamedSamples) {
-        // We would only have saved streamed samples during shutdown
-        // streaming, which cares about dumping the entire buffer, and thus
-        // should have passed in 0 for aSinceTime.
-        MOZ_ASSERT(aSinceTime == 0);
-        aWriter.Splice(mSavedStreamedSamples.get());
-        mSavedStreamedSamples.reset();
-      }
-      mBuffer->StreamSamplesToJSON(aWriter, mThreadId, aSinceTime,
-#ifndef SPS_STANDALONE
-                                   mPseudoStack->mRuntime,
-#else
-                                   nullptr,
-#endif
-                                   aUniqueStacks);
-    }
-    aWriter.EndArray();
-  }
-  aWriter.EndObject();
-
-  aWriter.StartObjectProperty("markers");
-  {
-    {
-      JSONSchemaWriter schema(aWriter);
-      schema.WriteField("name");
-      schema.WriteField("time");
-      schema.WriteField("data");
-    }
-
-    aWriter.StartArrayProperty("data");
-    {
-      if (mSavedStreamedMarkers) {
-        MOZ_ASSERT(aSinceTime == 0);
-        aWriter.Splice(mSavedStreamedMarkers.get());
-        mSavedStreamedMarkers.reset();
-      }
-      mBuffer->StreamMarkersToJSON(aWriter, mThreadId, aSinceTime, aUniqueStacks);
-    }
-    aWriter.EndArray();
-  }
-  aWriter.EndObject();
-}
-
-void ThreadProfile::FlushSamplesAndMarkers()
-{
-  // This function is used to serialize the current buffer just before
-  // JSRuntime destruction.
-  MOZ_ASSERT(mPseudoStack->mRuntime);
-
-  // Unlike StreamJSObject, do not surround the samples in brackets by calling
-  // aWriter.{Start,End}BareList. The result string will be a comma-separated
-  // list of JSON object literals that will prepended by StreamJSObject into
-  // an existing array.
-  //
-  // Note that the UniqueStacks instance is persisted so that the frame-index
-  // mapping is stable across JS shutdown.
-#ifndef SPS_STANDALONE
-  mUniqueStacks.emplace(mPseudoStack->mRuntime);
-#else
-  mUniqueStacks.emplace(nullptr);
-#endif
-
-  {
-    SpliceableChunkedJSONWriter b;
-    b.StartBareList();
-    {
-      mBuffer->StreamSamplesToJSON(b, mThreadId, /* aSinceTime = */ 0,
-#ifndef SPS_STANDALONE
-                                   mPseudoStack->mRuntime,
-#else
-                                   nullptr,
-#endif
-                                   *mUniqueStacks);
-    }
-    b.EndBareList();
-    mSavedStreamedSamples = b.WriteFunc()->CopyData();
-  }
-
-  {
-    SpliceableChunkedJSONWriter b;
-    b.StartBareList();
-    {
-      mBuffer->StreamMarkersToJSON(b, mThreadId, /* aSinceTime = */ 0, *mUniqueStacks);
-    }
-    b.EndBareList();
-    mSavedStreamedMarkers = b.WriteFunc()->CopyData();
-  }
-
-  // Reset the buffer. Attempting to symbolicate JS samples after mRuntime has
-  // gone away will crash.
-  mBuffer->reset();
-}
-
-PseudoStack* ThreadProfile::GetPseudoStack()
-{
-  return mPseudoStack;
-}
-
-void ThreadProfile::BeginUnwind()
-{
-  mMutex->Lock();
-}
-
-void ThreadProfile::EndUnwind()
-{
-  mMutex->Unlock();
-}
-
-Mutex& ThreadProfile::GetMutex()
-{
-  return *mMutex.get();
-}
-
-void ThreadProfile::DuplicateLastSample()
-{
-  mBuffer->DuplicateLastSample(mThreadId);
-}
-
 // END ThreadProfile
 ////////////////////////////////////////////////////////////////////////
rename from tools/profiler/ProfileEntry.h
rename to tools/profiler/core/ProfileEntry.h
--- a/tools/profiler/ProfileEntry.h
+++ b/tools/profiler/core/ProfileEntry.h
@@ -306,62 +306,16 @@ private:
   // until we can find a better solution.
 #ifdef SPS_STANDALONE
   std::map<StackKey, uint32_t> mStackToIndexMap;
 #else
   nsDataHashtable<nsGenericHashKey<StackKey>, uint32_t> mStackToIndexMap;
 #endif
 };
 
-class ProfileBuffer : public mozilla::RefCounted<ProfileBuffer> {
-public:
-  MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ProfileBuffer)
-
-  explicit ProfileBuffer(int aEntrySize);
-
-  virtual ~ProfileBuffer();
-
-  void addTag(const ProfileEntry& aTag);
-  void StreamSamplesToJSON(SpliceableJSONWriter& aWriter, int aThreadId, double aSinceTime,
-                           JSRuntime* rt, UniqueStacks& aUniqueStacks);
-  void StreamMarkersToJSON(SpliceableJSONWriter& aWriter, int aThreadId, double aSinceTime,
-                           UniqueStacks& aUniqueStacks);
-  void DuplicateLastSample(int aThreadId);
-
-  void addStoredMarker(ProfilerMarker* aStoredMarker);
-
-  // The following two methods are not signal safe! They delete markers.
-  void deleteExpiredStoredMarkers();
-  void reset();
-
-protected:
-  char* processDynamicTag(int readPos, int* tagsConsumed, char* tagBuff);
-  int FindLastSampleOfThread(int aThreadId);
-
-public:
-  // Circular buffer 'Keep One Slot Open' implementation for simplicity
-  mozilla::UniquePtr<ProfileEntry[]> mEntries;
-
-  // Points to the next entry we will write to, which is also the one at which
-  // we need to stop reading.
-  int mWritePos;
-
-  // Points to the entry at which we can start reading.
-  int mReadPos;
-
-  // The number of entries in our buffer.
-  int mEntrySize;
-
-  // How many times mWritePos has wrapped around.
-  uint32_t mGeneration;
-
-  // Markers that marker entries in the buffer might refer to.
-  ProfilerMarkerLinkedList mStoredMarkers;
-};
-
 //
 // ThreadProfile JSON Format
 // -------------------------
 //
 // The profile contains much duplicate information. The output JSON of the
 // profile attempts to deduplicate strings, frames, and stack prefixes, to cut
 // down on size and to increase JSON streaming speed. Deduplicated values are
 // streamed as indices into their respective tables.
@@ -445,100 +399,9 @@ public:
 //     "(root)",
 //     "foo.js",
 //     "baseline",
 //     "example marker"
 //   ]
 // }
 //
 
-class ThreadProfile
-{
-public:
-  ThreadProfile(ThreadInfo* aThreadInfo, ProfileBuffer* aBuffer);
-  virtual ~ThreadProfile();
-  void addTag(const ProfileEntry& aTag);
-
-  /**
-   * Track a marker which has been inserted into the ThreadProfile.
-   * This marker can safely be deleted once the generation has
-   * expired.
-   */
-  void addStoredMarker(ProfilerMarker *aStoredMarker);
-  PseudoStack* GetPseudoStack();
-  Mutex& GetMutex();
-  void StreamJSON(SpliceableJSONWriter& aWriter, double aSinceTime = 0);
-
-  /**
-   * Call this method when the JS entries inside the buffer are about to
-   * become invalid, i.e., just before JS shutdown.
-   */
-  void FlushSamplesAndMarkers();
-
-  void BeginUnwind();
-  virtual void EndUnwind();
-  virtual SyncProfile* AsSyncProfile() { return nullptr; }
-
-  bool IsMainThread() const { return mIsMainThread; }
-  const char* Name() const { return mThreadInfo->Name(); }
-  int ThreadId() const { return mThreadId; }
-
-  PlatformData* GetPlatformData() const { return mPlatformData; }
-  void* GetStackTop() const { return mStackTop; }
-  void DuplicateLastSample();
-
-  ThreadInfo* GetThreadInfo() const { return mThreadInfo; }
-#ifndef SPS_STANDALONE
-  ThreadResponsiveness* GetThreadResponsiveness() { return &mRespInfo; }
-#endif
-  void SetPendingDelete()
-  {
-    mPseudoStack = nullptr;
-    mPlatformData = nullptr;
-  }
-
-  uint32_t bufferGeneration() const {
-    return mBuffer->mGeneration;
-  }
-
-protected:
-  void StreamSamplesAndMarkers(SpliceableJSONWriter& aWriter, double aSinceTime,
-                               UniqueStacks& aUniqueStacks);
-
-private:
-  FRIEND_TEST(ThreadProfile, InsertOneTag);
-  FRIEND_TEST(ThreadProfile, InsertOneTagWithTinyBuffer);
-  FRIEND_TEST(ThreadProfile, InsertTagsNoWrap);
-  FRIEND_TEST(ThreadProfile, InsertTagsWrap);
-  FRIEND_TEST(ThreadProfile, MemoryMeasure);
-  ThreadInfo* mThreadInfo;
-
-  const mozilla::RefPtr<ProfileBuffer> mBuffer;
-
-  // JS frames in the buffer may require a live JSRuntime to stream (e.g.,
-  // stringifying JIT frames). In the case of JSRuntime destruction,
-  // FlushSamplesAndMarkers should be called to save them. These are spliced
-  // into the final stream.
-  mozilla::UniquePtr<char[]> mSavedStreamedSamples;
-  mozilla::UniquePtr<char[]> mSavedStreamedMarkers;
-  mozilla::Maybe<UniqueStacks> mUniqueStacks;
-
-  PseudoStack*   mPseudoStack;
-  mozilla::UniquePtr<Mutex>  mMutex;
-  int            mThreadId;
-  bool           mIsMainThread;
-  PlatformData*  mPlatformData;  // Platform specific data.
-  void* const    mStackTop;
-#ifndef SPS_STANDALONE
-  ThreadResponsiveness mRespInfo;
-#endif
-
-  // Only Linux is using a signal sender, instead of stopping the thread, so we
-  // need some space to store the data which cannot be collected in the signal
-  // handler code.
-#ifdef XP_LINUX
-public:
-  int64_t        mRssMemory;
-  int64_t        mUssMemory;
-#endif
-};
-
 #endif /* ndef MOZ_PROFILE_ENTRY_H */
rename from tools/profiler/ProfileJSONWriter.cpp
rename to tools/profiler/core/ProfileJSONWriter.cpp
rename from tools/profiler/ProfileJSONWriter.h
rename to tools/profiler/core/ProfileJSONWriter.h
rename from tools/profiler/ProfilerBacktrace.cpp
rename to tools/profiler/core/ProfilerBacktrace.cpp
rename from tools/profiler/ProfilerMarkers.cpp
rename to tools/profiler/core/ProfilerMarkers.cpp
rename from tools/profiler/SyncProfile.cpp
rename to tools/profiler/core/SyncProfile.cpp
rename from tools/profiler/SyncProfile.h
rename to tools/profiler/core/SyncProfile.h
--- a/tools/profiler/SyncProfile.h
+++ b/tools/profiler/core/SyncProfile.h
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __SYNCPROFILE_H
 #define __SYNCPROFILE_H
 
 #include "ProfileEntry.h"
+#include "ThreadProfile.h"
 
 class SyncProfile : public ThreadProfile
 {
 public:
   SyncProfile(ThreadInfo* aInfo, int aEntrySize);
   ~SyncProfile();
 
   // SyncProfiles' stacks are deduplicated in the context of the containing
new file mode 100644
--- /dev/null
+++ b/tools/profiler/core/ThreadInfo.cpp
@@ -0,0 +1,38 @@
+
+ThreadInfo::ThreadInfo(const char* aName, int aThreadId,
+                       bool aIsMainThread, PseudoStack* aPseudoStack,
+                       void* aStackTop)
+  : mName(strdup(aName))
+  , mThreadId(aThreadId)
+  , mIsMainThread(aIsMainThread)
+  , mPseudoStack(aPseudoStack)
+  , mPlatformData(Sampler::AllocPlatformData(aThreadId))
+  , mProfile(nullptr)
+  , mStackTop(aStackTop)
+  , mPendingDelete(false)
+{
+#ifndef SPS_STANDALONE
+  mThread = NS_GetCurrentThread();
+#endif
+}
+
+ThreadInfo::~ThreadInfo() {
+  free(mName);
+
+  if (mProfile)
+    delete mProfile;
+
+  Sampler::FreePlatformData(mPlatformData);
+}
+
+void
+ThreadInfo::SetPendingDelete()
+{
+  mPendingDelete = true;
+  // We don't own the pseudostack so disconnect it.
+  mPseudoStack = nullptr;
+  if (mProfile) {
+    mProfile->SetPendingDelete();
+  }
+}
+
new file mode 100644
--- /dev/null
+++ b/tools/profiler/core/ThreadInfo.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZ_THREAD_INFO_H
+#define MOZ_THREAD_INFO_H
+
+#include "platform.h"
+
+class ThreadInfo {
+ public:
+  ThreadInfo(const char* aName, int aThreadId, bool aIsMainThread, PseudoStack* aPseudoStack, void* aStackTop);
+
+  virtual ~ThreadInfo();
+
+  const char* Name() const { return mName; }
+  int ThreadId() const { return mThreadId; }
+
+  bool IsMainThread() const { return mIsMainThread; }
+  PseudoStack* Stack() const { return mPseudoStack; }
+
+  void SetProfile(ThreadProfile* aProfile) { mProfile = aProfile; }
+  ThreadProfile* Profile() const { return mProfile; }
+
+  PlatformData* GetPlatformData() const { return mPlatformData; }
+  void* StackTop() const { return mStackTop; }
+
+  virtual void SetPendingDelete();
+  bool IsPendingDelete() const { return mPendingDelete; }
+
+#ifdef MOZ_NUWA_PROCESS
+  void SetThreadId(int aThreadId) { mThreadId = aThreadId; }
+#endif
+
+#ifndef SPS_STANDALONE
+  /**
+   * May be null for the main thread if the profiler was started during startup
+   */
+  nsIThread* GetThread() const { return mThread.get(); }
+#endif
+ private:
+  char* mName;
+  int mThreadId;
+  const bool mIsMainThread;
+  PseudoStack* mPseudoStack;
+  PlatformData* mPlatformData;
+  ThreadProfile* mProfile;
+  void* const mStackTop;
+#ifndef SPS_STANDALONE
+  nsCOMPtr<nsIThread> mThread;
+#endif
+  bool mPendingDelete;
+};
+
+// Just like ThreadInfo, but owns a reference to the PseudoStack.
+class StackOwningThreadInfo : public ThreadInfo {
+ public:
+  StackOwningThreadInfo(const char* aName, int aThreadId, bool aIsMainThread, PseudoStack* aPseudoStack, void* aStackTop);
+  virtual ~StackOwningThreadInfo();
+
+  virtual void SetPendingDelete();
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/tools/profiler/core/ThreadProfile.cpp
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ThreadProfile::ThreadProfile(ThreadInfo* aInfo, ProfileBuffer* aBuffer)
+  : mThreadInfo(aInfo)
+  , mBuffer(aBuffer)
+  , mPseudoStack(aInfo->Stack())
+  , mMutex(OS::CreateMutex("ThreadProfile::mMutex"))
+  , mThreadId(int(aInfo->ThreadId()))
+  , mIsMainThread(aInfo->IsMainThread())
+  , mPlatformData(aInfo->GetPlatformData())
+  , mStackTop(aInfo->StackTop())
+#ifndef SPS_STANDALONE
+  , mRespInfo(this)
+#endif
+#ifdef XP_LINUX
+  , mRssMemory(0)
+  , mUssMemory(0)
+#endif
+{
+  MOZ_COUNT_CTOR(ThreadProfile);
+  MOZ_ASSERT(aBuffer);
+
+  // I don't know if we can assert this. But we should warn.
+  MOZ_ASSERT(aInfo->ThreadId() >= 0, "native thread ID is < 0");
+  MOZ_ASSERT(aInfo->ThreadId() <= INT32_MAX, "native thread ID is > INT32_MAX");
+}
+
+ThreadProfile::~ThreadProfile()
+{
+  MOZ_COUNT_DTOR(ThreadProfile);
+}
+
+void ThreadProfile::addTag(const ProfileEntry& aTag)
+{
+  mBuffer->addTag(aTag);
+}
+
+void ThreadProfile::addStoredMarker(ProfilerMarker *aStoredMarker) {
+  mBuffer->addStoredMarker(aStoredMarker);
+}
+
+void ThreadProfile::StreamJSON(SpliceableJSONWriter& aWriter, double aSinceTime)
+{
+  // mUniqueStacks may already be emplaced from FlushSamplesAndMarkers.
+  if (!mUniqueStacks.isSome()) {
+#ifndef SPS_STANDALONE
+    mUniqueStacks.emplace(mPseudoStack->mRuntime);
+#else
+    mUniqueStacks.emplace(nullptr);
+#endif
+  }
+
+  aWriter.Start(SpliceableJSONWriter::SingleLineStyle);
+  {
+    StreamSamplesAndMarkers(aWriter, aSinceTime, *mUniqueStacks);
+
+    aWriter.StartObjectProperty("stackTable");
+    {
+      {
+        JSONSchemaWriter schema(aWriter);
+        schema.WriteField("prefix");
+        schema.WriteField("frame");
+      }
+
+      aWriter.StartArrayProperty("data");
+      {
+        mUniqueStacks->SpliceStackTableElements(aWriter);
+      }
+      aWriter.EndArray();
+    }
+    aWriter.EndObject();
+
+    aWriter.StartObjectProperty("frameTable");
+    {
+      {
+        JSONSchemaWriter schema(aWriter);
+        schema.WriteField("location");
+        schema.WriteField("implementation");
+        schema.WriteField("optimizations");
+        schema.WriteField("line");
+        schema.WriteField("category");
+      }
+
+      aWriter.StartArrayProperty("data");
+      {
+        mUniqueStacks->SpliceFrameTableElements(aWriter);
+      }
+      aWriter.EndArray();
+    }
+    aWriter.EndObject();
+
+    aWriter.StartArrayProperty("stringTable");
+    {
+      mUniqueStacks->mUniqueStrings.SpliceStringTableElements(aWriter);
+    }
+    aWriter.EndArray();
+  }
+  aWriter.End();
+
+  mUniqueStacks.reset();
+}
+
+void ThreadProfile::StreamSamplesAndMarkers(SpliceableJSONWriter& aWriter, double aSinceTime,
+                                            UniqueStacks& aUniqueStacks)
+{
+#ifndef SPS_STANDALONE
+  // Thread meta data
+  if (XRE_GetProcessType() == GeckoProcessType_Plugin) {
+    // TODO Add the proper plugin name
+    aWriter.StringProperty("name", "Plugin");
+  } else if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    // This isn't going to really help once we have multiple content
+    // processes, but it'll do for now.
+    aWriter.StringProperty("name", "Content");
+  } else {
+    aWriter.StringProperty("name", Name());
+  }
+#else
+  aWriter.StringProperty("name", Name());
+#endif
+
+  aWriter.IntProperty("tid", static_cast<int>(mThreadId));
+
+  aWriter.StartObjectProperty("samples");
+  {
+    {
+      JSONSchemaWriter schema(aWriter);
+      schema.WriteField("stack");
+      schema.WriteField("time");
+      schema.WriteField("responsiveness");
+      schema.WriteField("rss");
+      schema.WriteField("uss");
+      schema.WriteField("frameNumber");
+      schema.WriteField("power");
+    }
+
+    aWriter.StartArrayProperty("data");
+    {
+      if (mSavedStreamedSamples) {
+        // We would only have saved streamed samples during shutdown
+        // streaming, which cares about dumping the entire buffer, and thus
+        // should have passed in 0 for aSinceTime.
+        MOZ_ASSERT(aSinceTime == 0);
+        aWriter.Splice(mSavedStreamedSamples.get());
+        mSavedStreamedSamples.reset();
+      }
+      mBuffer->StreamSamplesToJSON(aWriter, mThreadId, aSinceTime,
+#ifndef SPS_STANDALONE
+                                   mPseudoStack->mRuntime,
+#else
+                                   nullptr,
+#endif
+                                   aUniqueStacks);
+    }
+    aWriter.EndArray();
+  }
+  aWriter.EndObject();
+
+  aWriter.StartObjectProperty("markers");
+  {
+    {
+      JSONSchemaWriter schema(aWriter);
+      schema.WriteField("name");
+      schema.WriteField("time");
+      schema.WriteField("data");
+    }
+
+    aWriter.StartArrayProperty("data");
+    {
+      if (mSavedStreamedMarkers) {
+        MOZ_ASSERT(aSinceTime == 0);
+        aWriter.Splice(mSavedStreamedMarkers.get());
+        mSavedStreamedMarkers.reset();
+      }
+      mBuffer->StreamMarkersToJSON(aWriter, mThreadId, aSinceTime, aUniqueStacks);
+    }
+    aWriter.EndArray();
+  }
+  aWriter.EndObject();
+}
+
+void ThreadProfile::FlushSamplesAndMarkers()
+{
+  // This function is used to serialize the current buffer just before
+  // JSRuntime destruction.
+  MOZ_ASSERT(mPseudoStack->mRuntime);
+
+  // Unlike StreamJSObject, do not surround the samples in brackets by calling
+  // aWriter.{Start,End}BareList. The result string will be a comma-separated
+  // list of JSON object literals that will prepended by StreamJSObject into
+  // an existing array.
+  //
+  // Note that the UniqueStacks instance is persisted so that the frame-index
+  // mapping is stable across JS shutdown.
+#ifndef SPS_STANDALONE
+  mUniqueStacks.emplace(mPseudoStack->mRuntime);
+#else
+  mUniqueStacks.emplace(nullptr);
+#endif
+
+  {
+    SpliceableChunkedJSONWriter b;
+    b.StartBareList();
+    {
+      mBuffer->StreamSamplesToJSON(b, mThreadId, /* aSinceTime = */ 0,
+#ifndef SPS_STANDALONE
+                                   mPseudoStack->mRuntime,
+#else
+                                   nullptr,
+#endif
+                                   *mUniqueStacks);
+    }
+    b.EndBareList();
+    mSavedStreamedSamples = b.WriteFunc()->CopyData();
+  }
+
+  {
+    SpliceableChunkedJSONWriter b;
+    b.StartBareList();
+    {
+      mBuffer->StreamMarkersToJSON(b, mThreadId, /* aSinceTime = */ 0, *mUniqueStacks);
+    }
+    b.EndBareList();
+    mSavedStreamedMarkers = b.WriteFunc()->CopyData();
+  }
+
+  // Reset the buffer. Attempting to symbolicate JS samples after mRuntime has
+  // gone away will crash.
+  mBuffer->reset();
+}
+
+PseudoStack* ThreadProfile::GetPseudoStack()
+{
+  return mPseudoStack;
+}
+
+void ThreadProfile::BeginUnwind()
+{
+  mMutex->Lock();
+}
+
+void ThreadProfile::EndUnwind()
+{
+  mMutex->Unlock();
+}
+
+::Mutex& ThreadProfile::GetMutex()
+{
+  return *mMutex.get();
+}
+
+void ThreadProfile::DuplicateLastSample()
+{
+  mBuffer->DuplicateLastSample(mThreadId);
+}
+
new file mode 100644
--- /dev/null
+++ b/tools/profiler/core/ThreadProfile.h
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZ_THREAD_PROFILE_H
+#define MOZ_THREAD_PROFILE_H
+
+#include "ProfileBuffer.h"
+#include "ThreadInfo.h"
+
+class ThreadProfile
+{
+public:
+  ThreadProfile(ThreadInfo* aThreadInfo, ProfileBuffer* aBuffer);
+  virtual ~ThreadProfile();
+  void addTag(const ProfileEntry& aTag);
+
+  /**
+   * Track a marker which has been inserted into the ThreadProfile.
+   * This marker can safely be deleted once the generation has
+   * expired.
+   */
+  void addStoredMarker(ProfilerMarker *aStoredMarker);
+  PseudoStack* GetPseudoStack();
+  ::Mutex& GetMutex();
+  void StreamJSON(SpliceableJSONWriter& aWriter, double aSinceTime = 0);
+
+  /**
+   * Call this method when the JS entries inside the buffer are about to
+   * become invalid, i.e., just before JS shutdown.
+   */
+  void FlushSamplesAndMarkers();
+
+  void BeginUnwind();
+  virtual void EndUnwind();
+  virtual SyncProfile* AsSyncProfile() { return nullptr; }
+
+  bool IsMainThread() const { return mIsMainThread; }
+  const char* Name() const { return mThreadInfo->Name(); }
+  int ThreadId() const { return mThreadId; }
+
+  PlatformData* GetPlatformData() const { return mPlatformData; }
+  void* GetStackTop() const { return mStackTop; }
+  void DuplicateLastSample();
+
+  ThreadInfo* GetThreadInfo() const { return mThreadInfo; }
+#ifndef SPS_STANDALONE
+  ThreadResponsiveness* GetThreadResponsiveness() { return &mRespInfo; }
+#endif
+  void SetPendingDelete()
+  {
+    mPseudoStack = nullptr;
+    mPlatformData = nullptr;
+  }
+
+  uint32_t bufferGeneration() const {
+    return mBuffer->mGeneration;
+  }
+
+protected:
+  void StreamSamplesAndMarkers(SpliceableJSONWriter& aWriter, double aSinceTime,
+                               UniqueStacks& aUniqueStacks);
+
+private:
+  FRIEND_TEST(ThreadProfile, InsertOneTag);
+  FRIEND_TEST(ThreadProfile, InsertOneTagWithTinyBuffer);
+  FRIEND_TEST(ThreadProfile, InsertTagsNoWrap);
+  FRIEND_TEST(ThreadProfile, InsertTagsWrap);
+  FRIEND_TEST(ThreadProfile, MemoryMeasure);
+  ThreadInfo* mThreadInfo;
+
+  const mozilla::RefPtr<ProfileBuffer> mBuffer;
+
+  // JS frames in the buffer may require a live JSRuntime to stream (e.g.,
+  // stringifying JIT frames). In the case of JSRuntime destruction,
+  // FlushSamplesAndMarkers should be called to save them. These are spliced
+  // into the final stream.
+  mozilla::UniquePtr<char[]> mSavedStreamedSamples;
+  mozilla::UniquePtr<char[]> mSavedStreamedMarkers;
+  mozilla::Maybe<UniqueStacks> mUniqueStacks;
+
+  PseudoStack*   mPseudoStack;
+  mozilla::UniquePtr<Mutex>  mMutex;
+  int            mThreadId;
+  bool           mIsMainThread;
+  PlatformData*  mPlatformData;  // Platform specific data.
+  void* const    mStackTop;
+#ifndef SPS_STANDALONE
+  ThreadResponsiveness mRespInfo;
+#endif
+
+  // Only Linux is using a signal sender, instead of stopping the thread, so we
+  // need some space to store the data which cannot be collected in the signal
+  // handler code.
+#ifdef XP_LINUX
+public:
+  int64_t        mRssMemory;
+  int64_t        mUssMemory;
+#endif
+};
+
+#endif
rename from tools/profiler/platform-linux.cc
rename to tools/profiler/core/platform-linux.cc
--- a/tools/profiler/platform-linux.cc
+++ b/tools/profiler/core/platform-linux.cc
@@ -68,27 +68,27 @@
 #include "GeckoProfiler.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/LinuxSignal.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/DebugOnly.h"
 #include "ProfileEntry.h"
 #include "nsThreadUtils.h"
-#include "TableTicker.h"
+#include "GeckoSampler.h"
 #include "ThreadResponsiveness.h"
 
 #if defined(__ARM_EABI__) && defined(MOZ_WIDGET_GONK)
  // Should also work on other Android and ARM Linux, but not tested there yet.
 # define USE_EHABI_STACKWALK
 # include "EHABIStackWalk.h"
 #elif defined(SPS_PLAT_amd64_linux) || defined(SPS_PLAT_x86_linux)
 # define USE_LUL_STACKWALK
-# include "LulMain.h"
-# include "platform-linux-lul.h"
+# include "lul/LulMain.h"
+# include "lul/platform-linux-lul.h"
 #endif
 
 // Memory profile
 #include "nsMemoryReporterManager.h"
 
 #include <string.h>
 #include <list>
 
@@ -268,17 +268,17 @@ static void ProfilerSignalThread(ThreadP
     profile->mUssMemory = 0;
   }
 }
 
 int tgkill(pid_t tgid, pid_t tid, int signalno) {
   return syscall(SYS_tgkill, tgid, tid, signalno);
 }
 
-class PlatformData : public Malloced {
+class PlatformData {
  public:
   PlatformData()
   {}
 };
 
 /* static */ PlatformData*
 Sampler::AllocPlatformData(int aThreadId)
 {
rename from tools/profiler/platform-macos.cc
rename to tools/profiler/core/platform-macos.cc
--- a/tools/profiler/platform-macos.cc
+++ b/tools/profiler/core/platform-macos.cc
@@ -33,17 +33,17 @@
 #include "ThreadResponsiveness.h"
 #include "nsThreadUtils.h"
 
 // Memory profile
 #include "nsMemoryReporterManager.h"
 #endif
 
 #include "platform.h"
-#include "TableTicker.h"
+#include "GeckoSampler.h"
 #include "mozilla/TimeStamp.h"
 
 using mozilla::TimeStamp;
 using mozilla::TimeDuration;
 
 // this port is based off of v8 svn revision 9837
 
 // XXX: this is a very stubbed out implementation
@@ -132,17 +132,17 @@ void Thread::Start() {
   pthread_create(&thread_, attr_ptr, ThreadEntry, this);
   ASSERT(thread_ != kNoThread);
 }
 
 void Thread::Join() {
   pthread_join(thread_, NULL);
 }
 
-class PlatformData : public Malloced {
+class PlatformData {
  public:
   PlatformData() : profiled_thread_(mach_thread_self())
   {
     profiled_pthread_ = pthread_from_mach_thread_np(profiled_thread_);
   }
 
   ~PlatformData() {
     // Deallocate Mach port for thread.
rename from tools/profiler/platform-win32.cc
rename to tools/profiler/core/platform-win32.cc
--- a/tools/profiler/platform-win32.cc
+++ b/tools/profiler/core/platform-win32.cc
@@ -25,24 +25,24 @@
 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 // SUCH DAMAGE.
 
 #include <windows.h>
 #include <mmsystem.h>
 #include <process.h>
 #include "platform.h"
-#include "TableTicker.h"
+#include "GeckoSampler.h"
 #include "ThreadResponsiveness.h"
 #include "ProfileEntry.h"
 
 // Memory profile
 #include "nsMemoryReporterManager.h"
 
-class PlatformData : public Malloced {
+class PlatformData {
  public:
   // Get a handle to the calling thread. This is the thread that we are
   // going to profile. We need to make a copy of the handle because we are
   // going to use it in the sampler thread. Using GetThreadHandle() will
   // not work in this case. We're using OpenThread because DuplicateHandle
   // for some reason doesn't work in Chrome's sandbox.
   PlatformData(int aThreadId) : profiled_thread_(OpenThread(THREAD_GET_CONTEXT |
                                                THREAD_SUSPEND_RESUME |
rename from tools/profiler/platform.cpp
rename to tools/profiler/core/platform.cpp
--- a/tools/profiler/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -14,17 +14,17 @@
 #include "GeckoProfiler.h"
 #ifndef SPS_STANDALONE
 #include "ProfilerIOInterposeObserver.h"
 #include "mozilla/StaticPtr.h"
 #endif
 #include "mozilla/ThreadLocal.h"
 #include "mozilla/TimeStamp.h"
 #include "PseudoStack.h"
-#include "TableTicker.h"
+#include "GeckoSampler.h"
 #ifndef SPS_STANDALONE
 #include "nsIObserverService.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsXULAppAPI.h"
 #include "nsProfilerStartParams.h"
 #include "mozilla/Services.h"
 #include "nsThreadUtils.h"
@@ -33,23 +33,23 @@
 
 #if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
   #include "AndroidBridge.h"
 #endif
 
 #ifndef SPS_STANDALONE
 #if defined(SPS_PLAT_amd64_linux) || defined(SPS_PLAT_x86_linux)
 # define USE_LUL_STACKWALK
-# include "LulMain.h"
-# include "platform-linux-lul.h"
+# include "lul/LulMain.h"
+# include "lul/platform-linux-lul.h"
 #endif
 #endif
 
 mozilla::ThreadLocal<PseudoStack *> tlsPseudoStack;
-mozilla::ThreadLocal<TableTicker *> tlsTicker;
+mozilla::ThreadLocal<GeckoSampler *> tlsTicker;
 mozilla::ThreadLocal<void *> tlsStackTop;
 // We need to track whether we've been initialized otherwise
 // we end up using tlsStack without initializing it.
 // Because tlsStack is totally opaque to us we can't reuse
 // it as the flag itself.
 bool stack_key_initialized;
 
 mozilla::TimeStamp   sLastTracerEvent; // is raced on
@@ -78,17 +78,17 @@ const char* PROFILER_FEATURES = "MOZ_PRO
 // Values harvested from env vars, that control the profiler.
 static int sUnwindInterval;   /* in milliseconds */
 static int sUnwindStackScan;  /* max # of dubious frames allowed */
 static int sProfileEntries;   /* how many entries do we store? */
 
 std::vector<ThreadInfo*>* Sampler::sRegisteredThreads = nullptr;
 mozilla::UniquePtr< ::Mutex> Sampler::sRegisteredThreadsMutex;
 
-TableTicker* Sampler::sActiveSampler;
+GeckoSampler* Sampler::sActiveSampler;
 
 #ifndef SPS_STANDALONE
 static mozilla::StaticAutoPtr<mozilla::ProfilerIOInterposeObserver>
                                                             sInterposeObserver;
 #endif
 
 // The name that identifies the gecko thread for calls to
 // profiler_register_thread.
@@ -124,53 +124,16 @@ void Sampler::Shutdown() {
   // Delete the sLUL object, if it actually got created.
   if (sLUL) {
     delete sLUL;
     sLUL = nullptr;
   }
 #endif
 }
 
-ThreadInfo::ThreadInfo(const char* aName, int aThreadId,
-                       bool aIsMainThread, PseudoStack* aPseudoStack,
-                       void* aStackTop)
-  : mName(strdup(aName))
-  , mThreadId(aThreadId)
-  , mIsMainThread(aIsMainThread)
-  , mPseudoStack(aPseudoStack)
-  , mPlatformData(Sampler::AllocPlatformData(aThreadId))
-  , mProfile(nullptr)
-  , mStackTop(aStackTop)
-  , mPendingDelete(false)
-{
-#ifndef SPS_STANDALONE
-  mThread = NS_GetCurrentThread();
-#endif
-}
-
-ThreadInfo::~ThreadInfo() {
-  free(mName);
-
-  if (mProfile)
-    delete mProfile;
-
-  Sampler::FreePlatformData(mPlatformData);
-}
-
-void
-ThreadInfo::SetPendingDelete()
-{
-  mPendingDelete = true;
-  // We don't own the pseudostack so disconnect it.
-  mPseudoStack = nullptr;
-  if (mProfile) {
-    mProfile->SetPendingDelete();
-  }
-}
-
 StackOwningThreadInfo::StackOwningThreadInfo(const char* aName, int aThreadId,
                                              bool aIsMainThread,
                                              PseudoStack* aPseudoStack,
                                              void* aStackTop)
   : ThreadInfo(aName, aThreadId, aIsMainThread, aPseudoStack, aStackTop)
 {
   aPseudoStack->ref();
 }
@@ -542,17 +505,17 @@ void mozilla_sampler_init(void* stackTop
 void mozilla_sampler_shutdown()
 {
   sInitCount--;
 
   if (sInitCount > 0)
     return;
 
   // Save the profile on shutdown if requested.
-  TableTicker *t = tlsTicker.get();
+  GeckoSampler *t = tlsTicker.get();
   if (t) {
     const char *val = getenv("MOZ_PROFILER_SHUTDOWN");
     if (val) {
       std::ofstream stream;
       stream.open(val);
       if (stream.is_open()) {
         t->ToStreamAsJSON(stream);
         stream.close();
@@ -574,63 +537,63 @@ void mozilla_sampler_shutdown()
 
   PseudoStack *stack = tlsPseudoStack.get();
   stack->deref();
   tlsPseudoStack.set(nullptr);
 }
 
 void mozilla_sampler_save()
 {
-  TableTicker *t = tlsTicker.get();
+  GeckoSampler *t = tlsTicker.get();
   if (!t) {
     return;
   }
 
   t->RequestSave();
   // We're on the main thread already so we don't
   // have to wait to handle the save request.
   t->HandleSaveRequest();
 }
 
 mozilla::UniquePtr<char[]> mozilla_sampler_get_profile(double aSinceTime)
 {
-  TableTicker *t = tlsTicker.get();
+  GeckoSampler *t = tlsTicker.get();
   if (!t) {
     return nullptr;
   }
 
   return t->ToJSON(aSinceTime);
 }
 
 #ifndef SPS_STANDALONE
 JSObject *mozilla_sampler_get_profile_data(JSContext *aCx, double aSinceTime)
 {
-  TableTicker *t = tlsTicker.get();
+  GeckoSampler *t = tlsTicker.get();
   if (!t) {
     return nullptr;
   }
 
   return t->ToJSObject(aCx, aSinceTime);
 }
 
 void mozilla_sampler_get_profile_data_async(double aSinceTime,
                                             mozilla::dom::Promise* aPromise)
 {
-  TableTicker *t = tlsTicker.get();
+  GeckoSampler *t = tlsTicker.get();
   if (NS_WARN_IF(!t)) {
     return;
   }
 
   t->ToJSObjectAsync(aSinceTime, aPromise);
 }
 #endif
 
 void mozilla_sampler_save_profile_to_file(const char* aFilename)
 {
-  TableTicker *t = tlsTicker.get();
+  GeckoSampler *t = tlsTicker.get();
   if (!t) {
     return;
   }
 
   std::ofstream stream;
   stream.open(aFilename);
   if (stream.is_open()) {
     t->ToStreamAsJSON(stream);
@@ -697,17 +660,17 @@ void mozilla_sampler_get_buffer_info(uin
 {
   *aCurrentPosition = 0;
   *aTotalSize = 0;
   *aGeneration = 0;
 
   if (!stack_key_initialized)
     return;
 
-  TableTicker *t = tlsTicker.get();
+  GeckoSampler *t = tlsTicker.get();
   if (!t)
     return;
 
   t->GetBufferInfo(aCurrentPosition, aTotalSize, aGeneration);
 }
 
 // Values are only honored on the first start
 void mozilla_sampler_start(int aProfileEntries, double aInterval,
@@ -727,18 +690,18 @@ void mozilla_sampler_start(int aProfileE
 
   /* If the entry count was set using env vars, use that, too: */
   if (sProfileEntries > 0)
     aProfileEntries = sProfileEntries;
 
   // Reset the current state if the profiler is running
   profiler_stop();
 
-  TableTicker* t;
-  t = new TableTicker(aInterval ? aInterval : PROFILE_DEFAULT_INTERVAL,
+  GeckoSampler* t;
+  t = new GeckoSampler(aInterval ? aInterval : PROFILE_DEFAULT_INTERVAL,
                       aProfileEntries ? aProfileEntries : PROFILE_DEFAULT_ENTRY,
                       aFeatures, aFeatureCount,
                       aThreadNameFilters, aFilterCount);
 
   tlsTicker.set(t);
   t->Start();
   if (t->ProfileJS() || t->InPrivacyMode()) {
       ::MutexAutoLock lock(*Sampler::sRegisteredThreadsMutex);
@@ -822,17 +785,17 @@ void mozilla_sampler_start(int aProfileE
 
 void mozilla_sampler_stop()
 {
   LOG("BEGIN mozilla_sampler_stop");
 
   if (!stack_key_initialized)
     return;
 
-  TableTicker *t = tlsTicker.get();
+  GeckoSampler *t = tlsTicker.get();
   if (!t) {
     LOG("END   mozilla_sampler_stop-early");
     return;
   }
 
   bool disableJS = t->ProfileJS();
 
   t->Stop();
@@ -1032,17 +995,17 @@ ProfilerBacktrace* mozilla_sampler_get_b
     return nullptr;
   }
 
   // Don't capture a stack if we don't want to include personal information
   if (profiler_in_privacy_mode()) {
     return nullptr;
   }
 
-  TableTicker* t = tlsTicker.get();
+  GeckoSampler* t = tlsTicker.get();
   if (!t) {
     return nullptr;
   }
 
   return new ProfilerBacktrace(t->GetBacktrace());
 }
 
 void mozilla_sampler_free_backtrace(ProfilerBacktrace* aBacktrace)
@@ -1152,10 +1115,8 @@ class OSXMutex : public ::Mutex {
 mozilla::UniquePtr< ::Mutex> OS::CreateMutex(const char* aDesc) {
   return mozilla::MakeUnique<GeckoMutex>(aDesc);
 }
 
 #endif
 
 // END externally visible functions
 ////////////////////////////////////////////////////////////////////////
-
-
rename from tools/profiler/platform.h
rename to tools/profiler/core/platform.h
--- a/tools/profiler/platform.h
+++ b/tools/profiler/core/platform.h
@@ -53,16 +53,27 @@
 #endif
 #include "mozilla/TimeStamp.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/unused.h"
 #include "PlatformMacros.h"
 #include "v8-support.h"
 #include <vector>
 
+// We need a definition of gettid(), but glibc doesn't provide a
+// wrapper for it.
+#if defined(__GLIBC__)
+#include <unistd.h>
+#include <sys/syscall.h>
+static inline pid_t gettid()
+{
+  return (pid_t) syscall(SYS_gettid);
+}
+#endif
+
 #ifdef XP_WIN
 #include <windows.h>
 #endif
 
 #define ASSERT(a) MOZ_ASSERT(a)
 
 bool moz_profiler_verbose();
 
@@ -91,16 +102,18 @@ bool moz_profiler_verbose();
     } while (0)
 
 #endif
 
 #if defined(XP_MACOSX) || defined(XP_WIN) || defined(XP_LINUX)
 #define ENABLE_SPS_LEAF_DATA
 #endif
 
+typedef int32_t Atomic32;
+
 extern mozilla::TimeStamp sStartTime;
 
 typedef uint8_t* Address;
 
 // ----------------------------------------------------------------------------
 // Mutex
 //
 // Mutexes are used for serializing access to non-reentrant sections of code.
@@ -295,17 +308,17 @@ class TickSample {
   ThreadProfile* threadProfile;
   mozilla::TimeStamp timestamp;
   int64_t rssMemory;
   int64_t ussMemory;
 };
 
 class ThreadInfo;
 class PlatformData;
-class TableTicker;
+class GeckoSampler;
 class SyncProfile;
 class Sampler {
  public:
   // Initialize sampler.
   explicit Sampler(double interval, bool profiling, int entrySize);
   virtual ~Sampler();
 
   double interval() const { return interval_; }
@@ -365,18 +378,18 @@ class Sampler {
                                     PseudoStack* aPseudoStack,
                                     bool aIsMainThread, void* stackTop);
   static void UnregisterCurrentThread();
 
   static void Startup();
   // Should only be called on shutdown
   static void Shutdown();
 
-  static TableTicker* GetActiveSampler() { return sActiveSampler; }
-  static void SetActiveSampler(TableTicker* sampler) { sActiveSampler = sampler; }
+  static GeckoSampler* GetActiveSampler() { return sActiveSampler; }
+  static void SetActiveSampler(GeckoSampler* sampler) { sActiveSampler = sampler; }
 
   static mozilla::UniquePtr<Mutex> sRegisteredThreadsMutex;
 
   static bool CanNotifyObservers() {
 #ifdef MOZ_WIDGET_GONK
     // We use profile.sh on b2g to manually select threads and options per process.
     return false;
 #elif defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
@@ -385,17 +398,17 @@ class Sampler {
 #else
     MOZ_ASSERT(NS_IsMainThread());
     return true;
 #endif
   }
 
  protected:
   static std::vector<ThreadInfo*>* sRegisteredThreads;
-  static TableTicker* sActiveSampler;
+  static GeckoSampler* sActiveSampler;
 
  private:
   void SetActive(bool value) { NoBarrier_Store(&active_, value); }
 
   const double interval_;
   const bool profiling_;
   Atomic32 paused_;
   Atomic32 active_;
@@ -406,63 +419,9 @@ class Sampler {
   bool signal_handler_installed_;
   struct sigaction old_sigprof_signal_handler_;
   struct sigaction old_sigsave_signal_handler_;
   bool signal_sender_launched_;
   pthread_t signal_sender_thread_;
 #endif
 };
 
-class ThreadInfo {
- public:
-  ThreadInfo(const char* aName, int aThreadId, bool aIsMainThread, PseudoStack* aPseudoStack, void* aStackTop);
-
-  virtual ~ThreadInfo();
-
-  const char* Name() const { return mName; }
-  int ThreadId() const { return mThreadId; }
-
-  bool IsMainThread() const { return mIsMainThread; }
-  PseudoStack* Stack() const { return mPseudoStack; }
-
-  void SetProfile(ThreadProfile* aProfile) { mProfile = aProfile; }
-  ThreadProfile* Profile() const { return mProfile; }
-
-  PlatformData* GetPlatformData() const { return mPlatformData; }
-  void* StackTop() const { return mStackTop; }
-
-  virtual void SetPendingDelete();
-  bool IsPendingDelete() const { return mPendingDelete; }
-
-#ifdef MOZ_NUWA_PROCESS
-  void SetThreadId(int aThreadId) { mThreadId = aThreadId; }
-#endif
-
-#ifndef SPS_STANDALONE
-  /**
-   * May be null for the main thread if the profiler was started during startup
-   */
-  nsIThread* GetThread() const { return mThread.get(); }
-#endif
- private:
-  char* mName;
-  int mThreadId;
-  const bool mIsMainThread;
-  PseudoStack* mPseudoStack;
-  PlatformData* mPlatformData;
-  ThreadProfile* mProfile;
-  void* const mStackTop;
-#ifndef SPS_STANDALONE
-  nsCOMPtr<nsIThread> mThread;
-#endif
-  bool mPendingDelete;
-};
-
-// Just like ThreadInfo, but owns a reference to the PseudoStack.
-class StackOwningThreadInfo : public ThreadInfo {
- public:
-  StackOwningThreadInfo(const char* aName, int aThreadId, bool aIsMainThread, PseudoStack* aPseudoStack, void* aStackTop);
-  virtual ~StackOwningThreadInfo();
-
-  virtual void SetPendingDelete();
-};
-
 #endif /* ndef TOOLS_PLATFORM_H_ */
rename from tools/profiler/shared-libraries-linux.cc
rename to tools/profiler/core/shared-libraries-linux.cc
rename from tools/profiler/shared-libraries-macos.cc
rename to tools/profiler/core/shared-libraries-macos.cc
rename from tools/profiler/shared-libraries-win32.cc
rename to tools/profiler/core/shared-libraries-win32.cc
rename from tools/profiler/shim_mac_dump_syms.h
rename to tools/profiler/core/shim_mac_dump_syms.h
rename from tools/profiler/shim_mac_dump_syms.mm
rename to tools/profiler/core/shim_mac_dump_syms.mm
rename from tools/profiler/v8-support.h
rename to tools/profiler/core/v8-support.h
rename from tools/profiler/ProfileGatherer.cpp
rename to tools/profiler/gecko/ProfileGatherer.cpp
--- a/tools/profiler/ProfileGatherer.cpp
+++ b/tools/profiler/gecko/ProfileGatherer.cpp
@@ -1,25 +1,25 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ProfileGatherer.h"
 #include "mozilla/Services.h"
 #include "nsIObserverService.h"
-#include "TableTicker.h"
+#include "GeckoSampler.h"
 
 using mozilla::dom::AutoJSAPI;
 using mozilla::dom::Promise;
 
 namespace mozilla {
 
 NS_IMPL_ISUPPORTS0(ProfileGatherer)
 
-ProfileGatherer::ProfileGatherer(TableTicker* aTicker,
+ProfileGatherer::ProfileGatherer(GeckoSampler* aTicker,
                                  double aSinceTime,
                                  Promise* aPromise)
   : mPromise(aPromise)
   , mTicker(aTicker)
   , mSinceTime(aSinceTime)
   , mPendingProfiles(0)
 {
 }
@@ -69,17 +69,17 @@ void
 ProfileGatherer::Finish()
 {
   MOZ_ASSERT(NS_IsMainThread());
   UniquePtr<char[]> buf = mTicker->ToJSON(mSinceTime);
 
   AutoJSAPI jsapi;
   if (NS_WARN_IF(!jsapi.Init(mPromise->GlobalJSObject()))) {
     // We're really hosed if we can't get a JS context for some reason.
-    // We'll tell the TableTicker that we've gathered the profile just
+    // We'll tell the GeckoSampler that we've gathered the profile just
     // so that it can drop the reference to this ProfileGatherer and maybe
     // the user can try again.
     mTicker->ProfileGathered();
     return;
   }
 
   JSContext* cx = jsapi.cx();
 
rename from tools/profiler/Profiler.jsm
rename to tools/profiler/gecko/Profiler.jsm
rename from tools/profiler/ProfilerIOInterposeObserver.cpp
rename to tools/profiler/gecko/ProfilerIOInterposeObserver.cpp
rename from tools/profiler/ProfilerIOInterposeObserver.h
rename to tools/profiler/gecko/ProfilerIOInterposeObserver.h
rename from tools/profiler/SaveProfileTask.cpp
rename to tools/profiler/gecko/SaveProfileTask.cpp
rename from tools/profiler/SaveProfileTask.h
rename to tools/profiler/gecko/SaveProfileTask.h
rename from tools/profiler/ThreadResponsiveness.cpp
rename to tools/profiler/gecko/ThreadResponsiveness.cpp
rename from tools/profiler/ThreadResponsiveness.h
rename to tools/profiler/gecko/ThreadResponsiveness.h
rename from tools/profiler/local_debug_info_symbolizer.cc
rename to tools/profiler/gecko/local_debug_info_symbolizer.cc
rename from tools/profiler/local_debug_info_symbolizer.h
rename to tools/profiler/gecko/local_debug_info_symbolizer.h
rename from tools/profiler/nsIProfileSaveEvent.idl
rename to tools/profiler/gecko/nsIProfileSaveEvent.idl
rename from tools/profiler/nsIProfiler.idl
rename to tools/profiler/gecko/nsIProfiler.idl
rename from tools/profiler/nsProfiler.cpp
rename to tools/profiler/gecko/nsProfiler.cpp
rename from tools/profiler/nsProfiler.h
rename to tools/profiler/gecko/nsProfiler.h
rename from tools/profiler/nsProfilerCIID.h
rename to tools/profiler/gecko/nsProfilerCIID.h
rename from tools/profiler/nsProfilerFactory.cpp
rename to tools/profiler/gecko/nsProfilerFactory.cpp
rename from tools/profiler/nsProfilerStartParams.cpp
rename to tools/profiler/gecko/nsProfilerStartParams.cpp
rename from tools/profiler/nsProfilerStartParams.h
rename to tools/profiler/gecko/nsProfilerStartParams.h
rename from tools/profiler/AutoObjectMapper.cpp
rename to tools/profiler/lul/AutoObjectMapper.cpp
rename from tools/profiler/AutoObjectMapper.h
rename to tools/profiler/lul/AutoObjectMapper.h
rename from tools/profiler/LulCommon.cpp
rename to tools/profiler/lul/LulCommon.cpp
rename from tools/profiler/LulCommonExt.h
rename to tools/profiler/lul/LulCommonExt.h
rename from tools/profiler/LulDwarf.cpp
rename to tools/profiler/lul/LulDwarf.cpp
rename from tools/profiler/LulDwarfExt.h
rename to tools/profiler/lul/LulDwarfExt.h
rename from tools/profiler/LulDwarfInt.h
rename to tools/profiler/lul/LulDwarfInt.h
rename from tools/profiler/LulDwarfSummariser.cpp
rename to tools/profiler/lul/LulDwarfSummariser.cpp
rename from tools/profiler/LulDwarfSummariser.h
rename to tools/profiler/lul/LulDwarfSummariser.h
rename from tools/profiler/LulElf.cpp
rename to tools/profiler/lul/LulElf.cpp
rename from tools/profiler/LulElfExt.h
rename to tools/profiler/lul/LulElfExt.h
rename from tools/profiler/LulElfInt.h
rename to tools/profiler/lul/LulElfInt.h
rename from tools/profiler/LulMain.cpp
rename to tools/profiler/lul/LulMain.cpp
--- a/tools/profiler/LulMain.cpp
+++ b/tools/profiler/lul/LulMain.cpp
@@ -24,17 +24,16 @@
 
 #include "LulMainInt.h"
 
 #include "platform-linux-lul.h"  // for gettid()
 
 // Set this to 1 for verbose logging
 #define DEBUG_MAIN 0
 
-
 namespace lul {
 
 using std::string;
 using std::vector;
 using std::pair;
 using mozilla::DebugOnly;
 
 
rename from tools/profiler/LulMain.h
rename to tools/profiler/lul/LulMain.h
rename from tools/profiler/LulMainInt.h
rename to tools/profiler/lul/LulMainInt.h
rename from tools/profiler/LulPlatformMacros.h
rename to tools/profiler/lul/LulPlatformMacros.h
rename from tools/profiler/platform-linux-lul.cpp
rename to tools/profiler/lul/platform-linux-lul.cpp
rename from tools/profiler/platform-linux-lul.h
rename to tools/profiler/lul/platform-linux-lul.h
--- a/tools/profiler/platform-linux-lul.h
+++ b/tools/profiler/lul/platform-linux-lul.h
@@ -1,33 +1,24 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZ_PLATFORM_LINUX_LUL_H
 #define MOZ_PLATFORM_LINUX_LUL_H
 
+#include "platform.h"
+
 // Find out, in a platform-dependent way, where the code modules got
 // mapped in the process' virtual address space, and get |aLUL| to
 // load unwind info for them.
 void
 read_procmaps(lul::LUL* aLUL);
 
 // LUL needs a callback for its logging sink.
 void
 logging_sink_for_LUL(const char* str);
 
-// We need a definition of gettid(), but glibc doesn't provide a
-// wrapper for it.
-#if defined(__GLIBC__)
-#include <unistd.h>
-#include <sys/syscall.h>
-static inline pid_t gettid()
-{
-  return (pid_t) syscall(SYS_gettid);
-}
-#endif
-
 // A singleton instance of the library.
 extern lul::LUL* sLUL;
 
 #endif /* ndef MOZ_PLATFORM_LINUX_LUL_H */
--- a/tools/profiler/moz.build
+++ b/tools/profiler/moz.build
@@ -4,92 +4,97 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 if CONFIG['MOZ_ENABLE_PROFILER_SPS']:
     FAIL_ON_WARNINGS = True
 
     XPIDL_MODULE = 'profiler'
     XPIDL_SOURCES += [
-        'nsIProfiler.idl',
-        'nsIProfileSaveEvent.idl',
+        'gecko/nsIProfiler.idl',
+        'gecko/nsIProfileSaveEvent.idl',
     ]
     EXPORTS += [
-        'GeckoProfilerFunc.h',
-        'GeckoProfilerImpl.h',
-        'ProfilerBacktrace.h',
-        'ProfilerMarkers.h',
-        'PseudoStack.h',
-        'shared-libraries.h',
+        'public/GeckoProfilerFunc.h',
+        'public/GeckoProfilerImpl.h',
+        'public/ProfilerBacktrace.h',
+        'public/ProfilerMarkers.h',
+        'public/PseudoStack.h',
+        'public/shared-libraries.h',
     ]
     EXPORTS.mozilla += [
-        'ProfileGatherer.h',
+        'public/ProfileGatherer.h',
     ]
     EXTRA_JS_MODULES += [
-        'Profiler.jsm',
+        'gecko/Profiler.jsm',
     ]
     UNIFIED_SOURCES += [
-        'nsProfiler.cpp',
-        'nsProfilerFactory.cpp',
-        'nsProfilerStartParams.cpp',
-        'platform.cpp',
-        'ProfileEntry.cpp',
-        'ProfileGatherer.cpp',
-        'ProfileJSONWriter.cpp',
-        'ProfilerBacktrace.cpp',
-        'ProfilerIOInterposeObserver.cpp',
-        'ProfilerMarkers.cpp',
-        'SaveProfileTask.cpp',
-        'SyncProfile.cpp',
-        'TableTicker.cpp',
-        'ThreadResponsiveness.cpp',
+        'core/GeckoSampler.cpp',
+        'core/platform.cpp',
+        'core/ProfileBuffer.cpp',
+        'core/ProfileEntry.cpp',
+        'core/ProfileJSONWriter.cpp',
+        'core/ProfilerBacktrace.cpp',
+        'core/ProfilerMarkers.cpp',
+        'core/SyncProfile.cpp',
+        'core/ThreadInfo.cpp',
+        'core/ThreadProfile.cpp',
+        'gecko/nsProfiler.cpp',
+        'gecko/nsProfilerFactory.cpp',
+        'gecko/nsProfilerStartParams.cpp',
+        'gecko/ProfileGatherer.cpp',
+        'gecko/ProfilerIOInterposeObserver.cpp',
+        'gecko/SaveProfileTask.cpp',
+        'gecko/ThreadResponsiveness.cpp',
     ]
 
     # This file cannot be built in unified mode because of name clashes with mozglue headers on Android.
     SOURCES += [
-        'local_debug_info_symbolizer.cc',
+        'gecko/local_debug_info_symbolizer.cc',
     ]
 
     if CONFIG['OS_TARGET'] in ('Android', 'Linux'):
         UNIFIED_SOURCES += [
-            'AutoObjectMapper.cpp',
-            'LulCommon.cpp',
-            'LulDwarf.cpp',
-            'LulDwarfSummariser.cpp',
-            'LulElf.cpp',
-            'LulMain.cpp',
-            'platform-linux-lul.cpp',
+            'lul/AutoObjectMapper.cpp',
+            'lul/LulCommon.cpp',
+            'lul/LulDwarf.cpp',
+            'lul/LulDwarfSummariser.cpp',
+            'lul/LulElf.cpp',
+            'lul/LulMain.cpp',
+            'lul/platform-linux-lul.cpp',
         ]
         # These files cannot be built in unified mode because of name clashes with mozglue headers on Android.
         SOURCES += [
-            'platform-linux.cc',
-            'shared-libraries-linux.cc',
+            'core/platform-linux.cc',
+            'core/shared-libraries-linux.cc',
         ]
         if CONFIG['CPU_ARCH'] == 'arm':
             SOURCES += [
-                'EHABIStackWalk.cpp',
+                'core/EHABIStackWalk.cpp',
             ]
     elif CONFIG['OS_TARGET'] == 'Darwin':
         UNIFIED_SOURCES += [
-            'platform-macos.cc',
-            'shared-libraries-macos.cc',
-            'shim_mac_dump_syms.mm',
+            'core/platform-macos.cc',
+            'core/shared-libraries-macos.cc',
+            'core/shim_mac_dump_syms.mm',
         ]
     elif CONFIG['OS_TARGET'] == 'WINNT':
         SOURCES += [
-            'IntelPowerGadget.cpp',
-            'platform-win32.cc',
-            'shared-libraries-win32.cc',
+            'core/IntelPowerGadget.cpp',
+            'core/platform-win32.cc',
+            'core/shared-libraries-win32.cc',
         ]
 
     LOCAL_INCLUDES += [
         '/docshell/base',
         '/ipc/chromium/src',
         '/mozglue/linker',
         '/toolkit/crashreporter/google-breakpad/src',
+        '/tools/profiler/core/',
+        '/tools/profiler/gecko/',
         '/xpcom/base',
     ]
 
     # We need access to Breakpad's getcontext(3) which is suitable for Android
     if CONFIG['OS_TARGET'] == 'Android':
         LOCAL_INCLUDES += [
             '/toolkit/crashreporter/google-breakpad/src/common/android/include',
         ]
@@ -101,23 +106,23 @@ if CONFIG['MOZ_ENABLE_PROFILER_SPS']:
         DIRS += ['tests/gtest']
 
     if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and (CONFIG['ANDROID_VERSION'] <= '17' or CONFIG['ANDROID_VERSION'] >= '21'):
         DEFINES['ELFSIZE'] = 32
 
     FINAL_LIBRARY = 'xul'
 
 EXPORTS += [
-    'GeckoProfiler.h',
+    'public/GeckoProfiler.h',
 ]
 
 if CONFIG['MOZ_TASK_TRACER']:
     EXPORTS += [
-        'GeckoTaskTracer.h',
-        'GeckoTaskTracerImpl.h',
-        'TracedTaskCommon.h',
+        'public/GeckoTaskTracer.h',
+        'public/GeckoTaskTracerImpl.h',
+        'public/TracedTaskCommon.h',
     ]
     UNIFIED_SOURCES += [
-        'GeckoTaskTracer.cpp',
-        'TracedTaskCommon.cpp',
+        'tasktracer/GeckoTaskTracer.cpp',
+        'tasktracer/TracedTaskCommon.cpp',
     ]
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell.ini']
rename from tools/profiler/GeckoProfiler.h
rename to tools/profiler/public/GeckoProfiler.h
rename from tools/profiler/GeckoProfilerFunc.h
rename to tools/profiler/public/GeckoProfilerFunc.h
rename from tools/profiler/GeckoProfilerImpl.h
rename to tools/profiler/public/GeckoProfilerImpl.h
--- a/tools/profiler/GeckoProfilerImpl.h
+++ b/tools/profiler/public/GeckoProfilerImpl.h
@@ -33,24 +33,24 @@
 #undef slots
 #endif
 
 // Make sure that we can use std::min here without the Windows headers messing with us.
 #ifdef min
 #undef min
 #endif
 
-class TableTicker;
+class GeckoSampler;
 
 namespace mozilla {
 class TimeStamp;
 }
 
 extern mozilla::ThreadLocal<PseudoStack *> tlsPseudoStack;
-extern mozilla::ThreadLocal<TableTicker *> tlsTicker;
+extern mozilla::ThreadLocal<GeckoSampler *> tlsTicker;
 extern mozilla::ThreadLocal<void *> tlsStackTop;
 extern bool stack_key_initialized;
 
 #ifndef SAMPLE_FUNCTION_NAME
 # ifdef __GNUC__
 #  define SAMPLE_FUNCTION_NAME __FUNCTION__
 # elif defined(_MSC_VER)
 #  define SAMPLE_FUNCTION_NAME __FUNCTION__
rename from tools/profiler/ProfileGatherer.h
rename to tools/profiler/public/ProfileGatherer.h
--- a/tools/profiler/ProfileGatherer.h
+++ b/tools/profiler/public/ProfileGatherer.h
@@ -2,37 +2,37 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZ_PROFILE_GATHERER_H
 #define MOZ_PROFILE_GATHERER_H
 
 #include "mozilla/dom/Promise.h"
 
-class TableTicker;
+class GeckoSampler;
 
 namespace mozilla {
 
 class ProfileGatherer final : public nsISupports
 {
 public:
   NS_DECL_ISUPPORTS
 
-  ProfileGatherer(TableTicker* aTicker,
+  ProfileGatherer(GeckoSampler* aTicker,
                   double aSinceTime,
                   mozilla::dom::Promise* aPromise);
   void WillGatherOOPProfile();
   void GatheredOOPProfile();
   void Start();
 
 private:
   ~ProfileGatherer() {};
   void Finish();
 
   nsRefPtr<mozilla::dom::Promise> mPromise;
-  TableTicker* mTicker;
+  GeckoSampler* mTicker;
   double mSinceTime;
   uint32_t mPendingProfiles;
 };
 
 } // namespace mozilla
 
 #endif
rename from tools/profiler/ProfilerBacktrace.h
rename to tools/profiler/public/ProfilerBacktrace.h
rename from tools/profiler/ProfilerMarkers.h
rename to tools/profiler/public/ProfilerMarkers.h
rename from tools/profiler/PseudoStack.h
rename to tools/profiler/public/PseudoStack.h
rename from tools/profiler/shared-libraries.h
rename to tools/profiler/public/shared-libraries.h
rename from tools/profiler/GeckoTaskTracer.cpp
rename to tools/profiler/tasktracer/GeckoTaskTracer.cpp
rename from tools/profiler/GeckoTaskTracer.h
rename to tools/profiler/tasktracer/GeckoTaskTracer.h
rename from tools/profiler/GeckoTaskTracerImpl.h
rename to tools/profiler/tasktracer/GeckoTaskTracerImpl.h
rename from tools/profiler/SourceEventTypeMap.h
rename to tools/profiler/tasktracer/SourceEventTypeMap.h
rename from tools/profiler/TracedTaskCommon.cpp
rename to tools/profiler/tasktracer/TracedTaskCommon.cpp
rename from tools/profiler/TracedTaskCommon.h
rename to tools/profiler/tasktracer/TracedTaskCommon.h
--- a/tools/profiler/tests/gtest/ThreadProfileTest.cpp
+++ b/tools/profiler/tests/gtest/ThreadProfileTest.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gtest/gtest.h"
 
 #include "ProfileEntry.h"
+#include "ThreadProfile.h"
 
 // Make sure we can initialize our ThreadProfile
 TEST(ThreadProfile, Initialization) {
   PseudoStack* stack = PseudoStack::create();
   Thread::tid_t tid = 1000;
   ThreadInfo info("testThread", tid, true, stack, nullptr);
   mozilla::RefPtr<ProfileBuffer> pb = new ProfileBuffer(10);
   ThreadProfile tp(&info, pb);
--- a/tools/profiler/tests/gtest/moz.build
+++ b/tools/profiler/tests/gtest/moz.build
@@ -7,17 +7,19 @@
 if CONFIG['OS_TARGET'] in ('Android', 'Linux'):
     UNIFIED_SOURCES += [
         'LulTest.cpp',
         'LulTestDwarf.cpp',
         'LulTestInfrastructure.cpp',
     ]
 
 LOCAL_INCLUDES += [
-    '/tools/profiler',
+    '/tools/profiler/core',
+    '/tools/profiler/gecko',
+    '/tools/profiler/lul',
 ]
 
 UNIFIED_SOURCES += [
     'ThreadProfileTest.cpp',
 ]
 
 FINAL_LIBRARY = 'xul-gtest'