diff --git a/lib/Common/Memory/CustomHeap.cpp b/lib/Common/Memory/CustomHeap.cpp index dc85cecaafb..5cc09d8990e 100644 --- a/lib/Common/Memory/CustomHeap.cpp +++ b/lib/Common/Memory/CustomHeap.cpp @@ -1053,54 +1053,42 @@ void FillDebugBreak(_In_ BYTE* buffer, __in size_t byteCount, HANDLE processHand CompileAssert(sizeof(char16) == 2); char16 pattern = 0xDEFE; - const bool isLocalProc = processHandle == GetCurrentProcess(); - BYTE * writeBuffer; - - if (isLocalProc) + if (processHandle == GetCurrentProcess()) { - writeBuffer = buffer; + BYTE * writeBuffer = buffer; + wmemset((char16 *)writeBuffer, pattern, byteCount / 2); + if (byteCount % 2) + { + // Note: this is valid scenario: in JIT mode, we may not be 2-byte-aligned in the end of unwind info. + *(writeBuffer + byteCount - 1) = 0; // Fill last remaining byte. + } } else { - writeBuffer = HeapNewNoThrowArray(BYTE, byteCount); - // in oom scenario write element at a time - // TODO: OOP JIT, pre-allocate space so this can't happen - if (!writeBuffer) + const size_t bufferSize = 0x1000; + byte localBuffer[bufferSize]; + wmemset((char16 *)localBuffer, pattern, (bufferSize < byteCount ? bufferSize : byteCount) / 2); + + for (size_t i = 0; i < byteCount / bufferSize; i++) { - for (size_t i = 0; i < byteCount; i+= sizeof(char16)) + if (!WriteProcessMemory(processHandle, buffer, localBuffer, bufferSize, NULL)) { - if (!WriteProcessMemory(processHandle, buffer + i, &pattern, sizeof(char16), NULL)) - { - Js::Throw::CheckAndThrowJITOperationFailed(); - Js::Throw::FatalInternalError(); - } - } - if (byteCount % 2 != 0) - { - char lastByte = 0; - if (!WriteProcessMemory(processHandle, buffer + byteCount - 1, &lastByte, sizeof(BYTE), NULL)) - { - Js::Throw::CheckAndThrowJITOperationFailed(); - Js::Throw::FatalInternalError(); - } + MemoryOperationLastError::CheckProcessAndThrowFatalError(processHandle); } - return; + buffer += bufferSize; } - } - wmemset((char16 *)writeBuffer, pattern, byteCount / 2); - if (byteCount % 2) - { - // Note: this is valid scenario: in JIT mode, we may not be 2-byte-aligned in the end of unwind info. - *(writeBuffer + byteCount - 1) = 0; // Fill last remaining byte. - } - if (!isLocalProc) - { - if (!WriteProcessMemory(processHandle, buffer, writeBuffer, byteCount, NULL)) + if (byteCount % bufferSize > 0) { - MemoryOperationLastError::RecordLastErrorAndThrow(); + if (byteCount % 2 != 0) + { + localBuffer[(byteCount - 1) % bufferSize] = 0; + } + if (!WriteProcessMemory(processHandle, buffer, localBuffer, byteCount % bufferSize, NULL)) + { + MemoryOperationLastError::CheckProcessAndThrowFatalError(processHandle); + } } - HeapDeleteArray(byteCount, writeBuffer); } #elif defined(_M_ARM64) diff --git a/lib/JITServer/JITServer.cpp b/lib/JITServer/JITServer.cpp index 3d77dfc3087..7dbf8147930 100644 --- a/lib/JITServer/JITServer.cpp +++ b/lib/JITServer/JITServer.cpp @@ -131,15 +131,18 @@ ServerInitializeThreadContext( /* [out] */ __RPC__out intptr_t *threadContextRoot, /* [out] */ __RPC__out intptr_t *prereservedRegionAddr) { - AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); - - ServerThreadContext * contextInfo = HeapNewNoThrow(ServerThreadContext, threadContextData); - if (contextInfo == nullptr) + ServerThreadContext * contextInfo = nullptr; + try + { + AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast(ExceptionType_OutOfMemory)); + contextInfo = HeapNew(ServerThreadContext, threadContextData); + ServerContextManager::RegisterThreadContext(contextInfo); + } + catch (Js::OutOfMemoryException) { return E_OUTOFMEMORY; } - ServerContextManager::RegisterThreadContext(contextInfo); return ServerCallWrapper(contextInfo, [&]()->HRESULT { *threadContextRoot = (intptr_t)EncodePointer(contextInfo); @@ -175,8 +178,6 @@ ServerUpdatePropertyRecordMap( /* [in] */ intptr_t threadContextInfoAddress, /* [in] */ __RPC__in UpdatedPropertysIDL * updatedProps) { - AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); - ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer((void*)threadContextInfoAddress); if (threadContextInfo == nullptr) @@ -208,8 +209,6 @@ ServerAddDOMFastPathHelper( /* [in] */ intptr_t funcInfoAddr, /* [in] */ int helper) { - AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); - ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer((void*)scriptContextRoot); if (scriptContextInfo == nullptr) @@ -232,8 +231,6 @@ ServerAddModuleRecordInfo( /* [in] */ unsigned int moduleId, /* [in] */ intptr_t localExportSlotsAddr) { - AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); - ServerScriptContext * serverScriptContext = (ServerScriptContext*)DecodePointer((void*)scriptContextInfoAddress); if (serverScriptContext == nullptr) { @@ -277,8 +274,6 @@ ServerInitializeScriptContext( /* [in] */ intptr_t threadContextInfoAddress, /* [out] */ __RPC__out intptr_t * scriptContextInfoAddress) { - AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); - ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer((void*)threadContextInfoAddress); *scriptContextInfoAddress = 0; @@ -364,12 +359,11 @@ ServerDecommitInterpreterBufferManager( return RPC_S_INVALID_ARG; } - if (ServerContextManager::IsScriptContextAlive(scriptContext)) + return ServerCallWrapper(scriptContext, [&]()->HRESULT { - AutoReleaseContext autoScriptContext(scriptContext); scriptContext->DecommitEmitBufferManager(asmJsManager != FALSE); - } - return S_OK; + return S_OK; + }); } HRESULT @@ -389,11 +383,8 @@ ServerNewInterpreterThunkBlock( return RPC_S_INVALID_ARG; } - AutoReleaseContext autoScriptContext(scriptContext); return ServerCallWrapper(scriptContext, [&]()->HRESULT { - AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); - const DWORD bufferSize = InterpreterThunkEmitter::BlockSize; DWORD thunkCount = 0; @@ -410,6 +401,10 @@ ServerNewInterpreterThunkBlock( BYTE* remoteBuffer; EmitBufferAllocation * allocation = emitBufferManager->AllocateBuffer(bufferSize, &remoteBuffer); + if (!allocation) + { + Js::Throw::OutOfMemory(); + } InterpreterThunkEmitter::FillBuffer( arena, @@ -425,16 +420,20 @@ ServerNewInterpreterThunkBlock( &thunkCount ); - bool success = emitBufferManager->ProtectBufferWithExecuteReadWriteForInterpreter(allocation); - Assert(success); + if (!emitBufferManager->ProtectBufferWithExecuteReadWriteForInterpreter(allocation)) + { + MemoryOperationLastError::CheckProcessAndThrowFatalError(threadContext->GetProcessHandle()); + } if (!WriteProcessMemory(threadContext->GetProcessHandle(), remoteBuffer, localBuffer, bufferSize, nullptr)) { - Js::Throw::JITOperationFailed(GetLastError()); + MemoryOperationLastError::CheckProcessAndThrowFatalError(threadContext->GetProcessHandle()); } - success = emitBufferManager->CommitReadWriteBufferForInterpreter(allocation, remoteBuffer, bufferSize); - Assert(success); + if (!emitBufferManager->CommitReadWriteBufferForInterpreter(allocation, remoteBuffer, bufferSize)) + { + MemoryOperationLastError::CheckProcessAndThrowFatalError(threadContext->GetProcessHandle()); + } // Call to set VALID flag for CFG check threadContext->SetValidCallTargetForCFG(remoteBuffer); @@ -567,8 +566,6 @@ ServerRemoteCodeGen( /* [in] */ __RPC__in CodeGenWorkItemIDL *workItemData, /* [out] */ __RPC__out JITOutputIDL *jitData) { - AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); - memset(jitData, 0, sizeof(JITOutputIDL)); ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer((void*)scriptContextInfoAddress); @@ -794,6 +791,7 @@ HRESULT ServerCallWrapper(ServerThreadContext* threadContextInfo, Fn fn) HRESULT hr = S_OK; try { + AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); AutoReleaseThreadContext autoThreadContext(threadContextInfo); hr = fn();