blob: 5f750d3404672fc508f02dd1bf7e000abe5cfc09 [file] [log] [blame]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "JsrtPch.h"
#if !defined(_WIN32) && !defined(__ANDROID__)
#include <pthread.h>
#endif
#include "jsrtHelper.h"
#include "Base/ThreadContextTlsEntry.h"
#include "Base/VTuneChakraProfile.h"
#ifdef DYNAMIC_PROFILE_STORAGE
#include "Language/DynamicProfileStorage.h"
#endif
#if !defined(_WIN32) || defined(CHAKRA_STATIC_LIBRARY)
#include "Core/ConfigParser.h"
#include "Base/ThreadBoundThreadContextManager.h"
#ifdef CHAKRA_STATIC_LIBRARY
bool ConfigParserAPI::FillConsoleTitle(__ecount(cchBufferSize) LPWSTR buffer, size_t cchBufferSize, __in LPWSTR moduleName)
{
return false;
}
void ConfigParserAPI::DisplayInitialOutput(__in LPWSTR moduleName)
{
}
LPCWSTR JsUtil::ExternalApi::GetFeatureKeyName()
{
return _u("");
}
#endif // CHAKRA_STATIC_LIBRARY
#endif
JsrtCallbackState::JsrtCallbackState(ThreadContext* currentThreadContext)
{
if (currentThreadContext == nullptr)
{
originalThreadContext = ThreadContext::GetContextForCurrentThread();
}
else
{
originalThreadContext = currentThreadContext;
}
originalJsrtContext = JsrtContext::GetCurrent();
Assert(originalJsrtContext == nullptr || originalThreadContext == originalJsrtContext->GetScriptContext()->GetThreadContext());
}
JsrtCallbackState::~JsrtCallbackState()
{
if (originalJsrtContext != nullptr)
{
if (originalJsrtContext != JsrtContext::GetCurrent())
{
// This shouldn't fail as the context was previously set on the current thread.
bool isSet = JsrtContext::TrySetCurrent(originalJsrtContext);
if (!isSet)
{
Js::Throw::FatalInternalError();
}
}
}
else
{
bool isSet = ThreadContextTLSEntry::TrySetThreadContext(originalThreadContext);
if (!isSet)
{
Js::Throw::FatalInternalError();
}
}
}
void JsrtCallbackState::ObjectBeforeCallectCallbackWrapper(JsObjectBeforeCollectCallback callback, void* object, void* callbackState, void* threadContext)
{
JsrtCallbackState scope(reinterpret_cast<ThreadContext*>(threadContext));
callback(object, callbackState);
}
#if !defined(_WIN32) || defined(CHAKRA_STATIC_LIBRARY)
void ChakraBinaryAutoSystemInfoInit(AutoSystemInfo * autoSystemInfo)
{
autoSystemInfo->buildDateHash = JsUtil::CharacterBuffer<char>::StaticGetHashCode(__DATE__, _countof(__DATE__));
autoSystemInfo->buildTimeHash = JsUtil::CharacterBuffer<char>::StaticGetHashCode(__TIME__, _countof(__TIME__));
}
#ifndef _WIN32
static pthread_key_t s_threadLocalDummy;
#endif
static THREAD_LOCAL bool s_threadWasEntered = false;
_NOINLINE void DISPOSE_CHAKRA_CORE_THREAD(void *_)
{
free(_);
ThreadBoundThreadContextManager::DestroyContextAndEntryForCurrentThread();
}
_NOINLINE bool InitializeProcess()
{
#if !defined(_WIN32)
pthread_key_create(&s_threadLocalDummy, DISPOSE_CHAKRA_CORE_THREAD);
#endif
// setup the cleanup
// we do not track the main thread. When it exits do the cleanup below
#ifdef CHAKRA_STATIC_LIBRARY
atexit([]() {
ThreadBoundThreadContextManager::DestroyContextAndEntryForCurrentThread();
#ifdef DYNAMIC_PROFILE_STORAGE
DynamicProfileStorage::Uninitialize();
#endif
JsrtRuntime::Uninitialize();
// thread-bound entrypoint should be able to get cleanup correctly, however tlsentry
// for current thread might be left behind if this thread was initialized.
ThreadContextTLSEntry::CleanupThread();
ThreadContextTLSEntry::CleanupProcess();
});
#endif
#ifndef _WIN32
PAL_InitializeChakraCore();
#endif
HMODULE mod = GetModuleHandleW(NULL);
AutoSystemInfo::SaveModuleFileName(mod);
#if defined(_M_IX86) && !defined(__clang__)
// Enable SSE2 math functions in CRT if SSE2 is available
#pragma prefast(suppress:6031, "We don't require SSE2, but will use it if available")
_set_SSE2_enable(TRUE);
#endif
{
CmdLineArgsParser parser;
ConfigParser::ParseOnModuleLoad(parser, mod);
}
#if defined(ENABLE_JS_ETW) && !defined(ENABLE_JS_LTTNG)
EtwTrace::Register();
#endif
#ifdef VTUNE_PROFILING
VTuneChakraProfile::Register();
#endif
#if PERFMAP_TRACE_ENABLED
PlatformAgnostic::PerfTrace::Register();
#endif
ValueType::Initialize();
ThreadContext::GlobalInitialize();
#ifdef ENABLE_BASIC_TELEMETRY
g_TraceLoggingClient = NoCheckHeapNewStruct(TraceLoggingClient);
#endif
#ifdef DYNAMIC_PROFILE_STORAGE
DynamicProfileStorage::Initialize();
#endif
return true;
}
_NOINLINE void VALIDATE_ENTER_CURRENT_THREAD()
{
// We do also initialize the process part here
// This is thread safe by the standard
// Let's hope compiler doesn't fail
static bool _has_init = InitializeProcess();
if (!_has_init) // do not assert this.
{
abort();
}
if (s_threadWasEntered) return;
s_threadWasEntered = true;
#ifdef HEAP_TRACK_ALLOC
HeapAllocator::InitializeThread();
#endif
#ifndef _WIN32
// put something into key to make sure destructor is going to be called
pthread_setspecific(s_threadLocalDummy, malloc(1));
#endif
}
#endif