| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "stdafx.h"
- #include "Core/AtomLockGuids.h"
- #ifdef _WIN32
- #include <winver.h>
- #include <process.h>
- #include <fcntl.h>
- #else
- #include <pthread.h>
- #endif
- #ifdef __linux__
- #include <sys/sysinfo.h>
- #elif defined(__APPLE__)
- #include <sys/sysctl.h>
- #endif
- unsigned int MessageBase::s_messageCount = 0;
- Debugger* Debugger::debugger = nullptr;
- #ifdef _WIN32
- LPCWSTR hostName = _u("ch.exe");
- #else
- LPCWSTR hostName = _u("ch");
- #endif
- JsRuntimeHandle chRuntime = JS_INVALID_RUNTIME_HANDLE;
- BOOL doTTRecord = false;
- BOOL doTTReplay = false;
- const size_t ttUriBufferLength = MAX_PATH * 3;
- char ttUri[ttUriBufferLength];
- size_t ttUriLength = 0;
- UINT32 snapInterval = MAXUINT32;
- UINT32 snapHistoryLength = MAXUINT32;
- LPCWSTR connectionUuidString = NULL;
- UINT32 startEventCount = 1;
- extern "C"
- HRESULT __stdcall OnChakraCoreLoadedEntry(TestHooks& testHooks)
- {
- return ChakraRTInterface::OnChakraCoreLoaded(testHooks);
- }
- JsRuntimeAttributes jsrtAttributes = JsRuntimeAttributeNone;
- int HostExceptionFilter(int exceptionCode, _EXCEPTION_POINTERS *ep)
- {
- ChakraRTInterface::NotifyUnhandledException(ep);
- #if ENABLE_NATIVE_CODEGEN && _WIN32
- JITProcessManager::TerminateJITServer();
- #endif
- bool crashOnException = false;
- ChakraRTInterface::GetCrashOnExceptionFlag(&crashOnException);
- if (exceptionCode == EXCEPTION_BREAKPOINT || (crashOnException && exceptionCode != 0xE06D7363))
- {
- return EXCEPTION_CONTINUE_SEARCH;
- }
- fwprintf(stderr, _u("FATAL ERROR: %ls failed due to exception code %x\n"), hostName, exceptionCode);
- _flushall();
- // Exception happened, so we probably didn't clean up properly,
- // Don't exit normally, just terminate
- TerminateProcess(::GetCurrentProcess(), exceptionCode);
- return EXCEPTION_CONTINUE_SEARCH;
- }
- void __stdcall PrintUsageFormat()
- {
- wprintf(_u("\nUsage: %s [-v|-version] [-h|-help] [-?] [flaglist] <source file>\n"), hostName);
- wprintf(_u("\t-v|-version\t\tDisplays version info\n"));
- wprintf(_u("\t-h|-help\t\tDisplays this help message\n"));
- wprintf(_u("\t-?\t\t\tDisplays this help message with complete [flaglist] info\n"));
- }
- #if !defined(ENABLE_DEBUG_CONFIG_OPTIONS)
- void __stdcall PrintReleaseUsage()
- {
- wprintf(_u("\nUsage: %s [-v|-version] [-h|-help|-?] <source file> %s"), hostName,
- _u("\nNote: [flaglist] is not supported in Release builds; try a Debug or Test build to enable these flags.\n"));
- wprintf(_u("\t-v|-version\t\tDisplays version info\n"));
- wprintf(_u("\t-h|-help|-?\t\tDisplays this help message\n"));
- }
- #endif
- void __stdcall PrintUsage()
- {
- #if !defined(ENABLE_DEBUG_CONFIG_OPTIONS)
- PrintReleaseUsage();
- #else
- PrintUsageFormat();
- #endif
- }
- void __stdcall PrintChVersion()
- {
- #if CHAKRA_CORE_VERSION_RELEASE
- wprintf(_u("%s version %d.%d.%d.0\n"),
- #else
- wprintf(_u("%s version %d.%d.%d.0-beta\n"),
- #endif
- hostName, CHAKRA_CORE_MAJOR_VERSION, CHAKRA_CORE_MINOR_VERSION, CHAKRA_CORE_PATCH_VERSION);
- }
- #ifdef _WIN32
- void __stdcall PrintChakraCoreVersion()
- {
- char16 filename[_MAX_PATH];
- char16 drive[_MAX_DRIVE];
- char16 dir[_MAX_DIR];
- LPCWSTR chakraDllName = GetChakraDllNameW();
- char16 modulename[_MAX_PATH];
- if (!PlatformAgnostic::SystemInfo::GetBinaryLocation(modulename, _MAX_PATH))
- {
- return;
- }
- _wsplitpath_s(modulename, drive, _MAX_DRIVE, dir, _MAX_DIR, nullptr, 0, nullptr, 0);
- _wmakepath_s(filename, drive, dir, chakraDllName, nullptr);
- UINT size = 0;
- LPBYTE lpBuffer = NULL;
- DWORD verSize = GetFileVersionInfoSizeW(filename, NULL);
- if (verSize != NULL)
- {
- LPSTR verData = new char[verSize];
- if (GetFileVersionInfoW(filename, NULL, verSize, verData) &&
- VerQueryValueW(verData, _u("\\"), (VOID FAR * FAR *)&lpBuffer, &size) &&
- (size != 0))
- {
- VS_FIXEDFILEINFO *verInfo = (VS_FIXEDFILEINFO *)lpBuffer;
- if (verInfo->dwSignature == VS_FFI_SIGNATURE)
- {
- // Doesn't matter if you are on 32 bit or 64 bit,
- // DWORD is always 32 bits, so first two revision numbers
- // come from dwFileVersionMS, last two come from dwFileVersionLS
- wprintf(_u("%s version %u.%u.%u.%u\n"),
- chakraDllName,
- (verInfo->dwFileVersionMS >> 16) & 0xffff,
- (verInfo->dwFileVersionMS >> 0) & 0xffff,
- (verInfo->dwFileVersionLS >> 16) & 0xffff,
- (verInfo->dwFileVersionLS >> 0) & 0xffff);
- }
- }
- delete[] verData;
- }
- }
- #endif
- void __stdcall PrintVersion()
- {
- PrintChVersion();
- #ifdef _WIN32
- PrintChakraCoreVersion();
- #endif
- }
- // On success the param byteCodeBuffer will be allocated in the function.
- HRESULT GetSerializedBuffer(LPCSTR fileContents, JsFinalizeCallback fileContentFinalizeCallback, JsValueRef *byteCodeBuffer)
- {
- HRESULT hr = S_OK;
- JsValueRef scriptSource;
- IfJsErrorFailLog(ChakraRTInterface::JsCreateExternalArrayBuffer((void*)fileContents,
- (unsigned int)strlen(fileContents), fileContentFinalizeCallback, (void*)fileContents, &scriptSource));
- IfJsErrorFailLog(ChakraRTInterface::JsSerialize(scriptSource, byteCodeBuffer,
- JsParseScriptAttributeNone));
- Error:
- return hr;
- }
- HANDLE GetFileHandle(LPCWSTR filename)
- {
- if (filename != nullptr)
- {
- return CreateFile(filename, GENERIC_WRITE, FILE_SHARE_DELETE,
- nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
- }
- return GetStdHandle(STD_OUTPUT_HANDLE);
- }
- HRESULT CreateLibraryByteCodeHeader(LPCSTR contentsRaw, JsFinalizeCallback contentsRawFinalizeCallback, DWORD lengthBytes, LPCWSTR bcFullPath, LPCSTR libraryNameNarrow)
- {
- HANDLE bcFileHandle = nullptr;
- JsValueRef bufferVal;
- BYTE *bcBuffer = nullptr;
- unsigned int bcBufferSize = 0;
- DWORD written;
- // For validating the header file against the library file
- auto outputStr =
- "//-------------------------------------------------------------------------------------------------------\n"
- "// Copyright (C) Microsoft. All rights reserved.\n"
- "// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.\n"
- "//-------------------------------------------------------------------------------------------------------\n"
- "#if 0\n";
- std::string normalizedContentStr;
- char* nextToken = nullptr;
- char* token = strtok_s((char*)contentsRaw, "\r", &nextToken);
- while (token)
- {
- normalizedContentStr.append(token);
- token = strtok_s(nullptr, "\r", &nextToken);
- }
- // We no longer need contentsRaw, so call the finalizer for it if one was provided
- if (contentsRawFinalizeCallback != nullptr)
- {
- contentsRawFinalizeCallback((void*)contentsRaw);
- }
- const char* normalizedContent = normalizedContentStr.c_str();
- // We still need contentsRaw after this, so pass a null finalizeCallback into it
- HRESULT hr = GetSerializedBuffer(normalizedContent, nullptr, &bufferVal);
- IfFailedGoLabel((hr), ErrorRunFinalize);
- IfJsrtErrorHRLabel(ChakraRTInterface::JsGetArrayBufferStorage(bufferVal, &bcBuffer, &bcBufferSize), ErrorRunFinalize);
- bcFileHandle = GetFileHandle(bcFullPath);
- IfFalseGo(bcFileHandle != INVALID_HANDLE_VALUE && bcFileHandle != nullptr);
- IfFalseGoLabel(WriteFile(bcFileHandle, outputStr, (DWORD)strlen(outputStr), &written, nullptr), ErrorRunFinalize);
- IfFalseGoLabel(WriteFile(bcFileHandle, normalizedContent, (DWORD)normalizedContentStr.size(), &written, nullptr), ErrorRunFinalize);
- outputStr = "\n#endif\n";
- IfFalseGo(WriteFile(bcFileHandle, outputStr, (DWORD)strlen(outputStr), &written, nullptr));
- // Write out the bytecode
- outputStr = "namespace Js\n{\n const char Library_Bytecode_";
- IfFalseGo(WriteFile(bcFileHandle, outputStr, (DWORD)strlen(outputStr), &written, nullptr));
- IfFalseGo(WriteFile(bcFileHandle, libraryNameNarrow, (DWORD)strlen(libraryNameNarrow), &written, nullptr));
- outputStr = "[] = {\n/* 00000000 */";
- IfFalseGo(WriteFile(bcFileHandle, outputStr, (DWORD)strlen(outputStr), &written, nullptr));
- for (unsigned int i = 0; i < bcBufferSize; i++)
- {
- char scratch[6];
- auto scratchLen = sizeof(scratch);
- int num = _snprintf_s(scratch, scratchLen, _countof(scratch), " 0x%02X", bcBuffer[i]);
- Assert(num == 5);
- IfFalseGo(WriteFile(bcFileHandle, scratch, (DWORD)(scratchLen - 1), &written, nullptr));
- // Add a comma and a space if this is not the last item
- if (i < bcBufferSize - 1)
- {
- char commaSpace[2];
- _snprintf_s(commaSpace, sizeof(commaSpace), _countof(commaSpace), ","); // close quote, new line, offset and open quote
- IfFalseGo(WriteFile(bcFileHandle, commaSpace, (DWORD)strlen(commaSpace), &written, nullptr));
- }
- // Add a line break every 16 scratches, primarily so the compiler doesn't complain about the string being too long.
- // Also, won't add for the last scratch
- if (i % 16 == 15 && i < bcBufferSize - 1)
- {
- char offset[17];
- int actualLen = _snprintf_s(offset, sizeof(offset), _countof(offset), "\n/* %08X */", i + 1); // close quote, new line, offset and open quote
- IfFalseGo(WriteFile(bcFileHandle, offset, actualLen, &written, nullptr));
- }
- }
- outputStr = "};\n\n";
- IfFalseGo(WriteFile(bcFileHandle, outputStr, (DWORD)strlen(outputStr), &written, nullptr));
- outputStr = "}\n";
- IfFalseGo(WriteFile(bcFileHandle, outputStr, (DWORD)strlen(outputStr), &written, nullptr));
- ErrorRunFinalize:
- Error:
- if (bcFileHandle != nullptr)
- {
- CloseHandle(bcFileHandle);
- }
- return hr;
- }
- // Used becuase of what's likely a deficiency in the API
- typedef struct {
- void* scriptBody;
- JsFinalizeCallback scriptBodyFinalizeCallback;
- bool freeingHandled;
- } SerializedCallbackInfo;
- static bool CHAKRA_CALLBACK DummyJsSerializedScriptLoadUtf8Source(
- JsSourceContext sourceContext,
- JsValueRef* scriptBuffer,
- JsParseScriptAttributes *parseAttributes)
- {
- SerializedCallbackInfo* serializedCallbackInfo = reinterpret_cast<SerializedCallbackInfo*>(sourceContext);
- Assert(!serializedCallbackInfo->freeingHandled);
- serializedCallbackInfo->freeingHandled = true;
- size_t length = strlen(reinterpret_cast<const char*>(serializedCallbackInfo->scriptBody));
- // sourceContext is source ptr, see RunScript below
- if (ChakraRTInterface::JsCreateExternalArrayBuffer(serializedCallbackInfo->scriptBody, (unsigned int)length,
- serializedCallbackInfo->scriptBodyFinalizeCallback, serializedCallbackInfo->scriptBody, scriptBuffer) != JsNoError)
- {
- return false;
- }
- *parseAttributes = JsParseScriptAttributeNone;
- return true;
- }
- HRESULT RunScript(const char* fileName, LPCSTR fileContents, size_t fileLength, JsFinalizeCallback fileContentsFinalizeCallback, JsValueRef bufferValue, char *fullPath, JsValueRef parserStateCache)
- {
- HRESULT hr = S_OK;
- MessageQueue * messageQueue = new MessageQueue();
- WScriptJsrt::AddMessageQueue(messageQueue);
- IfJsErrorFailLogLabel(ChakraRTInterface::JsSetPromiseContinuationCallback(WScriptJsrt::PromiseContinuationCallback, (void*)messageQueue), ErrorRunFinalize);
- if(strlen(fileName) >= 14 && strcmp(fileName + strlen(fileName) - 14, "ttdSentinal.js") == 0)
- {
- if(fileContentsFinalizeCallback != nullptr)
- {
- fileContentsFinalizeCallback((void*)fileContents);
- }
- #if !ENABLE_TTD
- wprintf(_u("Sential js file is only ok when in TTDebug mode!!!\n"));
- return E_FAIL;
- #else
- if(!doTTReplay)
- {
- wprintf(_u("Sential js file is only ok when in TTReplay mode!!!\n"));
- return E_FAIL;
- }
- IfFailedReturn(ChakraRTInterface::JsTTDStart());
- try
- {
- JsTTDMoveMode moveMode = JsTTDMoveMode::JsTTDMoveKthEvent;
- int64_t snapEventTime = -1;
- int64_t nextEventTime = -2;
- while(true)
- {
- JsErrorCode error = ChakraRTInterface::JsTTDGetSnapTimeTopLevelEventMove(chRuntime, moveMode, startEventCount, &nextEventTime, &snapEventTime, nullptr);
- if(error != JsNoError)
- {
- if(error == JsErrorCategoryUsage)
- {
- wprintf(_u("Start time not in log range.\n"));
- }
- return error;
- }
- IfFailedReturn(ChakraRTInterface::JsTTDMoveToTopLevelEvent(chRuntime, moveMode, snapEventTime, nextEventTime));
- JsErrorCode res = ChakraRTInterface::JsTTDReplayExecution(&moveMode, &nextEventTime);
- //handle any uncaught exception by immediately time-traveling to the throwing line in the debugger -- in replay just report and exit
- if(res == JsErrorCategoryScript)
- {
- wprintf(_u("An unhandled script exception occurred!!!\n"));
- ExitProcess(0);
- }
- if(nextEventTime == -1)
- {
- wprintf(_u("\nReached end of Execution -- Exiting.\n"));
- break;
- }
- }
- }
- catch(...)
- {
- wprintf(_u("Terminal exception in Replay -- exiting.\n"));
- ExitProcess(0);
- }
- #endif
- }
- else
- {
- Assert(fileContents != nullptr || bufferValue != nullptr);
- JsErrorCode runScript;
- JsValueRef fname;
- IfJsErrorFailLogLabel(ChakraRTInterface::JsCreateString(fullPath,
- strlen(fullPath), &fname), ErrorRunFinalize);
- if (bufferValue != nullptr)
- {
- if (fileContents == nullptr)
- {
- // if we have no fileContents, no worry about freeing them, and the call is simple.
- runScript = ChakraRTInterface::JsRunSerialized(
- bufferValue,
- nullptr /*JsSerializedLoadScriptCallback*/,
- 0 /*SourceContext*/,
- fname,
- nullptr /*result*/
- );
- }
- else // fileContents != nullptr
- {
- // Memory management is a little more complex here
- SerializedCallbackInfo serializedCallbackInfo;
- serializedCallbackInfo.scriptBody = (void*)fileContents;
- serializedCallbackInfo.scriptBodyFinalizeCallback = fileContentsFinalizeCallback;
- serializedCallbackInfo.freeingHandled = false;
- // Now we can run our script, with this serializedCallbackInfo as the sourcecontext
- runScript = ChakraRTInterface::JsRunSerialized(
- bufferValue,
- DummyJsSerializedScriptLoadUtf8Source,
- reinterpret_cast<JsSourceContext>(&serializedCallbackInfo),
- // Use source ptr as sourceContext
- fname,
- nullptr /*result*/);
- // Now that we're down here, we can free the fileContents if they weren't sent into
- // a GC-managed object.
- if (!serializedCallbackInfo.freeingHandled)
- {
- if (fileContentsFinalizeCallback != nullptr)
- {
- fileContentsFinalizeCallback((void*)fileContents);
- }
- }
- }
- }
- else if (parserStateCache != nullptr)
- {
- JsValueRef scriptSource;
- IfJsErrorFailLog(ChakraRTInterface::JsCreateExternalArrayBuffer((void*)fileContents,
- (unsigned int)fileLength,
- fileContentsFinalizeCallback, (void*)fileContents, &scriptSource));
- // TODO: Support TTD
- runScript = ChakraRTInterface::JsRunScriptWithParserState(
- scriptSource,
- WScriptJsrt::GetNextSourceContext(),
- fname,
- JsParseScriptAttributeNone,
- parserStateCache,
- nullptr);
- }
- else // bufferValue == nullptr && parserStateCache == nullptr
- {
- JsValueRef scriptSource;
- IfJsErrorFailLog(ChakraRTInterface::JsCreateExternalArrayBuffer((void*)fileContents,
- (unsigned int)fileLength,
- fileContentsFinalizeCallback, (void*)fileContents, &scriptSource));
- #if ENABLE_TTD
- if(doTTRecord)
- {
- JsPropertyIdRef ttProperty = nullptr;
- JsValueRef ttString = nullptr;
- JsValueRef global = nullptr;
- IfFailedReturn(ChakraRTInterface::JsCreatePropertyId("ttdLogURI", strlen("ttdLogURI"), &ttProperty));
- IfFailedReturn(ChakraRTInterface::JsCreateString(ttUri, ttUriLength, &ttString));
- IfFailedReturn(ChakraRTInterface::JsGetGlobalObject(&global));
- IfFailedReturn(ChakraRTInterface::JsSetProperty(global, ttProperty, ttString, false));
- IfFailedReturn(ChakraRTInterface::JsTTDStart());
- }
- auto sourceContext = WScriptJsrt::GetNextSourceContext();
- WScriptJsrt::RegisterScriptDir(sourceContext, fullPath);
- runScript = ChakraRTInterface::JsRun(scriptSource,
- sourceContext, fname,
- JsParseScriptAttributeNone, nullptr /*result*/);
- if (runScript == JsErrorCategoryUsage)
- {
- wprintf(_u("FATAL ERROR: Core was compiled without ENABLE_TTD is defined. CH is trying to use TTD interface\n"));
- abort();
- }
- #else
- runScript = ChakraRTInterface::JsRun(scriptSource,
- WScriptJsrt::GetNextSourceContext(), fname,
- JsParseScriptAttributeNone,
- nullptr /*result*/);
- #endif
- }
- //Do a yield after the main script body executes
- ChakraRTInterface::JsTTDNotifyYield();
- if(runScript != JsNoError)
- {
- WScriptJsrt::PrintException(fileName, runScript);
- }
- else
- {
- // Repeatedly flush the message queue until it's empty. It is necessary to loop on this
- // because setTimeout can add scripts to execute.
- do
- {
- IfFailGo(messageQueue->ProcessAll(fileName));
- } while(!messageQueue->IsEmpty());
- }
- }
- if(false)
- {
- ErrorRunFinalize:
- if(fileContentsFinalizeCallback != nullptr)
- {
- fileContentsFinalizeCallback((void*)fileContents);
- }
- }
- Error:
- #if ENABLE_TTD
- if(doTTRecord)
- {
- IfFailedReturn(ChakraRTInterface::JsTTDStop());
- }
- #endif
- if (messageQueue != nullptr)
- {
- messageQueue->RemoveAll();
- // clean up possible pinned exception object on exit to avoid potential leak
- bool hasException;
- if (ChakraRTInterface::JsHasException(&hasException) == JsNoError && hasException)
- {
- JsValueRef exception = JS_INVALID_REFERENCE;
- ChakraRTInterface::JsGetAndClearException(&exception);
- }
- delete messageQueue;
- }
- // We only call RunScript() once, safe to Uninitialize()
- WScriptJsrt::Uninitialize();
- return hr;
- }
- static HRESULT CreateRuntime(JsRuntimeHandle *runtime)
- {
- HRESULT hr = E_FAIL;
- #ifndef _WIN32
- // On Posix, malloc optimistically returns a non-null address without
- // checking if it's actually able to back that allocation in memory
- // Upon use of that address however, if the address space for that allocation
- // can't be committed, the process is killed
- // See the man page for malloc
- //
- // In order to avoid having to deal with this, we set the memory limit for the
- // runtime to the size of the physical memory on the system
- // TODO:
- // We could move the following into its own platform agnostic API
- // but in this case, this is a one-time call thats not applicable
- // on Windows so decided to leave as is
- // Additionally, we can probably do better than just limit to the physical memory
- // size
- #if defined(__APPLE__) || defined(__linux__)
- size_t memoryLimit;
- #ifdef __APPLE__
- int totalRamHW[] = { CTL_HW, HW_MEMSIZE };
- size_t length = sizeof(memoryLimit);
- if (sysctl(totalRamHW, 2, &memoryLimit, &length, NULL, 0) == -1)
- {
- memoryLimit = 0;
- }
- #else
- struct sysinfo sysInfo;
- if (sysinfo(&sysInfo) == -1)
- {
- memoryLimit = 0;
- }
- else
- {
- memoryLimit = sysInfo.totalram;
- }
- #endif // __APPLE__
- #endif // __APPLE__ || __linux
- #endif // !_WIN32
- IfJsErrorFailLog(ChakraRTInterface::JsCreateRuntime(jsrtAttributes, nullptr, runtime));
- #ifndef _WIN32
- IfJsErrorFailLog(ChakraRTInterface::JsSetRuntimeMemoryLimit(*runtime, memoryLimit));
- #endif
- hr = S_OK;
- Error:
- return hr;
- }
- HRESULT GetParserStateBuffer(LPCSTR fileContents, JsFinalizeCallback fileContentsFinalizeCallback, JsValueRef *parserStateBuffer)
- {
- HRESULT hr = S_OK;
- JsValueRef scriptSource = nullptr;
- IfJsErrorFailLog(ChakraRTInterface::JsCreateExternalArrayBuffer((void*)fileContents,
- (unsigned int)strlen(fileContents), fileContentsFinalizeCallback, (void*)fileContents, &scriptSource));
- IfJsErrorFailLog(ChakraRTInterface::JsSerializeParserState(scriptSource, parserStateBuffer, JsParseScriptAttributeNone));
- Error:
- return hr;
- }
- HRESULT CreateParserState(LPCSTR fileContents, size_t fileLength, JsFinalizeCallback fileContentsFinalizeCallback, LPCWSTR fullPath)
- {
- HRESULT hr = S_OK;
- HANDLE fileHandle = nullptr;
- JsValueRef parserStateBuffer = nullptr;
- BYTE *buffer = nullptr;
- unsigned int bufferSize = 0;
- IfFailedGoLabel(GetParserStateBuffer(fileContents, fileContentsFinalizeCallback, &parserStateBuffer), Error);
- IfJsErrorFailLog(ChakraRTInterface::JsGetArrayBufferStorage(parserStateBuffer, &buffer, &bufferSize));
- fileHandle = GetFileHandle(fullPath);
- IfFalseGo(fileHandle != INVALID_HANDLE_VALUE && fileHandle != nullptr);
- for (unsigned int i = 0; i < bufferSize; i++)
- {
- const unsigned int BYTES_PER_LINE = 32;
- DWORD written = 0;
- char scratch[3];
- auto scratchLen = sizeof(scratch);
- int num = _snprintf_s(scratch, scratchLen, _countof(scratch), "%02X", buffer[i]);
- Assert(num == 2);
- IfFalseGo(WriteFile(fileHandle, scratch, (DWORD)(scratchLen - 1), &written, nullptr));
- // Add line breaks so this block can be readable
- if (i % BYTES_PER_LINE == (BYTES_PER_LINE - 1) && i < bufferSize - 1)
- {
- IfFalseGo(WriteFile(fileHandle, "\n", 1, &written, nullptr));
- }
- }
- Error:
- if (fileHandle != nullptr)
- {
- CloseHandle(fileHandle);
- }
- return hr;
- }
- HRESULT CreateParserStateAndRunScript(const char* fileName, LPCSTR fileContents, size_t fileLength, JsFinalizeCallback fileContentsFinalizeCallback, char *fullPath)
- {
- HRESULT hr = S_OK;
- JsRuntimeHandle runtime = JS_INVALID_RUNTIME_HANDLE;
- JsContextRef context = JS_INVALID_REFERENCE, current = JS_INVALID_REFERENCE;
- JsValueRef bufferVal;
- // We don't want this to free fileContents when it completes, so the finalizeCallback is nullptr
- IfFailedGoLabel(GetParserStateBuffer(fileContents, nullptr, &bufferVal), ErrorRunFinalize);
- // Bytecode buffer is created in one runtime and will be executed on different runtime.
- IfFailedGoLabel(CreateRuntime(&runtime), ErrorRunFinalize);
- chRuntime = runtime;
- IfJsErrorFailLogLabel(ChakraRTInterface::JsCreateContext(runtime, &context), ErrorRunFinalize);
- IfJsErrorFailLogLabel(ChakraRTInterface::JsGetCurrentContext(¤t), ErrorRunFinalize);
- IfJsErrorFailLogLabel(ChakraRTInterface::JsSetCurrentContext(context), ErrorRunFinalize);
- // Initialized the WScript object on the new context
- if (!WScriptJsrt::Initialize())
- {
- IfFailedGoLabel(E_FAIL, ErrorRunFinalize);
- }
- // This is our last call to use fileContents, so pass in the finalizeCallback
- IfFailGo(RunScript(fileName, fileContents, fileLength, fileContentsFinalizeCallback, nullptr, fullPath, bufferVal));
- if (false)
- {
- ErrorRunFinalize:
- if (fileContentsFinalizeCallback != nullptr)
- {
- fileContentsFinalizeCallback((void*)fileContents);
- }
- }
- Error:
- if (current != JS_INVALID_REFERENCE)
- {
- ChakraRTInterface::JsSetCurrentContext(current);
- }
- if (runtime != JS_INVALID_RUNTIME_HANDLE)
- {
- ChakraRTInterface::JsDisposeRuntime(runtime);
- }
- return hr;
- }
- HRESULT CreateAndRunSerializedScript(const char* fileName, LPCSTR fileContents, size_t fileLength, JsFinalizeCallback fileContentsFinalizeCallback, char *fullPath)
- {
- HRESULT hr = S_OK;
- JsRuntimeHandle runtime = JS_INVALID_RUNTIME_HANDLE;
- JsContextRef context = JS_INVALID_REFERENCE, current = JS_INVALID_REFERENCE;
- JsValueRef bufferVal;
- // We don't want this to free fileContents when it completes, so the finalizeCallback is nullptr
- IfFailedGoLabel(GetSerializedBuffer(fileContents, nullptr, &bufferVal), ErrorRunFinalize);
- // Bytecode buffer is created in one runtime and will be executed on different runtime.
- IfFailedGoLabel(CreateRuntime(&runtime), ErrorRunFinalize);
- chRuntime = runtime;
- IfJsErrorFailLogLabel(ChakraRTInterface::JsCreateContext(runtime, &context), ErrorRunFinalize);
- IfJsErrorFailLogLabel(ChakraRTInterface::JsGetCurrentContext(¤t), ErrorRunFinalize);
- IfJsErrorFailLogLabel(ChakraRTInterface::JsSetCurrentContext(context), ErrorRunFinalize);
- // Initialized the WScript object on the new context
- if (!WScriptJsrt::Initialize())
- {
- IfFailedGoLabel(E_FAIL, ErrorRunFinalize);
- }
- // This is our last call to use fileContents, so pass in the finalizeCallback
- IfFailGo(RunScript(fileName, fileContents, fileLength, fileContentsFinalizeCallback, bufferVal, fullPath, nullptr));
- if(false)
- {
- ErrorRunFinalize:
- if(fileContentsFinalizeCallback != nullptr)
- {
- fileContentsFinalizeCallback((void*)fileContents);
- }
- }
- Error:
- if (current != JS_INVALID_REFERENCE)
- {
- ChakraRTInterface::JsSetCurrentContext(current);
- }
- if (runtime != JS_INVALID_RUNTIME_HANDLE)
- {
- ChakraRTInterface::JsDisposeRuntime(runtime);
- }
- return hr;
- }
- HRESULT ExecuteTest(const char* fileName)
- {
- HRESULT hr = S_OK;
- LPCSTR fileContents = nullptr;
- JsRuntimeHandle runtime = JS_INVALID_RUNTIME_HANDLE;
- UINT lengthBytes = 0;
- if(strlen(fileName) >= 14 && strcmp(fileName + strlen(fileName) - 14, "ttdSentinal.js") == 0)
- {
- #if !ENABLE_TTD
- wprintf(_u("Sentinel js file is only ok when in TTDebug mode!!!\n"));
- return E_FAIL;
- #else
- if(!doTTReplay)
- {
- wprintf(_u("Sentinel js file is only ok when in TTReplay mode!!!\n"));
- return E_FAIL;
- }
- jsrtAttributes = static_cast<JsRuntimeAttributes>(jsrtAttributes | JsRuntimeAttributeEnableExperimentalFeatures);
- IfJsErrorFailLog(ChakraRTInterface::JsTTDCreateReplayRuntime(jsrtAttributes, ttUri, ttUriLength, Helpers::TTCreateStreamCallback, Helpers::TTReadBytesFromStreamCallback, Helpers::TTFlushAndCloseStreamCallback, nullptr, &runtime));
- chRuntime = runtime;
- JsContextRef context = JS_INVALID_REFERENCE;
- IfJsErrorFailLog(ChakraRTInterface::JsTTDCreateContext(runtime, true, &context));
- IfJsErrorFailLog(ChakraRTInterface::JsSetCurrentContext(context));
- IfFailGo(RunScript(fileName, fileContents, lengthBytes, WScriptJsrt::FinalizeFree, nullptr, nullptr, nullptr));
- unsigned int rcount = 0;
- IfJsErrorFailLog(ChakraRTInterface::JsSetCurrentContext(nullptr));
- ChakraRTInterface::JsRelease(context, &rcount);
- AssertMsg(rcount == 0, "Should only have had 1 ref from replay code and one ref from current context??");
- #endif
- }
- else
- {
- LPCOLESTR contentsRaw = nullptr;
- char fullPath[_MAX_PATH];
- size_t len = 0;
- hr = Helpers::LoadScriptFromFile(fileName, fileContents, &lengthBytes);
- contentsRaw; lengthBytes; // Unused for now.
- IfFailGo(hr);
- if (HostConfigFlags::flags.GenerateLibraryByteCodeHeaderIsEnabled)
- {
- jsrtAttributes = (JsRuntimeAttributes)(jsrtAttributes | JsRuntimeAttributeSerializeLibraryByteCode);
- }
- #if ENABLE_TTD
- if (doTTRecord)
- {
- //Ensure we run with experimental features (as that is what Node does right now).
- jsrtAttributes = static_cast<JsRuntimeAttributes>(jsrtAttributes | JsRuntimeAttributeEnableExperimentalFeatures);
- IfJsErrorFailLog(ChakraRTInterface::JsTTDCreateRecordRuntime(jsrtAttributes, snapInterval, snapHistoryLength, Helpers::TTCreateStreamCallback, Helpers::TTWriteBytesToStreamCallback, Helpers::TTFlushAndCloseStreamCallback, nullptr, &runtime));
- chRuntime = runtime;
- JsContextRef context = JS_INVALID_REFERENCE;
- IfJsErrorFailLog(ChakraRTInterface::JsTTDCreateContext(runtime, true, &context));
- #if ENABLE_TTD
- //We need this here since this context is created in record
- IfJsErrorFailLog(ChakraRTInterface::JsSetObjectBeforeCollectCallback(context, nullptr, WScriptJsrt::JsContextBeforeCollectCallback));
- #endif
- IfJsErrorFailLog(ChakraRTInterface::JsSetCurrentContext(context));
- }
- else
- {
- AssertMsg(!doTTReplay, "Should be handled in the else case above!!!");
- IfJsErrorFailLog(ChakraRTInterface::JsCreateRuntime(jsrtAttributes, nullptr, &runtime));
- chRuntime = runtime;
- if (HostConfigFlags::flags.DebugLaunch)
- {
- Debugger* debugger = Debugger::GetDebugger(runtime);
- debugger->StartDebugging(runtime);
- }
- JsContextRef context = JS_INVALID_REFERENCE;
- IfJsErrorFailLog(ChakraRTInterface::JsCreateContext(runtime, &context));
- //Don't need collect callback since this is always in replay
- IfJsErrorFailLog(ChakraRTInterface::JsSetCurrentContext(context));
- }
- #else
- IfJsErrorFailLog(ChakraRTInterface::JsCreateRuntime(jsrtAttributes, nullptr, &runtime));
- chRuntime = runtime;
- if (HostConfigFlags::flags.DebugLaunch)
- {
- Debugger* debugger = Debugger::GetDebugger(runtime);
- debugger->StartDebugging(runtime);
- }
- JsContextRef context = JS_INVALID_REFERENCE;
- IfJsErrorFailLog(ChakraRTInterface::JsCreateContext(runtime, &context));
- IfJsErrorFailLog(ChakraRTInterface::JsSetCurrentContext(context));
- #endif
- #ifdef DEBUG
- ChakraRTInterface::SetCheckOpHelpersFlag(true);
- #endif
- #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
- ChakraRTInterface::SetOOPCFGRegistrationFlag(false);
- #endif
- if (!WScriptJsrt::Initialize())
- {
- IfFailGo(E_FAIL);
- }
- if (_fullpath(fullPath, fileName, _MAX_PATH) == nullptr)
- {
- IfFailGo(E_FAIL);
- }
- if (HostConfigFlags::flags.TrackRejectedPromises)
- {
- ChakraRTInterface::JsSetHostPromiseRejectionTracker(WScriptJsrt::PromiseRejectionTrackerCallback, nullptr);
- }
-
- len = strlen(fullPath);
- if (HostConfigFlags::flags.GenerateLibraryByteCodeHeaderIsEnabled)
- {
- if (HostConfigFlags::flags.GenerateLibraryByteCodeHeader != nullptr)
- {
- if (wcslen(HostConfigFlags::flags.GenerateLibraryByteCodeHeader) == 0)
- {
- HostConfigFlags::flags.GenerateLibraryByteCodeHeader = nullptr;
- }
- }
- CHAR libraryName[_MAX_PATH];
- CHAR ext[_MAX_EXT];
- _splitpath_s(fullPath, NULL, 0, NULL, 0, libraryName, _countof(libraryName), ext, _countof(ext));
- IfFailGo(CreateLibraryByteCodeHeader(fileContents, WScriptJsrt::FinalizeFree, lengthBytes, HostConfigFlags::flags.GenerateLibraryByteCodeHeader, libraryName));
- }
- else if (HostConfigFlags::flags.SerializedIsEnabled)
- {
- CreateAndRunSerializedScript(fileName, fileContents, lengthBytes, WScriptJsrt::FinalizeFree, fullPath);
- }
- else if (HostConfigFlags::flags.GenerateParserStateCacheIsEnabled)
- {
- CreateParserState(fileContents, lengthBytes, WScriptJsrt::FinalizeFree, nullptr);
- }
- else if (HostConfigFlags::flags.UseParserStateCacheIsEnabled)
- {
- CreateParserStateAndRunScript(fileName, fileContents, lengthBytes, WScriptJsrt::FinalizeFree, fullPath);
- }
- else
- {
- IfFailGo(RunScript(fileName, fileContents, lengthBytes, WScriptJsrt::FinalizeFree, nullptr, fullPath, nullptr));
- }
- }
- Error:
- if (Debugger::debugger != nullptr)
- {
- Debugger::debugger->CompareOrWriteBaselineFile(fileName);
- Debugger::CloseDebugger();
- }
- ChakraRTInterface::JsSetCurrentContext(nullptr);
- if (runtime != JS_INVALID_RUNTIME_HANDLE)
- {
- ChakraRTInterface::JsDisposeRuntime(runtime);
- }
- _flushall();
- return hr;
- }
- HRESULT ExecuteTestWithMemoryCheck(char* fileName)
- {
- HRESULT hr = E_FAIL;
- #ifdef _WIN32 // looks on linux it always leak ThreadContextTLSEntry since there's no DllMain
- #ifdef CHECK_MEMORY_LEAK
- // Always check memory leak, unless user specified the flag already
- if (!ChakraRTInterface::IsEnabledCheckMemoryFlag())
- {
- ChakraRTInterface::SetCheckMemoryLeakFlag(true);
- }
- // Disable the output in case an unhandled exception happens
- // We will re-enable it if there is no unhandled exceptions
- ChakraRTInterface::SetEnableCheckMemoryLeakOutput(false);
- #endif
- #endif
- #ifdef _WIN32
- __try
- {
- hr = ExecuteTest(fileName);
- }
- __except (HostExceptionFilter(GetExceptionCode(), GetExceptionInformation()))
- {
- Assert(false);
- }
- #else
- // REVIEW: Do we need a SEH handler here?
- hr = ExecuteTest(fileName);
- if (FAILED(hr)) exit(0);
- #endif // _WIN32
- _flushall();
- #ifdef CHECK_MEMORY_LEAK
- ChakraRTInterface::SetEnableCheckMemoryLeakOutput(true);
- #endif
- return hr;
- }
- #ifdef _WIN32
- bool HandleJITServerFlag(int& argc, _Inout_updates_to_(argc, argc) LPWSTR argv[])
- {
- LPCWSTR flag = _u("-jitserver:");
- LPCWSTR flagWithoutColon = _u("-jitserver");
- size_t flagLen = wcslen(flag);
- int i = 0;
- for (i = 1; i < argc; ++i)
- {
- if (!_wcsicmp(argv[i], flagWithoutColon))
- {
- connectionUuidString = _u("");
- break;
- }
- else if (!_wcsnicmp(argv[i], flag, flagLen))
- {
- connectionUuidString = argv[i] + flagLen;
- if (wcslen(connectionUuidString) == 0)
- {
- fwprintf(stdout, _u("[FAILED]: must pass a UUID to -jitserver:\n"));
- return false;
- }
- else
- {
- break;
- }
- }
- }
- if (i == argc)
- {
- return false;
- }
- // remove this flag now
- HostConfigFlags::RemoveArg(argc, argv, i);
- return true;
- }
- typedef HRESULT(WINAPI *JsInitializeJITServerPtr)(UUID* connectionUuid, void* securityDescriptor, void* alpcSecurityDescriptor);
- int _cdecl RunJITServer(int argc, __in_ecount(argc) LPWSTR argv[])
- {
- ChakraRTInterface::ArgInfo argInfo = { argc, argv, PrintUsage, nullptr };
- HINSTANCE chakraLibrary = nullptr;
- bool success = ChakraRTInterface::LoadChakraDll(&argInfo, &chakraLibrary);
- int status = 0;
- JsInitializeJITServerPtr initRpcServer = nullptr;
- if (!success)
- {
- wprintf(_u("\nDll load failed\n"));
- return ERROR_DLL_INIT_FAILED;
- }
- UUID connectionUuid;
- status = UuidFromStringW((RPC_WSTR)connectionUuidString, &connectionUuid);
- if (status != RPC_S_OK)
- {
- goto cleanup;
- }
- initRpcServer = (JsInitializeJITServerPtr)GetProcAddress(chakraLibrary, "JsInitializeJITServer");
- status = initRpcServer(&connectionUuid, nullptr, nullptr);
- if (FAILED(status))
- {
- wprintf(_u("InitializeJITServer failed by 0x%x\n"), status);
- goto cleanup;
- }
- status = 0;
- cleanup:
- if (chakraLibrary)
- {
- ChakraRTInterface::UnloadChakraDll(chakraLibrary);
- }
- return status;
- }
- #endif
- unsigned int WINAPI StaticThreadProc(void *lpParam)
- {
- ChakraRTInterface::ArgInfo* argInfo = static_cast<ChakraRTInterface::ArgInfo* >(lpParam);
- return ExecuteTestWithMemoryCheck(argInfo->filename);
- }
- #ifndef _WIN32
- static char16** argv = nullptr;
- int main(int argc, char** c_argv)
- {
- #ifndef CHAKRA_STATIC_LIBRARY
- // xplat-todo: PAL free CH ?
- PAL_InitializeChakraCore();
- #endif
- int origargc = argc; // store for clean-up later
- argv = new char16*[argc];
- for (int i = 0; i < argc; i++)
- {
- NarrowStringToWideDynamic(c_argv[i], &argv[i]);
- }
- #else
- #define PAL_Shutdown()
- int _cdecl wmain(int argc, __in_ecount(argc) LPWSTR argv[])
- {
- #endif
- #ifdef _WIN32
- // Set the output mode of stdout so we can display non-ASCII characters on the console and redirect to file as UTF-8
- {
- int result = _setmode(_fileno(stdout), _O_U8TEXT); // set stdout to UTF-8 mode
- if (result == -1)
- {
- // Failed to set mode. Undefined behavior may result, so exit now.
- wprintf(_u("Failed to set output stream mode. Exiting...\n"));
- return EXIT_FAILURE;
- }
- }
- bool runJITServer = HandleJITServerFlag(argc, argv);
- #endif
- int retval = -1;
- HRESULT exitCode = E_FAIL;
- int cpos = 1;
- HINSTANCE chakraLibrary = nullptr;
- bool success = false;
- ChakraRTInterface::ArgInfo argInfo;
- #ifdef _WIN32
- ATOM lock;
- #endif
- if (argc < 2)
- {
- PrintUsage();
- PAL_Shutdown();
- retval = EXIT_FAILURE;
- goto return_cleanup;
- }
- #ifdef _WIN32
- if (runJITServer)
- {
- retval = RunJITServer(argc, argv);
- goto return_cleanup;
- }
- #endif
- for(int i = 1; i < argc; ++i)
- {
- const wchar *arg = argv[i];
- size_t arglen = wcslen(arg);
- // support - or / prefix for flags
- if (arglen >= 1 && (arg[0] == _u('-')
- #ifdef _WIN32
- || arg[0] == _u('/') // '/' prefix for legacy (Windows-only because it starts a path on Unix)
- #endif
- ))
- {
- // support -- prefix for flags
- if (arglen >= 2 && arg[0] == _u('-') && arg[1] == _u('-'))
- {
- arg += 2; // advance past -- prefix
- }
- else
- {
- arg += 1; // advance past - or / prefix
- }
- }
- arglen = wcslen(arg); // get length of flag after prefix
- if ((arglen == 1 && wcsncmp(arg, _u("v"), arglen) == 0) ||
- (arglen == 7 && wcsncmp(arg, _u("version"), arglen) == 0))
- {
- PrintVersion();
- PAL_Shutdown();
- retval = EXIT_SUCCESS;
- goto return_cleanup;
- }
- else if (
- #if !defined(ENABLE_DEBUG_CONFIG_OPTIONS) // release builds can display some kind of help message
- (arglen == 1 && wcsncmp(arg, _u("?"), arglen) == 0) ||
- #endif
- (arglen == 1 && wcsncmp(arg, _u("h"), arglen) == 0) ||
- (arglen == 4 && wcsncmp(arg, _u("help"), arglen) == 0)
- )
- {
- PrintUsage();
- PAL_Shutdown();
- retval = EXIT_SUCCESS;
- goto return_cleanup;
- }
- else if(wcsstr(argv[i], _u("-TTRecord=")) == argv[i])
- {
- doTTRecord = true;
- wchar* ruri = argv[i] + wcslen(_u("-TTRecord="));
- Helpers::GetTTDDirectory(ruri, &ttUriLength, ttUri, ttUriBufferLength);
- }
- else if(wcsstr(argv[i], _u("-TTReplay=")) == argv[i])
- {
- doTTReplay = true;
- wchar* ruri = argv[i] + wcslen(_u("-TTReplay="));
- Helpers::GetTTDDirectory(ruri, &ttUriLength, ttUri, ttUriBufferLength);
- }
- else if(wcsstr(argv[i], _u("-TTSnapInterval=")) == argv[i])
- {
- LPCWSTR intervalStr = argv[i] + wcslen(_u("-TTSnapInterval="));
- snapInterval = (UINT32)_wtoi(intervalStr);
- }
- else if(wcsstr(argv[i], _u("-TTHistoryLength=")) == argv[i])
- {
- LPCWSTR historyStr = argv[i] + wcslen(_u("-TTHistoryLength="));
- snapHistoryLength = (UINT32)_wtoi(historyStr);
- }
- else if(wcsstr(argv[i], _u("-TTDStartEvent=")) == argv[i])
- {
- LPCWSTR startEventStr = argv[i] + wcslen(_u("-TTDStartEvent="));
- startEventCount = (UINT32)_wtoi(startEventStr);
- }
- else
- {
- wchar *temp = argv[cpos];
- argv[cpos] = argv[i];
- argv[i] = temp;
- cpos++;
- }
- }
- argc = cpos;
- if(doTTRecord & doTTReplay)
- {
- fwprintf(stderr, _u("Cannot run in record and replay at same time!!!"));
- ExitProcess(0);
- }
- HostConfigFlags::pfnPrintUsage = PrintUsageFormat;
- // The following code is present to make sure we don't load
- // jscript9.dll etc with ch. Since that isn't a concern on non-Windows
- // builds, it's safe to conditionally compile it out.
- #ifdef _WIN32
- lock = ::AddAtom(szChakraCoreLock);
- AssertMsg(lock, "failed to lock chakracore.dll");
- #endif // _WIN32
- HostConfigFlags::HandleArgsFlag(argc, argv);
- argInfo = { argc, argv, PrintUsage, nullptr };
- success = ChakraRTInterface::LoadChakraDll(&argInfo, &chakraLibrary);
- #if defined(CHAKRA_STATIC_LIBRARY) && !defined(NDEBUG)
- // handle command line flags
- OnChakraCoreLoaded(OnChakraCoreLoadedEntry);
- #endif
- if (argInfo.filename == nullptr)
- {
- WideStringToNarrowDynamic(argv[1], &argInfo.filename);
- }
- if (success)
- {
- if (HostConfigFlags::flags.CustomConfigFile != NULL)
- {
- ChakraRTInterface::SetConfigFile(HostConfigFlags::flags.CustomConfigFile);
- }
- #ifdef _WIN32
- #if ENABLE_NATIVE_CODEGEN
- if (HostConfigFlags::flags.OOPJIT)
- {
- // TODO: Error checking
- JITProcessManager::StartRpcServer(argc, argv);
- ChakraRTInterface::ConnectJITServer(JITProcessManager::GetRpcProccessHandle(), nullptr, JITProcessManager::GetRpcConnectionId());
- }
- #endif
- HANDLE threadHandle;
- threadHandle = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, &StaticThreadProc, &argInfo, STACK_SIZE_PARAM_IS_A_RESERVATION, 0));
- if (threadHandle != nullptr)
- {
- DWORD waitResult = WaitForSingleObject(threadHandle, INFINITE);
- Assert(waitResult == WAIT_OBJECT_0);
- DWORD threadExitCode;
- GetExitCodeThread(threadHandle, &threadExitCode);
- exitCode = (HRESULT)threadExitCode;
- CloseHandle(threadHandle);
- }
- else
- {
- fwprintf(stderr, _u("FATAL ERROR: failed to create worker thread error code %d, exiting\n"), errno);
- AssertMsg(false, "failed to create worker thread");
- }
- #else
- // On linux, execute on the same thread
- exitCode = ExecuteTestWithMemoryCheck(argInfo.filename);
- #endif
- ChakraRTInterface::UnloadChakraDll(chakraLibrary);
- }
- #if ENABLE_NATIVE_CODEGEN && defined(_WIN32)
- JITProcessManager::TerminateJITServer();
- #endif
- PAL_Shutdown();
- retval = (int)exitCode;
- return_cleanup:
- #ifndef _WIN32
- if(argv != nullptr)
- {
- for(int i=0;i<origargc;i++)
- {
- free(argv[i]);
- argv[i] = nullptr;
- }
- }
- delete[] argv;
- argv = nullptr;
- #ifdef NO_SANITIZE_ADDRESS_CHECK
- pthread_exit(&retval);
- #else
- return retval;
- #endif
- #else
- return retval;
- #endif
- }
|