/* 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 "Instruments.h"

#ifdef __APPLE__

#include "jsapi.h"
#include <dlfcn.h>
#include <CoreFoundation/CoreFoundation.h>

// There are now 2 paths to the DTPerformanceSession framework. We try to load
// the one contained in /Applications/Xcode.app first, falling back to the one
// contained in /Library/Developer/4.0/Instruments.
#define DTPerformanceLibraryPath "/Applications/Xcode.app/Contents/Developer/Library/Frameworks/DTPerformanceSession.framework/Versions/Current/DTPerformanceSession"
#define OldDTPerformanceLibraryPath "/Library/Developer/4.0/Instruments/Frameworks/DTPerformanceSession.framework/Versions/Current/DTPerformanceSession"

extern "C" {

typedef CFTypeRef DTPerformanceSessionRef;

#define DTPerformanceSession_TimeProfiler               "com.apple.instruments.dtps.timeprofiler"
// DTPerformanceSession_Option_SamplingInterval is measured in microseconds
#define DTPerformanceSession_Option_SamplingInterval    "com.apple.instruments.dtps.option.samplinginterval"

typedef void (*dtps_errorcallback_t)(CFStringRef, CFErrorRef);
typedef DTPerformanceSessionRef (*DTPerformanceSessionCreateFunction)(CFStringRef, CFStringRef, CFDictionaryRef, CFErrorRef*);
typedef bool (*DTPerformanceSessionAddInstrumentFunction)(DTPerformanceSessionRef, CFStringRef, CFDictionaryRef, dtps_errorcallback_t, CFErrorRef*);
typedef bool (*DTPerformanceSessionIsRecordingFunction)(DTPerformanceSessionRef);
typedef bool (*DTPerformanceSessionStartFunction)(DTPerformanceSessionRef, CFArrayRef, CFErrorRef*);
typedef bool (*DTPerformanceSessionStopFunction)(DTPerformanceSessionRef, CFArrayRef, CFErrorRef*);
typedef bool (*DTPerformanceSessionSaveFunction)(DTPerformanceSessionRef, CFStringRef, CFErrorRef*);

} // extern "C"

namespace Instruments {

static const int kSamplingInterval = 20; // microseconds

template<typename T>
class AutoReleased
{
public:
  AutoReleased(T aTypeRef) : mTypeRef(aTypeRef)
  {
  }
  ~AutoReleased()
  {
    if (mTypeRef) {
      CFRelease(mTypeRef);
    }
  }

  operator T()
  {
    return mTypeRef;
  }

private:
  T mTypeRef;
};

#define DTPERFORMANCE_SYMBOLS \
  SYMBOL(DTPerformanceSessionCreate) \
  SYMBOL(DTPerformanceSessionAddInstrument) \
  SYMBOL(DTPerformanceSessionIsRecording) \
  SYMBOL(DTPerformanceSessionStart) \
  SYMBOL(DTPerformanceSessionStop) \
  SYMBOL(DTPerformanceSessionSave)

#define SYMBOL(_sym) \
  _sym##Function _sym = NULL;

DTPERFORMANCE_SYMBOLS

#undef SYMBOL

void*
LoadDTPerformanceLibraries(bool dontLoad)
{
  int flags = RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE;
  if (dontLoad) {
    flags |= RTLD_NOLOAD;
  }

  void *DTPerformanceLibrary = dlopen(DTPerformanceLibraryPath, flags);
  if (!DTPerformanceLibrary) {
    DTPerformanceLibrary = dlopen(OldDTPerformanceLibraryPath, flags);
  }
  return DTPerformanceLibrary;
}

bool
LoadDTPerformanceLibrary()
{
  void *DTPerformanceLibrary = LoadDTPerformanceLibraries(true);
  if (!DTPerformanceLibrary) {
    DTPerformanceLibrary = LoadDTPerformanceLibraries(false);
    if (!DTPerformanceLibrary) {
      return false;
    }
  }

#define SYMBOL(_sym) \
  _sym = reinterpret_cast<_sym##Function>(dlsym(DTPerformanceLibrary, #_sym)); \
  if (!_sym) { \
    dlclose(DTPerformanceLibrary); \
    DTPerformanceLibrary = NULL; \
    return false; \
  }

  DTPERFORMANCE_SYMBOLS

#undef SYMBOL

  dlclose(DTPerformanceLibrary);

  return true;
}

static DTPerformanceSessionRef gSession;

bool
Error(CFErrorRef error)
{
  if (gSession) {
    CFErrorRef unused = NULL;
    DTPerformanceSessionStop(gSession, NULL, &unused);
    CFRelease(gSession);
    gSession = NULL;
  }
#ifdef DEBUG
  AutoReleased<CFDataRef> data =
    CFStringCreateExternalRepresentation(NULL, CFErrorCopyDescription(error),
                                         kCFStringEncodingUTF8, '?');
  if (data != NULL) {
    printf("%.*s\n\n", (int)CFDataGetLength(data), CFDataGetBytePtr(data));
  }
#endif
  return false;
}

bool
Start()
{
  if (gSession) {
    return false;
  }

  if (!LoadDTPerformanceLibrary()) {
    return false;
  }

  AutoReleased<CFStringRef> process =
    CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), getpid());
  if (!process) {
    return false;
  }
  CFErrorRef error = NULL;
  gSession = DTPerformanceSessionCreate(NULL, process, NULL, &error);
  if (!gSession) {
    return Error(error);
  }

  AutoReleased<CFNumberRef> interval =
    CFNumberCreate(0, kCFNumberIntType, &kSamplingInterval);
  if (!interval) {
    return false;
  }
  CFStringRef keys[1] = { CFSTR(DTPerformanceSession_Option_SamplingInterval) };
  CFNumberRef values[1] = { interval };
  AutoReleased<CFDictionaryRef> options =
    CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys,
                       (const void**)values, 1, &kCFTypeDictionaryKeyCallBacks,
                       &kCFTypeDictionaryValueCallBacks);
  if (!options) {
    return false;
  }

  if (!DTPerformanceSessionAddInstrument(gSession,
                                         CFSTR(DTPerformanceSession_TimeProfiler),
                                         options, NULL, &error)) {
    return Error(error);
  }

  return Resume();
}

void
Pause()
{
  if (gSession && DTPerformanceSessionIsRecording(gSession)) {
    CFErrorRef error = NULL;
    if (!DTPerformanceSessionStop(gSession, NULL, &error)) {
      Error(error);
    }
  }
}

bool
Resume()
{
  if (!gSession) {
    return false;
  }

  CFErrorRef error = NULL;
  return DTPerformanceSessionStart(gSession, NULL, &error) ||
         Error(error);
}

void
Stop(const char* profileName)
{
  Pause();

  CFErrorRef error = NULL;
  AutoReleased<CFStringRef> name =
    CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s"), "/tmp/",
                             profileName ? profileName : "mozilla");
  if (!DTPerformanceSessionSave(gSession, name, &error)) {
    Error(error);
    return;
  }

  CFRelease(gSession);
  gSession = NULL;
}

} // namespace Instruments

#endif /* __APPLE__ */
