MemoryLogger.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "CommonMemoryPch.h"
  6. #include "MemoryLogger.h"
  7. #ifdef ENABLE_TRACE
  8. namespace Js
  9. {
  10. MemoryLogger::MemoryLogger(TAllocator* alloc, ULONG count) : m_alloc(alloc), m_capacity(count), m_current(0)
  11. {
  12. m_log = AnewArrayZ(m_alloc, char16*, m_capacity);
  13. }
  14. MemoryLogger::~MemoryLogger()
  15. {
  16. Adelete(m_alloc, m_log);
  17. }
  18. void MemoryLogger::Write(const char16* msg)
  19. {
  20. #ifdef EXCEPTION_CHECK
  21. // In most cases this will be called at runtime when we have exception check enabled.
  22. AutoNestedHandledExceptionType autoNestedHandledExceptionType(ExceptionType_DisableCheck);
  23. #endif
  24. AutoCriticalSection autocs(&m_criticalSection); // TODO: with circular buffer now we can use much granular lock.
  25. // Create a copy of the message.
  26. size_t len = wcslen(msg);
  27. char16* buf = AnewArray(m_alloc, char16, len + 1);
  28. js_wmemcpy_s(buf, len + 1, msg, len + 1); // Copy with the NULL-terminator.
  29. // m_current is the next position to write to.
  30. if (m_log[m_current])
  31. {
  32. Adelete(m_alloc, m_log[m_current]);
  33. }
  34. m_log[m_current] = buf;
  35. m_current = (m_current + 1) % m_capacity;
  36. }
  37. MemoryLogger* MemoryLogger::Create(TAllocator* alloc, ULONG count)
  38. {
  39. #ifdef EXCEPTION_CHECK
  40. AutoNestedHandledExceptionType autoNestedHandledExceptionType(ExceptionType_DisableCheck);
  41. #endif
  42. return Anew(alloc, MemoryLogger, alloc, count);
  43. }
  44. #ifdef STACK_BACK_TRACE
  45. StackTraceHelper* StackTraceHelper::Create(TAllocator* alloc)
  46. {
  47. #ifdef EXCEPTION_CHECK
  48. AutoNestedHandledExceptionType autoNestedHandledExceptionType(ExceptionType_DisableCheck);
  49. #endif
  50. return Anew(alloc, StackTraceHelper, alloc);
  51. }
  52. // Capture and fill buffer.
  53. ULONG StackTraceHelper::GetStackTrace(ULONG framesToSkip, ULONG framesToCapture, void** stackFrames)
  54. {
  55. #ifdef EXCEPTION_CHECK
  56. AutoNestedHandledExceptionType autoNestedHandledExceptionType(ExceptionType_DisableCheck);
  57. #endif
  58. StackBackTrace* stackTrace = this->GetStackBackTrace(framesToCapture);
  59. ULONG capturedCount = stackTrace->Capture(framesToSkip);
  60. Assert(capturedCount <= framesToCapture);
  61. ULONG i = 0;
  62. stackTrace->Map([&i, framesToCapture, stackFrames](void* funcAddr){
  63. Assert(i <= framesToCapture);
  64. stackFrames[i++] = funcAddr;
  65. });
  66. return capturedCount;
  67. }
  68. // Capture and print.
  69. size_t StackTraceHelper::PrintStackTrace(ULONG framesToSkip, ULONG framesToCapture)
  70. {
  71. #ifdef EXCEPTION_CHECK
  72. AutoNestedHandledExceptionType autoNestedHandledExceptionType(ExceptionType_DisableCheck);
  73. #endif
  74. StackBackTrace* stackTrace = this->GetStackBackTrace(framesToCapture);
  75. stackTrace->Capture(framesToSkip);
  76. return stackTrace->Print();
  77. }
  78. StackBackTrace* StackTraceHelper::GetStackBackTrace(ULONG frameCount)
  79. {
  80. // Create, if we haven't already for calling thread.
  81. if (!s_stackBackTrace)
  82. {
  83. s_stackBackTrace = StackBackTrace::Create(m_alloc, frameCount);
  84. }
  85. Assert(s_stackBackTrace->GetRequestedFrameCount() >= frameCount);
  86. return s_stackBackTrace;
  87. }
  88. THREAD_LOCAL StackBackTrace* StackTraceHelper::s_stackBackTrace = nullptr;
  89. #endif // STACK_BACK_TRACE
  90. }
  91. #endif // ENABLE_TRACE