text: //-------------------------------------------------------------------------------------------------------
  // Copyright (C) Microsoft. All rights reserved.
  // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  //-------------------------------------------------------------------------------------------------------
  #include "RuntimeBasePch.h"
  
  #ifdef PROFILE_EXEC
  #include "Base\ScriptContextProfiler.h"
  
  namespace Js
  {
      ULONG
      ScriptContextProfiler::AddRef()
      {
          return refcount++;
      }
  
      ULONG
      ScriptContextProfiler::Release()
      {
          ULONG count = --refcount;
          if (count == 0)
          {
              if (recycler != nullptr && this->profiler == recycler->GetProfiler())
              {
                  recycler->SetProfiler(nullptr, nullptr);
              }
              NoCheckHeapDelete(this);
          }
          return count;
      }
  
      ScriptContextProfiler::ScriptContextProfiler() :
          refcount(1), profilerArena(nullptr), profiler(nullptr), backgroundRecyclerProfilerArena(nullptr), backgroundRecyclerProfiler(nullptr), recycler(nullptr), pageAllocator(nullptr), next(nullptr)
      {
      }
  
      void
      ScriptContextProfiler::Initialize(PageAllocator * pageAllocator, Recycler * recycler)
      {
          Assert(!IsInitialized());
          profilerArena = HeapNew(ArenaAllocator, L"Profiler", pageAllocator, Js::Throw::OutOfMemory);
          profiler = Anew(profilerArena, Profiler, profilerArena);
          if (recycler)
          {
              backgroundRecyclerProfilerArena = recycler->AddBackgroundProfilerArena();
              backgroundRecyclerProfiler = Anew(profilerArena, Profiler, backgroundRecyclerProfilerArena);
  
  #if DBG
              //backgroundRecyclerProfiler is allocated from background and its guaranteed to assert below if we don't disable thread access check.
              backgroundRecyclerProfiler->alloc->GetPageAllocator()->SetDisableThreadAccessCheck();
  #endif
  
              backgroundRecyclerProfiler->Begin(Js::AllPhase);
  
  #if DBG
              backgroundRecyclerProfiler->alloc->GetPageAllocator()->SetEnableThreadAccessCheck();
  #endif
          }
          profiler->Begin(Js::AllPhase);
  
          this->recycler = recycler;
      }
  
      void
      ScriptContextProfiler::ProfilePrint(Js::Phase phase)
      {
          if (!IsInitialized())
          {
              return;
          }
          profiler->End(Js::AllPhase);
          profiler->Print(phase);
          if (this->backgroundRecyclerProfiler)
          {
              this->backgroundRecyclerProfiler->End(Js::AllPhase);
              this->backgroundRecyclerProfiler->Print(phase);
              this->backgroundRecyclerProfiler->Begin(Js::AllPhase);
          }
          profiler->Begin(Js::AllPhase);
      }
  
      ScriptContextProfiler::~ScriptContextProfiler()
      {
          if (profilerArena)
          {
              HeapDelete(profilerArena);
          }
  
          if (recycler && backgroundRecyclerProfilerArena)
          {
  #if DBG
              //We are freeing from main thread, disable thread check assert.
              backgroundRecyclerProfilerArena->GetPageAllocator()->SetDisableThreadAccessCheck();
  #endif
              recycler->ReleaseBackgroundProfilerArena(backgroundRecyclerProfilerArena);
          }
      }
  
      void
      ScriptContextProfiler::ProfileBegin(Js::Phase phase)
      {
          Assert(IsInitialized());
          this->profiler->Begin(phase);
      }
  
      void
      ScriptContextProfiler::ProfileEnd(Js::Phase phase)
      {
          Assert(IsInitialized());
          this->profiler->End(phase);
      }
  
      void
      ScriptContextProfiler::ProfileSuspend(Js::Phase phase, Js::Profiler::SuspendRecord * suspendRecord)
      {
          Assert(IsInitialized());
          this->profiler->Suspend(phase, suspendRecord);
      }
  
      void
      ScriptContextProfiler::ProfileResume(Js::Profiler::SuspendRecord * suspendRecord)
      {
          Assert(IsInitialized());
          this->profiler->Resume(suspendRecord);
      }
  
      void
      ScriptContextProfiler::ProfileMerge(ScriptContextProfiler * profiler)
      {
          Assert(IsInitialized());
          this->profiler->Merge(profiler->profiler);
      }
  }
  #endif
  