Merge pull request #2879 from janvorli/fix-exception-in-prestub-using-holder-pass1
authorJan Vorlicek <janvorli@microsoft.com>
Wed, 27 Jan 2016 15:11:19 +0000 (16:11 +0100)
committerJan Vorlicek <janvorli@microsoft.com>
Wed, 27 Jan 2016 15:11:19 +0000 (16:11 +0100)
Fix exception in PreStubWorker call chain - update

49 files changed:
Documentation/project-docs/contributing.md
LICENSE.TXT
netci.groovy
src/binder/coreclrbindercommon.cpp
src/binder/inc/clrprivbindercoreclr.h
src/gc/env/common.h
src/gc/env/gcenv.base.h
src/gc/env/gcenv.interlocked.inl
src/gc/env/gcenv.os.h
src/gc/env/gcenv.structs.h
src/gc/gc.cpp
src/gc/gcee.cpp
src/gc/gcpriv.h
src/gc/handletable.cpp
src/gc/sample/CMakeLists.txt
src/gc/sample/gcenv.ee.cpp
src/gc/sample/gcenv.h
src/gc/sample/gcenv.unix.cpp
src/gc/sample/gcenv.windows.cpp
src/inc/clrhost.h
src/inc/winwrap.h
src/jit/codegenxarch.cpp
src/jit/importer.cpp
src/jit/liveness.cpp
src/mscorlib/src/System/String.cs
src/mscorlib/src/System/TimeZoneInfo.cs
src/pal/src/arch/i386/dispatchexceptionwrapper.S
src/pal/src/exception/machexception.cpp
src/pal/src/exception/machmessage.cpp
src/pal/src/exception/machmessage.h
src/pal/src/include/pal/context.h
src/pal/src/include/pal/process.h
src/pal/src/include/pal/thread.hpp
src/pal/src/memory/heap.cpp
src/pal/src/thread/context.cpp
src/pal/src/thread/process.cpp
src/pal/src/thread/thread.cpp
src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest1.cpp
src/pal/tests/palsuite/exception_handling/pal_sxs/test1/dlltest2.cpp
src/utilcode/clrhost_nodependencies.cpp
src/utilcode/hostimpl.cpp
src/vm/disassembler.cpp
src/vm/gcenv.h
src/vm/gcenv.os.cpp
src/vm/i386/virtualcallstubcpu.hpp
src/vm/threads.cpp
tests/arm64/Tests.lst
tests/buildtest.cmd
tests/src/JIT/Performance/CodeQuality/V8/DeltaBlue/DeltaBlue.cs

index 1b16c99..e0d0560 100644 (file)
@@ -6,43 +6,14 @@ The .NET Core team maintains several guidelines for contributing to the .NET Cor
 Contribution Guidelines
 =======================
 
-- [Contribution Bar](#contribution-bar) describes the bar that the team uses to accept changes.
-- [Contributing Ports](#contributing-ports) describes the slightly different bar for contributing changes that enable .NET Core to run on other OSes and chips.
-- [Mscorlib Contributions](#contributing-to-mscorlib-library) describes contributing to the mscorlib library.
+- [Licensing](#copyright) describes the licensing practices for the project.
 - [General Contribution Guidance](#general-contribution-guidance) describes general contribution guidance, including more subjective stylistic guidelines.
-- [DOs and DON'Ts](#dos-and-donts) provides a partial checklist summary of contributing guidelines, in classic framework guidlines do/don't style.
-- [Contributor License Agreement (CLA)](#contributor-license-agreement) describes the requirement and process of signing a Contributor License Agreement (CLA).
+- [Contribution Bar](#contribution-bar) describes the bar that the team uses to accept changes.
 - [Contribution Workflow](contributing-workflow.md) describes the workflow that the team uses for considering and accepting changes.
 - [Garbage Collection Guidelines](garbage-collector-guidelines.md) for changes that affect the GC.
 - [Performance Guidelines](performance-guidelines.md) for changes in performance critical code or that otherwise affect performance.
 - [Porting the JIT](https://github.com/dotnet/coreclr/pull/2214#issuecomment-161850464) to other chip architectures.
 
-Contribution "Bar"
-==================
-
-Project maintainers will merge changes that align with [project priorities](project-priorities.md) and/or improve the product significantly for a broad set of apps. Proposed must also satisfy the published [guidelines for .NET Core](#contribution-guidelines).
-
-Maintainers will not merge changes that have narrowly-defined benefits, due to compatibility risk. The CoreCLR codebase is used by several Microsoft products (e.g. Windows Phone, ASP.NET 5, .NET Framework 4.6) to enable execution of managed code. Changes to the open source codebase can become part of these products, but are first reviewed and tested to ensure they are correct for those products and will not inadvertently break applications. We may revert changes if they are found to be breaking.
-
-Contributing Ports
-==================
-
-We encourage ports of CoreCLR to other platforms. Linux and OS X ports are in progress and have a lot of momentum behind them. There is also interest in a [FreeBSD port](https://github.com/dotnet/coreclr/issues/455) (and OpenBSD and NetBSD).
-
-Ports have a weaker contribution bar, since they do not contribute to compatibility risk with existing Microsoft products on Windows. For ports, we are primarily looking for functionaly correct implementations.
-
-Contributing to mscorlib library
-================================
-
-Most managed code changes should be made in the [CoreFX](https://github.com/dotnet/corefx) repo. We have moved and are continuing to move many mscorlib types to CoreFX. Please use the following general rule-of-thumb for choosing the right repo to make your change (start by creating an issue):
-
-- The type or concept doesn't yet exist in .NET Core -> choose CoreFX.
-- The type exists in both CoreCLR and CoreFX repo -> choose CoreFX.
-- The type exists in CoreCLR only -> choose CoreCLR.
-- In doubt -> choose CoreFX.
-
-Please see [Breaking Changes](https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/breaking-changes.md) to understand our requirements on changes that could impact compatibility. Please pay the most attention to changes that affect the [Public Contract](https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/breaking-changes.md#bucket-1-public-contract). We will not accept changes that break compatibility.
-
 General Contribution Guidance
 =============================
 
@@ -81,7 +52,7 @@ changes during the course of your commits, please rebase them away before submit
 the PR.
 
 DOs and DON'Ts
-==============
+--------------
 
 * **DO** follow our [coding style](https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md) (C# code-specific)
 * **DO** give priority to the current style of the project or file you're changing even if it diverges from the general guidelines.
@@ -99,13 +70,62 @@ DOs and DON'Ts
 * **DON'T** submit PRs that alter licensing related files or headers. If you believe there's a problem with them, file an issue and we'll be happy to discuss it.
 * **DON'T** add API additions without filing an issue and discussing with us first. See [API Review Process](https://github.com/dotnet/corefx/blob/master/Documentation/project-docs/api-review-process.md).
 
+Contribution "Bar"
+==================
+
+Project maintainers will merge changes that align with [project priorities](project-priorities.md) and/or improve the product significantly for a broad set of apps. Proposals must also satisfy the published [guidelines for .NET Core](#contribution-guidelines).
+
+Maintainers will not merge changes that have narrowly-defined benefits, due to compatibility risk. The CoreCLR codebase is used by several Microsoft products (e.g. Windows Phone, ASP.NET Core, .NET Framework 4.x) to enable execution of managed code. Changes to the open source codebase can become part of these products, but are first reviewed and tested to ensure they are correct for those products and will not inadvertently break applications. We may revert changes if they are found to be breaking.
+
+Contributing Ports
+------------------
+
+We encourage ports of CoreCLR to other platforms. Linux and OS X ports are in progress and have a lot of momentum behind them. There is also interest in a [FreeBSD port](https://github.com/dotnet/coreclr/issues/455) (and OpenBSD and NetBSD).
+
+Ports have a weaker contribution bar, since they do not contribute to compatibility risk with existing Microsoft products on Windows. For ports, we are primarily looking for functionaly correct implementations.
+
+Contributing to mscorlib library
+--------------------------------
+
+Most managed code changes should be made in the [CoreFX](https://github.com/dotnet/corefx) repo. We have moved and are continuing to move many mscorlib types to CoreFX. Please use the following general rule-of-thumb for choosing the right repo to make your change (start by creating an issue):
+
+- The type or concept doesn't yet exist in .NET Core -> choose CoreFX.
+- The type exists in both CoreCLR and CoreFX repo -> choose CoreFX.
+- The type exists in CoreCLR only -> choose CoreCLR.
+- In doubt -> choose CoreFX.
+
+Please see [Breaking Changes](https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/breaking-changes.md) to understand our requirements on changes that could impact compatibility. Please pay the most attention to changes that affect the [Public Contract](https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/breaking-changes.md#bucket-1-public-contract). We will not accept changes that break compatibility.
+
+Licensing
+=========
+
+The .NET Core project sources are licensed as [MIT](../../LICENSE.TXT). The project contains source from other projects that may be licensed differently, which are called out in [3rd party notices](../../THIRD-PARTY-NOTICES).
+
+.NET Core binaries are produced and licensed separately. Microsoft produces a distribution of .NET Core licensed under the [.NET Library License](https://www.microsoft.com/net/dotnet_library_license.htm). Other groups or companies may produce their own distributions of .NET Core.
+
+Copyright
+---------
+
+The .NET Core project copyright is held by ".NET Foundation and Contributors" except where otherwise called out (see [3rd party notices](../../THIRD-PARTY-NOTICES)). Please read the [.NET Core license](../../LICENSE.TXT) to review the copyright.
+
+File Headers
+------------
+
+The following file header is the used for .NET Core. Please use it for new files.
+
+```
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+```
+
+The addition of existing files from other projects is handled on a case by case basis. 
+
 Contributor License Agreement
-=============================
+-----------------------------
 
 You must sign a [.NET Foundation Contribution License Agreement (CLA)](http://cla2.dotnetfoundation.org) before your PR will be merged. This a one-time requirement for projects in the .NET Foundation. You can read more about [Contribution License Agreements (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) on wikipedia.
 
-However, you don't have to do this up-front. You can simply clone, fork, and submit your pull-request as usual.
-
-When your pull-request is created, it is classified by a CLA bot. If the change is trivial, i.e. you just fixed a typo, then the PR is labelled with `cla-not-required`. Otherwise it's classified as `cla-required`. In that case, the system will also tell you how you can sign the CLA. Once you signed a CLA, the current and all future pull-requests will be labelled as `cla-signed`.
+Signing the CLA is super simple and can be done in less than a minute.
 
-Signing the CLA might sound scary but it's actually super simple and can be done in less than a minute.
+You don't have to do this up-front. You can simply clone, fork, and submit your pull-request as usual. When your pull-request is created, it is classified by a CLA bot. If the change is trivial (e.g. you just fixed a typo), then the PR is labelled with `cla-not-required`. Otherwise it's classified as `cla-required`. Once you signed a CLA, the current and all future pull-requests will be labelled as `cla-signed`.
index 7bb386e..99ae10b 100644 (file)
@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) Microsoft Corporation
+Copyright (c) .NET Foundation and Contributors
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
index c9dc5aa..7672bca 100644 (file)
@@ -559,6 +559,14 @@ combinedScenarios.each { scenario ->
                             switch (architecture) {
                                 case 'x64':
                                 case 'x86':
+
+                                    // This will shorten the output file path lengths
+                                    // if __TestIntermediateDir is already set, buildtest.cmd will
+                                    // output test binaries to that directory. If it is not set, the 
+                                    // binaries are sent to a default directory whose name is about
+                                    // 35 characters long.
+                                    buildCommands += "set __TestIntermediateDir=int"
+                                    
                                     if (scenario == 'default' || Constants.jitStressModeScenarios.containsKey(scenario)) {
                                         buildCommands += "build.cmd ${lowerConfiguration} ${architecture}"
                                     }
index cec0d8e..6e3f52e 100644 (file)
@@ -44,6 +44,7 @@ HRESULT CCoreCLRBinderHelper::DefaultBinderSetupContext(DWORD dwAppDomainId,CLRP
             if(SUCCEEDED(hr))
             {
                 pApplicationContext->SetAppDomainId(dwAppDomainId);
+                pBinder->SetManagedAssemblyLoadContext(NULL);
                 *ppTPABinder = clr::SafeAddRef(pBinder.Extract());
             }
         }
index ce54556..a9904e3 100644 (file)
@@ -86,8 +86,6 @@ public:
 
     void SetManagedAssemblyLoadContext(INT_PTR ptrManagedTPABinderInstance)
     {
-        _ASSERTE(m_ptrManagedAssemblyLoadContext == NULL);
-
         m_ptrManagedAssemblyLoadContext = ptrManagedTPABinderInstance;
     }
     
index 39e97b3..35df7e0 100644 (file)
@@ -15,6 +15,7 @@
 #include <stdint.h>
 #include <stddef.h>
 #include <stdio.h>
+#include <string.h>
 #include <wchar.h>
 #include <assert.h>
 #include <stdarg.h>
index fdfa0fc..83376f5 100644 (file)
 typedef uint32_t BOOL;
 typedef uint32_t DWORD;
 typedef void* LPVOID;
-typedef uint32_t UINT;
-typedef int32_t LONG;
-typedef uintptr_t ULONG_PTR;
-typedef void VOID;
-typedef void* PVOID;
-typedef void * LPSECURITY_ATTRIBUTES;
-typedef void const * LPCVOID;
-typedef wchar_t * PWSTR, *LPWSTR;
-typedef const wchar_t *LPCWSTR, *PCWSTR;
-typedef size_t SIZE_T;
-
-typedef void * HANDLE;
 
 // -----------------------------------------------------------------------------------------------------------
 // HRESULT subset.
@@ -105,14 +93,24 @@ inline HRESULT HRESULT_FROM_WIN32(unsigned long x)
 
 #define UNREFERENCED_PARAMETER(P)          (void)(P)
 
-#define INVALID_HANDLE_VALUE    ((HANDLE)-1)
-
 #ifdef PLATFORM_UNIX
 #define  _vsnprintf vsnprintf
 #define sprintf_s snprintf
 #define swprintf_s swprintf
 #endif
 
+#ifdef UNICODE
+#define _tcslen wcslen
+#define _tcscpy wcscpy
+#define _stprintf_s swprintf_s
+#define _tfopen _wfopen
+#else
+#define _tcslen strlen
+#define _tcscpy strcpy
+#define _stprintf_s sprintf_s
+#define _tfopen fopen
+#endif
+
 #define WINAPI __stdcall
 
 typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(void* lpThreadParameter);
@@ -123,12 +121,12 @@ typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(void* lpThreadParameter);
 
 #if defined(_MSC_VER) 
  #if defined(_ARM_)
-  
+
   __forceinline void YieldProcessor() { }
   extern "C" void __emit(const unsigned __int32 opcode);
   #pragma intrinsic(__emit)
   #define MemoryBarrier() { __emit(0xF3BF); __emit(0x8F5F); }
+
  #elif defined(_ARM64_)
 
   extern "C" void __yield(void);
@@ -141,26 +139,26 @@ typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(void* lpThreadParameter);
 
  #elif defined(_AMD64_)
   
-  extern "C" VOID
+  extern "C" void
   _mm_pause (
-      VOID
+      void
       );
   
-  extern "C" VOID
+  extern "C" void
   _mm_mfence (
-      VOID
+      void
       );
-  
+
   #pragma intrinsic(_mm_pause)
   #pragma intrinsic(_mm_mfence)
   
   #define YieldProcessor _mm_pause
   #define MemoryBarrier _mm_mfence
-  
+
  #elif defined(_X86_)
   
   #define YieldProcessor() __asm { rep nop }
-  
+
   __forceinline void MemoryBarrier()
   {
       int32_t Barrier;
@@ -168,7 +166,7 @@ typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)(void* lpThreadParameter);
           xchg Barrier, eax
       }
   }
-  
+
  #else // !_ARM_ && !_AMD64_ && !_X86_
   #error Unsupported architecture
  #endif
@@ -465,15 +463,6 @@ public:
 #ifdef FEATURE_REDHAWK
 typedef uint32_t (__stdcall *BackgroundCallback)(void* pCallbackContext);
 REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalStartBackgroundGCThread(BackgroundCallback callback, void* pCallbackContext);
-
-enum PalCapability
-{
-    WriteWatchCapability                = 0x00000001,   // GetWriteWatch() and friends
-    LowMemoryNotificationCapability     = 0x00000002,   // CreateMemoryResourceNotification() and friends
-    GetCurrentProcessorNumberCapability = 0x00000004,   // GetCurrentProcessorNumber()
-};
-
-REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalHasCapability(PalCapability capability);
 #endif // FEATURE_REDHAWK
 
 void DestroyThread(Thread * pThread);
@@ -530,7 +519,7 @@ namespace ETW
 
 #define LOG(x)
 
-VOID LogSpewAlways(const char *fmt, ...);
+void LogSpewAlways(const char *fmt, ...);
 
 #define LL_INFO10 4
 
@@ -581,7 +570,7 @@ public:
     typedef CLRConfigTypes ConfigStringInfo;
 
     static uint32_t GetConfigValue(ConfigDWORDInfo eType);
-    static HRESULT GetConfigValue(ConfigStringInfo /*eType*/, wchar_t * * outVal);
+    static HRESULT GetConfigValue(ConfigStringInfo /*eType*/, TCHAR * * outVal);
 };
 
 inline bool FitsInU1(uint64_t val)
index 62e171c..ea4ff88 100644 (file)
@@ -188,12 +188,12 @@ __forceinline T Interlocked::CompareExchangePointer(T volatile *destination, T e
 {
 #ifdef _MSC_VER
 #ifdef BIT64
-    return (T)(TADDR)_InterlockedCompareExchangePointer((void* volatile *)destination, exchange, comparand);
+    return (T)(TADDR)_InterlockedCompareExchangePointer((void* volatile *)destination, (void*)exchange, (void*)comparand);
 #else
     return (T)(TADDR)_InterlockedCompareExchange((long volatile *)(void* volatile *)destination, (long)(void*)exchange, (long)(void*)comparand);
 #endif
 #else
-    return (T)(TADDR)__sync_val_compare_and_swap((void* volatile *)destination, comparand, exchange);
+    return (T)(TADDR)__sync_val_compare_and_swap((void* volatile *)destination, (void*)comparand, (void*)exchange);
 #endif
 }
 
index c1ae87a..9ffd97b 100644 (file)
@@ -257,18 +257,6 @@ public:
     // Return:
     //  Time stamp in milliseconds
     static uint32_t GetLowPrecisionTimeStamp();
-
-    //
-    // File
-    //
-
-    // Open a file
-    // Parameters:
-    //  filename - name of the file to open
-    //  mode     - mode to open the file in (like in the CRT fopen)
-    // Return:
-    //  FILE* of the opened file
-    static FILE* OpenFile(const WCHAR* filename, const WCHAR* mode);
 };
 
 #endif // __GCENV_OS_H__
index 7c576a5..8593e5e 100644 (file)
@@ -33,6 +33,20 @@ typedef void * HANDLE;
 
 #ifdef PLATFORM_UNIX
 
+typedef char TCHAR;
+#define _T(s) s
+
+#else
+
+#ifndef _INC_WINDOWS
+typedef wchar_t TCHAR;
+#define _T(s) L##s
+#endif
+
+#endif
+
+#ifdef PLATFORM_UNIX
+
 class EEThreadId
 {
     pthread_t m_id;
@@ -76,7 +90,7 @@ public:
 
     void SetToCurrentThread()
     {
-        m_uiId = ::GetCurrentThreadId();        
+        m_uiId = ::GetCurrentThreadId();
     }
 
     void Clear()
index b329f89..0add1a9 100644 (file)
@@ -168,7 +168,7 @@ size_t GetHighPrecisionTimeStamp()
 GCStatistics g_GCStatistics;
 GCStatistics g_LastGCStatistics;
 
-WCHAR* GCStatistics::logFileName = NULL;
+TCHAR* GCStatistics::logFileName = NULL;
 FILE*  GCStatistics::logFile = NULL;
 
 void GCStatistics::AddGCStats(const gc_mechanisms& settings, size_t timeInMSec)
@@ -9507,21 +9507,22 @@ void gc_heap::adjust_ephemeral_limits ()
 FILE* CreateLogFile(const CLRConfig::ConfigStringInfo & info, BOOL is_config)
 {
     FILE* logFile;
-    LPWSTR  temp_logfile_name = NULL;
+    TCHAR * temp_logfile_name = NULL;
     CLRConfig::GetConfigValue(info, &temp_logfile_name);
 
-    WCHAR logfile_name[MAX_LONGPATH+1];
+    TCHAR logfile_name[MAX_LONGPATH+1];
     if (temp_logfile_name != 0)
     {
-        wcscpy(logfile_name, temp_logfile_name);
+        _tcscpy(logfile_name, temp_logfile_name);
     }
 
-    size_t logfile_name_len = wcslen(logfile_name);
-    WCHAR* szPid = logfile_name + logfile_name_len;
+    size_t logfile_name_len = _tcslen(logfile_name);
+    TCHAR* szPid = logfile_name + logfile_name_len;
     size_t remaining_space = MAX_LONGPATH + 1 - logfile_name_len;
-    swprintf_s(szPid, remaining_space, W(".%d%s"), GCToOSInterface::GetCurrentProcessId(), (is_config ? W(".config.log") : W(".log")));
 
-    logFile = GCToOSInterface::OpenFile(logfile_name, W("wb"));
+    _stprintf_s(szPid, remaining_space, _T(".%d%s"), GCToOSInterface::GetCurrentProcessId(), (is_config ? _T(".config.log") : _T(".log")));
+
+    logFile = _tfopen(logfile_name, _T("wb"));
 
     delete temp_logfile_name;
 
@@ -9614,9 +9615,8 @@ HRESULT gc_heap::initialize_gc (size_t segment_size,
     GCStatistics::logFileName = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_GCMixLog);
     if (GCStatistics::logFileName != NULL)
     {
-        GCStatistics::logFile = GCToOSInterface::OpenFile((LPCWSTR)GCStatistics::logFileName, W("a"));
+        GCStatistics::logFile = _tfopen(GCStatistics::logFileName, _T("a"));
     }
-
 #endif // GC_STATS
 
     HRESULT hres = S_OK;
@@ -14567,7 +14567,7 @@ int gc_heap::generation_to_condemn (int n_initial,
         // Need to get it early enough for all heaps to use.
         available_physical_mem = ms.ullAvailPhys;
         local_settings->entry_memory_load = ms.dwMemoryLoad;
-        
+
         // @TODO: Force compaction more often under GCSTRESS
         if (ms.dwMemoryLoad >= high_memory_load_th || low_memory_detected)
         {
index 498c3be..8da9690 100755 (executable)
@@ -421,7 +421,7 @@ BOOL ProfilerShouldTrackConditionalWeakTableElements() {
 #if defined(GC_PROFILING)
     return CORProfilerTrackConditionalWeakTableElements();
 #else
-        return FALSE;
+    return FALSE;
 #endif // defined (GC_PROFILING)
 }
 
index fe40c0c..9aa864a 100644 (file)
@@ -611,7 +611,7 @@ struct GCStatistics
     : public StatisticsBase
 {
     // initialized to the contents of COMPLUS_GcMixLog, or NULL, if not present
-    static WCHAR* logFileName;
+    static TCHAR* logFileName;
     static FILE*  logFile;
 
     // number of times we executed a background GC, a foreground GC, or a
index 7ded783..597aeb9 100644 (file)
@@ -391,7 +391,7 @@ void ValidateFetchObjrefForHandle(OBJECTREF objref, ADIndex appDomainIndex)
     _ASSERTE(!pDomain->NoAccessToHandleTable());
 
 #if CHECK_APP_DOMAIN_LEAKS
-       if (g_pConfig->AppDomainLeaks() && objref != NULL)
+    if (g_pConfig->AppDomainLeaks() && objref != NULL)
     {
         if (appDomainIndex.m_dwIndex)
             objref->TryAssignAppDomain(pDomain);
index a46f9ae..45cdbb2 100644 (file)
@@ -22,6 +22,7 @@ set(SOURCES
 if(WIN32)
     list(APPEND SOURCES
         gcenv.windows.cpp)
+    add_definitions(-DUNICODE=1)
 else()
     list(APPEND SOURCES
         gcenv.unix.cpp)
index e17bb83..cc809e7 100644 (file)
@@ -250,7 +250,7 @@ void StompWriteBarrierResize(bool /*bReqUpperBoundsCheck*/)
 {
 }
 
-VOID LogSpewAlways(const char * /*fmt*/, ...)
+void LogSpewAlways(const char * /*fmt*/, ...)
 {
 }
 
@@ -282,7 +282,7 @@ uint32_t CLRConfig::GetConfigValue(ConfigDWORDInfo eType)
     }
 }
 
-HRESULT CLRConfig::GetConfigValue(ConfigStringInfo /*eType*/, wchar_t * * outVal)
+HRESULT CLRConfig::GetConfigValue(ConfigStringInfo /*eType*/, TCHAR * * outVal)
 {
     *outVal = NULL;
     return 0;
index c09d012..9920f69 100644 (file)
@@ -16,9 +16,6 @@
 #define _ASSERTE(_expr) ASSERT(_expr)
 #endif
 
-typedef wchar_t WCHAR;
-#define W(s) L##s
-
 #include "gcenv.structs.h"
 #include "gcenv.base.h"
 #include "gcenv.ee.h"
index f3c502c..51ae723 100644 (file)
@@ -307,12 +307,6 @@ bool IsGCSpecialThread()
 
 #endif // 0
 
-bool PalHasCapability(PalCapability capability)
-{
-    // TODO: Implement for background GC
-    return false;
-}
-
 WINBASEAPI
 UINT
 WINAPI
index bce8496..7015770 100644 (file)
@@ -85,7 +85,7 @@ bool GCToOSInterface::SetCurrentThreadIdealAffinity(GCThreadAffinity* affinity)
         proc.Group = (WORD)affinity->Group;
         proc.Number = (BYTE)affinity->Processor;
         proc.Reserved = 0;
-        
+
         success = !!SetThreadIdealProcessorEx(GetCurrentThread(), &proc, NULL);
     }
     else
@@ -94,7 +94,7 @@ bool GCToOSInterface::SetCurrentThreadIdealAffinity(GCThreadAffinity* affinity)
         {
             proc.Number = affinity->Processor;
             success = !!SetThreadIdealProcessorEx(GetCurrentThread(), &proc, NULL);
-        }        
+        }
     }
 #endif
 
@@ -414,17 +414,6 @@ bool GCToOSInterface::CreateThread(GCThreadFunction function, void* param, GCThr
     return true;
 }
 
-// Open a file
-// Parameters:
-//  filename - name of the file to open
-//  mode     - mode to open the file in (like in the CRT fopen)
-// Return:
-//  FILE* of the opened file
-FILE* GCToOSInterface::OpenFile(const WCHAR* filename, const WCHAR* mode)
-{
-    return _wfopen(filename, mode);
-}
-
 // Initialize the critical section
 void CLRCriticalSection::Initialize()
 {
index 3d1a8fa..f8c3ac9 100644 (file)
@@ -82,12 +82,8 @@ extern int RFS_HashStack();
 
 void ClrFlsAssociateCallback(DWORD slot, PTLS_CALLBACK_FUNCTION callback);
 
-// Function pointer for fast TLS fetch - do not use directly
-typedef LPVOID (*POPTIMIZEDTLSGETTER)();
-
 typedef LPVOID* (*CLRFLSGETBLOCK)();
-
-extern POPTIMIZEDTLSGETTER __ClrFlsGetBlock;
+extern CLRFLSGETBLOCK __ClrFlsGetBlock;
 
 #ifndef CLR_STANDALONE_BINDER
 // Combining getter/setter into a single call
@@ -101,8 +97,7 @@ inline void ClrFlsIncrementValue(DWORD slot, int increment)
 
     _ASSERTE(increment != 0);
     
-    CLRFLSGETBLOCK clrFlsGetBlockFn = (CLRFLSGETBLOCK)__ClrFlsGetBlock;
-    void **block = (*clrFlsGetBlockFn)();
+    void **block = (*__ClrFlsGetBlock)();
     size_t value;
 
     if (block != NULL)
@@ -137,9 +132,8 @@ inline void * ClrFlsGetValue (DWORD slot)
     STATIC_CONTRACT_CANNOT_TAKE_LOCK;
     STATIC_CONTRACT_SO_TOLERANT;
 
-    CLRFLSGETBLOCK clrFlsGetBlockFn = (CLRFLSGETBLOCK)__ClrFlsGetBlock;
-    void **block = (*clrFlsGetBlockFn)();
-    if (block != NULL)
+       void **block = (*__ClrFlsGetBlock)();
+       if (block != NULL)
     {
         return block[slot];
     }
@@ -163,9 +157,8 @@ inline BOOL ClrFlsCheckValue(DWORD slot, void ** pValue)
 #ifdef _DEBUG
     *pValue = ULongToPtr(0xcccccccc);
 #endif //_DEBUG 
-    CLRFLSGETBLOCK clrFlsGetBlockFn = (CLRFLSGETBLOCK)__ClrFlsGetBlock;
-    void **block = (*clrFlsGetBlockFn)();
-    if (block != NULL)
+       void **block = (*__ClrFlsGetBlock)();
+       if (block != NULL)
     {
         *pValue = block[slot];
         return TRUE;    
@@ -186,9 +179,8 @@ inline void ClrFlsSetValue(DWORD slot, void *pData)
     STATIC_CONTRACT_CANNOT_TAKE_LOCK;
     STATIC_CONTRACT_SO_TOLERANT;
 
-    CLRFLSGETBLOCK clrFlsGetBlockFn = (CLRFLSGETBLOCK)__ClrFlsGetBlock;
-    void **block = (*clrFlsGetBlockFn)();
-    if (block != NULL)
+       void **block = (*__ClrFlsGetBlock)();
+       if (block != NULL)
     {
         block[slot] = pData;
     }
index c0c43eb..00940eb 100644 (file)
 #endif // FEATURE_CORESYSTEM
 
 #ifndef _T
-#define _T(str) L ## str
+#define _T(str) W(str)
 #endif
 
 
index 2426a7a..01d6085 100644 (file)
@@ -7914,7 +7914,7 @@ CodeGen::genIntrinsic(GenTreePtr treeNode)
 unsigned
 CodeGen::getFirstArgWithStackSlot()
 {
-#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
+#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
     unsigned baseVarNum = compiler->lvaFirstStackIncomingArgNum;
 
     if (compiler->lvaFirstStackIncomingArgNum != BAD_VAR_NUM)
@@ -7942,11 +7942,11 @@ CodeGen::getFirstArgWithStackSlot()
     }
 
     return baseVarNum;
-#elif _TARGET_AMD64_
+#elif defined(_TARGET_AMD64_)
     return 0;
 #else
     // Not implemented for x86.
-     NYI_X86("getFirstArgWithStackSlot not yet implemented for x86.");
+    NYI_X86("getFirstArgWithStackSlot not yet implemented for x86.");
     return BAD_VAR_NUM;
 #endif // !FEATURE_UNIX_AMD64_STRUCT_PASSING
 }
index 7af7c09..d99cf1a 100755 (executable)
@@ -3097,7 +3097,7 @@ GenTreePtr      Compiler::impIntrinsic(CORINFO_CLASS_HANDLE     clsHnd,
         return op1;
 
 
-#ifndef _TARGET_ARM_
+#ifdef _TARGET_XARCH_
         // TODO-ARM-CQ: reenable treating Interlocked operation as intrinsic
     case CORINFO_INTRINSIC_InterlockedAdd32:
         interlockedOperator = GT_LOCKADD; goto InterlockedBinOpCommon;
@@ -3135,7 +3135,7 @@ InterlockedBinOpCommon:
         op1 = gtNewOperNode(interlockedOperator, genActualType(callType), op1, op2);
         op1->gtFlags |= GTF_GLOB_EFFECT;
         return op1;
-#endif
+#endif // _TARGET_XARCH_
 
     case CORINFO_INTRINSIC_MemoryBarrier:
 
index fc22a69..becba53 100644 (file)
@@ -1116,14 +1116,14 @@ void                Compiler::fgExtendDbgLifetimes()
         }
     }
 
-    /* raMarkStkVars() reserves stack space for unused variables (which
-       needs to be initialized). However, arguments don't need to be initialized.
-       So just ensure that they don't have a 0 ref cnt */
+    // raMarkStkVars() reserves stack space for unused variables (which
+    //   needs to be initialized). However, arguments don't need to be initialized.
+    //   So just ensure that they don't have a 0 ref cnt
 
     unsigned lclNum = 0;
     for (LclVarDsc* varDsc = lvaTable; lclNum < lvaCount; lclNum++, varDsc++)
     {
-        if (varDsc->lvRefCnt == 0 && varDsc->lvArgReg)
+        if (varDsc->lvRefCnt == 0 && varDsc->lvIsRegArg)
         {
             varDsc->lvRefCnt = 1;
         }
index 2479505..7939fde 100644 (file)
@@ -372,19 +372,23 @@ namespace System {
                 char* a = ap;
                 char* b = bp;
 
-                // unroll the loop
-#if AMD64
+#if WIN64
+                // Single int read aligns pointers for the following long reads
+                // PERF: No length check needed as there is always an int32 worth of string allocated
+                //       This read can also include the null terminator which both strings will have
+                if (*(int*)a != *(int*)b) return false;
+                length -= 2; a += 2; b += 2;
+
                 // for AMD64 bit platform we unroll by 12 and
                 // check 3 qword at a time. This is less code
                 // than the 32 bit case and is a shorter path length.
-                // Reads are unaligned
 
                 while (length >= 12)
                 {
                     if (*(long*)a     != *(long*)b) return false;
                     if (*(long*)(a+4) != *(long*)(b+4)) return false;
                     if (*(long*)(a+8) != *(long*)(b+8)) return false;
-                    a += 12; b += 12; length -= 12;
+                    length -= 12; a += 12; b += 12;
                 }
 #else
                 while (length >= 10)
@@ -394,7 +398,7 @@ namespace System {
                     if (*(int*)(a+4) != *(int*)(b+4)) return false;
                     if (*(int*)(a+6) != *(int*)(b+6)) return false;
                     if (*(int*)(a+8) != *(int*)(b+8)) return false;
-                    a += 10; b += 10; length -= 10;
+                    length -= 10; a += 10; b += 10;
                 }
 #endif
 
@@ -405,13 +409,70 @@ namespace System {
                 while (length > 0) 
                 {
                     if (*(int*)a != *(int*)b) break;
-                    a += 2; b += 2; length -= 2;
+                    length -= 2; a += 2; b += 2;
                 }
 
                 return (length <= 0);
             }
         }
-        
+
+        [System.Security.SecuritySafeCritical]  // auto-generated
+        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+        private unsafe static bool StartsWithOrdinalHelper(String str, String startsWith)
+        {
+            Contract.Requires(str != null);
+            Contract.Requires(startsWith != null);
+            Contract.Requires(str.Length >= startsWith.Length);
+
+            int length = startsWith.Length;
+
+            fixed (char* ap = &str.m_firstChar) fixed (char* bp = &startsWith.m_firstChar)
+            {
+                char* a = ap;
+                char* b = bp;
+
+#if WIN64
+                // Single int read aligns pointers for the following long reads
+                // No length check needed as this method is called when length >= 2
+                Contract.Assert(length >= 2);
+                if (*(int*)a != *(int*)b) goto ReturnFalse;
+                length -= 2; a += 2; b += 2;
+
+                while (length >= 12)
+                {
+                    if (*(long*)a != *(long*)b) goto ReturnFalse;
+                    if (*(long*)(a + 4) != *(long*)(b + 4)) goto ReturnFalse;
+                    if (*(long*)(a + 8) != *(long*)(b + 8)) goto ReturnFalse;
+                    length -= 12; a += 12; b += 12;
+                }
+#else
+                while (length >= 10)
+                {
+                    if (*(int*)a != *(int*)b) goto ReturnFalse;
+                    if (*(int*)(a+2) != *(int*)(b+2)) goto ReturnFalse;
+                    if (*(int*)(a+4) != *(int*)(b+4)) goto ReturnFalse;
+                    if (*(int*)(a+6) != *(int*)(b+6)) goto ReturnFalse;
+                    if (*(int*)(a+8) != *(int*)(b+8)) goto ReturnFalse;
+                    length -= 10; a += 10; b += 10;
+                }
+#endif
+
+                while (length >= 2)
+                {
+                    if (*(int*)a != *(int*)b) goto ReturnFalse;
+                    length -= 2; a += 2; b += 2;
+                }
+
+                // PERF: This depends on the fact that the String objects are always zero terminated 
+                // and that the terminating zero is not included in the length. For even string sizes
+                // this compare can include the zero terminator. Bitwise OR avoids a branch.
+                return length == 0 | *a == *b;
+
+                ReturnFalse:
+                return false;
+            }
+        }
+
         [System.Security.SecuritySafeCritical]  // auto-generated
         private unsafe static int CompareOrdinalHelper(String strA, String strB)
         {
@@ -453,9 +514,9 @@ namespace System {
                         diffOffset = 8;
                         break;
                     }
+                    length -= 10;
                     a += 10; 
                     b += 10; 
-                    length -= 10;
                 }
 
                 if( diffOffset != -1) {
@@ -479,9 +540,9 @@ namespace System {
                     if (*(int*)a != *(int*)b) {
                         break;
                     }
+                    length -= 2;
                     a += 2; 
                     b += 2; 
-                    length -= 2;
                 }
 
                 if( length > 0) { 
@@ -2559,7 +2620,7 @@ namespace System {
                     }
                     return (value.Length == 1) ?
                             true :                 // First char is the same and thats all there is to compare
-                            (nativeCompareOrdinalEx(this, 0, value, 0, value.Length) == 0);
+                            StartsWithOrdinalHelper(this, value);
 
                 case StringComparison.OrdinalIgnoreCase:
                     if( this.Length < value.Length) {
index c4548f3..26cdfe1 100644 (file)
@@ -3471,33 +3471,58 @@ namespace System {
             // fall back to reading from the local machine 
             // when the cache is not fully populated               
             if (!cachedData.m_allSystemTimeZonesRead) {
+                result = TryGetTimeZoneFromLocalMachine(id, dstDisabled, out value, out e, cachedData);
+            }
+#if PLATFORM_UNIX
+            // On UNIX, there may be some tzfiles that aren't in the zones.tab file, and thus aren't returned from GetSystemTimeZones().
+            // If a caller asks for one of these zones before calling GetSystemTimeZones(), the time zone is returned successfully. But if
+            // GetSystemTimeZones() is called first, FindSystemTimeZoneById will throw TimeZoneNotFoundException, which is inconsistent.
+            // To fix this, even if m_allSystemTimeZonesRead is true, try reading the tzfile from disk, but don't add the time zone to the
+            // list returned from GetSystemTimeZones(). These time zones will only be available if asked for directly.
+            else {
+                result = TryGetTimeZoneFromLocalMachine(id, dstDisabled, out value, out e, cachedData);
+            }
+#else
+            else {
+                result = TimeZoneInfoResult.TimeZoneNotFoundException;
+                value = null;
+            }
+#endif // PLATFORM_UNIX
+
+            return result;
+        }
+
+        private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachine(string id, bool dstDisabled, out TimeZoneInfo value, out Exception e, CachedData cachedData)
+        {
+            TimeZoneInfoResult result;
+            TimeZoneInfo match;
+
 #if FEATURE_WIN32_REGISTRY
-                result = TryGetTimeZoneByRegistryKey(id, out match, out e);
+            result = TryGetTimeZoneByRegistryKey(id, out match, out e);
 #elif PLATFORM_UNIX
-                result = TryGetTimeZoneByFile(id, out match, out e);
+            result = TryGetTimeZoneByFile(id, out match, out e);
 #endif // FEATURE_WIN32_REGISTRY
 
-                if (result == TimeZoneInfoResult.Success) {
-                    if (cachedData.m_systemTimeZones == null)
-                        cachedData.m_systemTimeZones = new Dictionary<string, TimeZoneInfo>();
+            if (result == TimeZoneInfoResult.Success)
+            {
+                if (cachedData.m_systemTimeZones == null)
+                    cachedData.m_systemTimeZones = new Dictionary<string, TimeZoneInfo>();
 
-                    cachedData.m_systemTimeZones.Add(id, match);
+                cachedData.m_systemTimeZones.Add(id, match);
 
-                    if (dstDisabled && match.m_supportsDaylightSavingTime) {
-                        // we found a cache hit but we want a time zone without DST and this one has DST data
-                        value = CreateCustomTimeZone(match.m_id, match.m_baseUtcOffset, match.m_displayName, match.m_standardDisplayName);
-                    }
-                    else {
-                        value = new TimeZoneInfo(match.m_id, match.m_baseUtcOffset, match.m_displayName, match.m_standardDisplayName,
-                                              match.m_daylightDisplayName, match.m_adjustmentRules, false);
-                    }
+                if (dstDisabled && match.m_supportsDaylightSavingTime)
+                {
+                    // we found a cache hit but we want a time zone without DST and this one has DST data
+                    value = CreateCustomTimeZone(match.m_id, match.m_baseUtcOffset, match.m_displayName, match.m_standardDisplayName);
                 }
-                else {
-                    value = null;
+                else
+                {
+                    value = new TimeZoneInfo(match.m_id, match.m_baseUtcOffset, match.m_displayName, match.m_standardDisplayName,
+                                          match.m_daylightDisplayName, match.m_adjustmentRules, false);
                 }
             }
-            else {
-                result = TimeZoneInfoResult.TimeZoneNotFoundException;
+            else
+            {
                 value = null;
             }
 
index 26aeb70..b055407 100644 (file)
@@ -18,9 +18,9 @@
 #include "unixasmmacros.inc"
 
 #if defined(__x86_64__)
-#define PAL_DISPATCHEXCEPTION __Z21PAL_DispatchExceptionmmmmmmP8_CONTEXTP17_EXCEPTION_RECORD
+#define PAL_DISPATCHEXCEPTION __Z21PAL_DispatchExceptionmmmmmmP8_CONTEXTP17_EXCEPTION_RECORDP11MachMessage
 #else //!defined(_AMD64_)
-#define PAL_DISPATCHEXCEPTION __Z21PAL_DispatchExceptionP8_CONTEXTP17_EXCEPTION_RECORD
+#define PAL_DISPATCHEXCEPTION __Z21PAL_DispatchExceptionP8_CONTEXTP17_EXCEPTION_RECORDP11MachMessage
 #endif // defined(_AMD64_)
 
 // Offset of the return address from the PAL_DISPATCHEXCEPTION in the PAL_DispatchExceptionWrapper
@@ -34,13 +34,14 @@ C_FUNC(PAL_DispatchExceptionReturnOffset):
 // unwinding behavior is equivalent to any standard function having
 // an ebp frame. It is analogous to the following source file.
 // 
-// void PAL_DispatchException(CONTEXT *pContext, EXCEPTION_RECORD *pExceptionRecord);
+// void PAL_DispatchException(CONTEXT *pContext, EXCEPTION_RECORD *pExceptionRecord, MachMessage *pMessage);
 // 
 // extern "C" void PAL_DispatchExceptionWrapper()
 // {
 //     CONTEXT Context;
 //     EXCEPTION_RECORD ExceptionRecord;
-//     PAL_DispatchException(&Context, &ExceptionRecord);
+//     MachMessage Message;
+//     PAL_DispatchException(&Context, &ExceptionRecord, &Message);
 // }
 //
 
index 854b8b3..d710872 100644 (file)
@@ -48,50 +48,13 @@ using namespace CorUnix;
 
 SET_DEFAULT_DEBUG_CHANNEL(EXCEPT);
 
-#if !DISABLE_EXCEPTIONS
+void ForwardMachException(CPalThread *pThread, MachMessage *pMessage);
+
 // The port we use to handle exceptions and to set the thread context
 mach_port_t s_ExceptionPort;
 
-// Since we now forward some exception notifications to previous handlers we need to be able to wait on more
-// than one port at a time (to intercept and forward replies from these forwarded notifications). Therefore we
-// listen on a port set rather than a single port (the port above is one member, the initial one, of this port
-// set).
-static mach_port_t s_ExceptionPortSet;
-
-// We also allow hosts to reset the exception handler on a thread so that can raise the chance their
-// exceptions aren't handled or swallowed by another component (perhaps one that doesn't chain back to
-// previous handlers like we do). In order to avoid stomping any previous handler we recorded when first
-// setting up the thread we actually keep two sets of chain-back information: one for the bottom of the thread
-// (chaining back to code that set up a handler before we did) and one for the top (chaining back to code that
-// set up a handler after we did). We also allocate a second exception port for this latter case (which we put
-// in the port set above so we can wait on both simultaneously). This allows us to distinguish where the
-// exception was raised from since it's possible, for example, for an exception forwarded by us near the top
-// of the stack to re-enter us for bottom registration and we want to chain back to the bottom handler in
-// those situations rather than falsely claiming a handler cycle. This way we should be able to support a
-// number of different handler scenarios with close to perfect semantics.
-mach_port_t s_TopExceptionPort;
-
 static BOOL s_DebugInitialized = FALSE;
 
-// To better support side-by-side use of the process we forward any exceptions we don't understand to the
-// previous handler registered for the exception (if there is one). We need to keep track of all the
-// notifications we've forwarded so we can forward the eventual reply back to the original sender (the reply
-// doesn't contain enough context for us to do this without this additional context). The structure below
-// holds all the context necessary for a single forwarded notification and is held on a singly linked list by
-// the exception thread.
-struct ForwardedNotification
-{
-    ForwardedNotification      *m_pNext;                // Pointer to the next forward record or NULL
-    mach_port_t                 m_hListenReplyPort;     // We listen to this port for a reply
-    mach_port_t                 m_hForwardReplyPort;    // Forward the reply to this port
-    thread_act_t                m_hTargetThread;        // Thread which caused the exception
-    MachMessage::MessageType    m_eNotificationType;    // Message type of the original notification
-    thread_state_flavor_t       m_eNotificationFlavor;  // Thread state flavor used in the original notification
-    bool                        m_fTopException;        // Was this notification delivered to the "top" handler?
-};
-
-#endif // !DISABLE_EXCEPTIONS
-
 static const char * PAL_MACH_EXCEPTION_MODE = "PAL_MachExceptionMode";
 
 enum MachExceptionMode
@@ -184,16 +147,16 @@ static exception_mask_t GetExceptionMask()
         {                                                               \
             PAL_EnterHolder enterHolder;                                \
             PAL_printf(__VA_ARGS__);                                    \
-            PAL_DisplayDialogFormatted("NON-PAL RETAIL ASSERT", __VA_ARGS__); \
+            PAL_DisplayDialogFormatted("NON-PAL ASSERT", __VA_ARGS__);  \
         }                                                               \
         DBG_DebugBreak();                                               \
         abort();                                                        \
     }
 
-#define CHECK_MACH(function, MachRet)                                   \
-    if (MachRet != KERN_SUCCESS)                                        \
+#define CHECK_MACH(function, machret)                                   \
+    if (machret != KERN_SUCCESS)                                        \
     {                                                                   \
-        NONPAL_RETAIL_ASSERT(function " failed: %08X: %s\n", MachRet, mach_error_string(MachRet)); \
+        NONPAL_RETAIL_ASSERT(function " failed: %08X: %s\n", machret, mach_error_string(machret)); \
     }
 
 #ifdef FEATURE_PAL_SXS
@@ -211,11 +174,8 @@ Return value :
     ERROR_SUCCESS, if enabling succeeded
     an error code, otherwise
 --*/
-
-
 PAL_ERROR CorUnix::CPalThread::EnableMachExceptions()
 {
-#if !DISABLE_EXCEPTIONS
     TRACE("%08X: Enter()\n", (unsigned int)(size_t)this);
 
     exception_mask_t machExceptionMask = GetExceptionMask();
@@ -238,19 +198,11 @@ PAL_ERROR CorUnix::CPalThread::EnableMachExceptions()
         }
 #endif // _DEBUG
 
-        // We could be called in two situations:
-        //   1) The CoreCLR has seen this thread for the first time.
-        //   2) The host has called ICLRRuntimeHost2::RegisterMacEHPort().
         // We store a set of previous handlers and register an exception port that is unique to both (to help
         // us get the correct chain-back semantics in as many scenarios as possible). The following call tells
         // us which we should do.
-        mach_port_t hExceptionPort;
-        CThreadMachExceptionHandlerNode *pSavedHandlers =
-            m_sMachExceptionHandlers.GetNodeForInitialization(&hExceptionPort);
-        
-        NONPAL_TRACE("Enabling %s handlers for thread %08X\n",
-                     hExceptionPort == s_TopExceptionPort ? "top" : "bottom",
-                     GetMachPortSelf());
+        CThreadMachExceptionHandlerNode *pSavedHandlers = m_sMachExceptionHandlers.GetNodeForInitialization();
+        NONPAL_TRACE("Enabling handlers for thread %08X exception port %08X\n", GetMachPortSelf(), s_ExceptionPort);
 
         // Swap current handlers into temporary storage first. That's because it's possible (even likely) that
         // some or all of the handlers might still be ours. In those cases we don't want to overwrite the
@@ -266,7 +218,7 @@ PAL_ERROR CorUnix::CPalThread::EnableMachExceptions()
 
         MachRet = thread_swap_exception_ports(thread,
                                               machExceptionMask,
-                                              hExceptionPort,
+                                              s_ExceptionPort,
                                               excepBehavior,
                                               MACHINE_THREAD_STATE,
                                               rgMasks,
@@ -274,8 +226,10 @@ PAL_ERROR CorUnix::CPalThread::EnableMachExceptions()
                                               rgHandlers,
                                               rgBehaviors,
                                               rgFlavors);
+
         kern_return_t MachRetDeallocate = mach_port_deallocate(mach_task_self(), thread);
         CHECK_MACH("mach_port_deallocate", MachRetDeallocate);
+
         if (MachRet != KERN_SUCCESS)
         {
             ASSERT("thread_swap_exception_ports failed: %d\n", MachRet);
@@ -285,7 +239,7 @@ PAL_ERROR CorUnix::CPalThread::EnableMachExceptions()
         // Scan through the returned handlers looking for those that are ours.
         for (mach_msg_type_number_t i = 0; i < oldCount; i++)
         {
-            if (rgHandlers[i] == s_ExceptionPort || rgHandlers[i] == s_TopExceptionPort)
+            if (rgHandlers[i] == s_ExceptionPort)
             {
                 // We were already registered for the exceptions indicated by rgMasks[i]. Look through each
                 // exception (set bit in the mask) separately, checking whether we previously had a (non-CLR)
@@ -306,8 +260,7 @@ PAL_ERROR CorUnix::CPalThread::EnableMachExceptions()
                             continue;
 
                         // Found one. By definition it shouldn't be one of our handlers.
-                        if (pSavedHandlers->m_handlers[k] == s_ExceptionPort ||
-                            pSavedHandlers->m_handlers[k] == s_TopExceptionPort)
+                        if (pSavedHandlers->m_handlers[k] == s_ExceptionPort)
                             ASSERT("Stored our own handlers in Mach exception chain-back info.\n");
 
                         // We need to replicate the handling details back into our temporary data in place of
@@ -374,7 +327,6 @@ PAL_ERROR CorUnix::CPalThread::EnableMachExceptions()
         memcpy(pSavedHandlers->m_behaviors, rgBehaviors, sizeof(rgBehaviors));
         memcpy(pSavedHandlers->m_flavors, rgFlavors, sizeof(rgFlavors));
     }
-#endif // !DISABLE_EXCEPTIONS
     return ERROR_SUCCESS;
 }
 
@@ -393,7 +345,6 @@ Return value :
 --*/
 PAL_ERROR CorUnix::CPalThread::DisableMachExceptions()
 {
-#if !DISABLE_EXCEPTIONS
     TRACE("%08X: Leave()\n", (unsigned int)(size_t)this);
 
     PAL_ERROR palError = NO_ERROR;
@@ -442,7 +393,6 @@ PAL_ERROR CorUnix::CPalThread::DisableMachExceptions()
     }
 
     return palError;
-#endif // !DISABLE_EXCEPTIONS
 }
 
 #else // FEATURE_PAL_SXS
@@ -461,7 +411,6 @@ Return value :
 --*/
 BOOL SEHEnableMachExceptions()
 {
-#if !DISABLE_EXCEPTIONS
     exception_mask_t machExceptionMask = GetExceptionMask();
     if (machExceptionMask != 0)
     {
@@ -479,7 +428,6 @@ BOOL SEHEnableMachExceptions()
             return FALSE;
         }
     }
-#endif // !DISABLE_EXCEPTIONS
     return TRUE;
 }
 
@@ -497,7 +445,6 @@ Return value :
 --*/
 BOOL SEHDisableMachExceptions()
 {
-#if !DISABLE_EXCEPTIONS
     exception_mask_t machExceptionMask = GetExceptionMask();
     if (machExceptionMask != 0)
     {
@@ -516,20 +463,19 @@ BOOL SEHDisableMachExceptions()
         }
     }
     return TRUE;
-#endif // !DISABLE_EXCEPTIONS
 }
 
 #endif // FEATURE_PAL_SXS
 
-#if !DISABLE_EXCEPTIONS
 #if !defined(_AMD64_)
-void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord)
+void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachMessage *pMessage)
 #else // defined(_AMD64_)
 
-// Since catch_exception_raise pushed the context and exception record on the stack, we need to adjust the signature
-// of PAL_DispatchException such that the corresponding arguments are considered to be on the stack per GCC64 calling
-// convention rules. Hence, the first 6 dummy arguments (corresponding to RDI, RSI, RDX,RCX, R8, R9).
-void PAL_DispatchException(DWORD64 dwRDI, DWORD64 dwRSI, DWORD64 dwRDX, DWORD64 dwRCX, DWORD64 dwR8, DWORD64 dwR9, PCONTEXT pContext, PEXCEPTION_RECORD pExRecord)
+// Since HijackFaultingThread pushed the context, exception record and mach exception message on the stack,
+// we need to adjust the signature of PAL_DispatchException such that the corresponding arguments are considered
+// to be on the stack per GCC64 calling convention rules. Hence, the first 6 dummy arguments (corresponding to RDI,
+// RSI, RDX,RCX, R8, R9).
+void PAL_DispatchException(DWORD64 dwRDI, DWORD64 dwRSI, DWORD64 dwRDX, DWORD64 dwRCX, DWORD64 dwR8, DWORD64 dwR9, PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachMessage *pMessage)
 #endif // !defined(_AMD64_)
 {
     CPalThread *pThread = InternalGetCurrentThread();
@@ -548,8 +494,11 @@ void PAL_DispatchException(DWORD64 dwRDI, DWORD64 dwRSI, DWORD64 dwRDX, DWORD64
     pointers.ExceptionRecord = pExRecord;
     pointers.ContextRecord = pContext;
 
-    NONPAL_TRACE("PAL_DispatchException(EC %08x EA %p)\n", pExRecord->ExceptionCode, pExRecord->ExceptionAddress);
+    TRACE("PAL_DispatchException(EC %08x EA %p)\n", pExRecord->ExceptionCode, pExRecord->ExceptionAddress);
     SEHProcessException(&pointers);
+
+    // Chain the exception to the next PAL
+    ForwardMachException(pThread, pMessage);
 }
 
 #if defined(_X86_) || defined(_AMD64_)
@@ -559,93 +508,99 @@ extern "C" int PAL_DispatchExceptionReturnOffset;
 
 /*++
 Function :
-    exception_from_trap_code
+    ExceptionRecordFromMessage
 
-    map a Trap code to a SEH exception code
+    Setups up an ExceptionRecord from an exception message
 
 Parameters :
-    exception_type_t exception          : Trap code to map
-    exception_data_t code               : Sub code
-    mach_msg_type_number_t code_count   : Size of sub code
+    message - exception message to build the exception record
+    pExceptionRecord - exception record to setup
 */
-static DWORD exception_from_trap_code(
-   exception_type_t exception,          // [in] The type of the exception
-   MACH_EH_TYPE(exception_data_t) code, // [in] A machine dependent array indicating a particular instance of exception
-   mach_msg_type_number_t code_count,   // [in] The size of the buffer (in natural-sized units)
-   EXCEPTION_RECORD *pExceptionRecord   // [out] Used to return exception parameters
-#if defined(_AMD64_)
-   , mach_port_t thread
-#endif // defined(_AMD64_)
-   )
+static void 
+ExceptionRecordFromMessage(
+    MachMessage &message,               // [in] exception message
+    EXCEPTION_RECORD *pExceptionRecord) // [out] Used to return exception parameters
 {
-    pExceptionRecord->NumberParameters = 0;
+    exception_type_t exception = message.GetException();
+    MACH_EH_TYPE(exception_data_type_t) subcodes[2];
+    mach_msg_type_number_t subcode_count;
+    
+    subcode_count = message.GetExceptionCodeCount();
+    if (subcode_count < 0 || subcode_count > 2)
+        NONPAL_RETAIL_ASSERT("Bad exception subcode count: %d", subcode_count);
+
+    for (int i = 0; i < subcode_count; i++)
+        subcodes[i] = message.GetExceptionCode(i);
+
+    memset(pExceptionRecord, 0, sizeof(EXCEPTION_RECORD));
+
+    DWORD exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
 
     switch(exception)
     {
     // Could not access memory. subcode contains the bad memory address. 
     case EXC_BAD_ACCESS:
-        if (code_count != 2)
+        if (subcode_count != 2)
         {
-            NONPAL_RETAIL_ASSERT("Got an unexpected sub code");
-            return EXCEPTION_ILLEGAL_INSTRUCTION; 
+            NONPAL_RETAIL_ASSERT("Got an unexpected subcode");
+            exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; 
         }
-        pExceptionRecord->NumberParameters = 2;
-        pExceptionRecord->ExceptionInformation[0] = 0;
-        pExceptionRecord->ExceptionInformation[1] = code[1];
-
-#if defined(_AMD64_)
+        else
         {
-            // For X64, get exception state from the thread that contains the address (and not IP) using which
-            // the fault happened.
-            x86_exception_state64_t ThreadExceptionState;
-            const thread_state_flavor_t ThreadExceptionStateFlavor = x86_EXCEPTION_STATE64;
-            unsigned int ehStateCount = sizeof(ThreadExceptionState)/sizeof(unsigned);
-            kern_return_t MachRet = thread_get_state(thread,
-                                   ThreadExceptionStateFlavor,
-                                   (thread_state_t)&ThreadExceptionState,
-                                   &ehStateCount);
-            CHECK_MACH("thread_get_state", MachRet);
-            ULONG64 faultAddr = ThreadExceptionState.__faultvaddr;
-            pExceptionRecord->ExceptionInformation[1] = faultAddr;
-        }
-#endif // _AMD64_
+            exceptionCode = EXCEPTION_ACCESS_VIOLATION;
 
-        return EXCEPTION_ACCESS_VIOLATION; 
+            pExceptionRecord->NumberParameters = 2;
+            pExceptionRecord->ExceptionInformation[0] = 0;
+            pExceptionRecord->ExceptionInformation[1] = subcodes[1];
+            NONPAL_TRACE("subcodes[1] = %llx\n", subcodes[1]);
+        }
+        break;
 
-    // Instruction failed. Illegal, privileged, or undefined instruction or operand.
-    case EXC_BAD_INSTRUCTION:
-        // TODO: Identify privileged instruction. Need to get the thread state and read the machine code. May be better to do this in the place that calls SEHProcessException, similar to how it's done on Linux.
-        return EXCEPTION_ILLEGAL_INSTRUCTION; 
+    // Instruction failed. Illegal or undefined instruction or operand. 
+    case EXC_BAD_INSTRUCTION :
+        // TODO: Identify privileged instruction. Need to get the thread state and read the machine code. May
+        // be better to do this in the place that calls SEHProcessException, similar to how it's done on Linux.
+        exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; 
+        break;
 
     // Arithmetic exception; exact nature of exception is in subcode field. 
     case EXC_ARITHMETIC:
-        if (code_count != 2)
+        if (subcode_count != 2)
         {
-            NONPAL_RETAIL_ASSERT("Got an unexpected sub code");
-            return EXCEPTION_ILLEGAL_INSTRUCTION; 
+            NONPAL_RETAIL_ASSERT("Got an unexpected subcode");
+            exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; 
         }
-        switch (*(unsigned *)code)
+        else
         {
+            switch (subcodes[0])
+            {
 #if defined(_X86_) || defined(_AMD64_)
-        case EXC_I386_DIV:
-            return EXCEPTION_INT_DIVIDE_BY_ZERO;
-        case EXC_I386_INTO:
-            return EXCEPTION_INT_OVERFLOW;
-        case EXC_I386_EXTOVR:
-            return EXCEPTION_FLT_OVERFLOW;
-        case EXC_I386_BOUND:
-            return EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
+                case EXC_I386_DIV:
+                    exceptionCode = EXCEPTION_INT_DIVIDE_BY_ZERO;
+                    break;
+                case EXC_I386_INTO:
+                    exceptionCode = EXCEPTION_INT_OVERFLOW;
+                    break;
+                case EXC_I386_EXTOVR:
+                    exceptionCode = EXCEPTION_FLT_OVERFLOW;
+                    break;
+                case EXC_I386_BOUND:
+                    exceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
+                    break;
 #else
 #error Trap code to exception mapping not defined for this architecture
 #endif
-        default:
-            return EXCEPTION_ILLEGAL_INSTRUCTION; 
+                default:
+                    exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
+                    break;
+            }
         }
         break;
 
     case EXC_SOFTWARE:
 #if defined(_X86_) || defined(_AMD64_)
-        return EXCEPTION_ILLEGAL_INSTRUCTION;
+        exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
+        break;
 #else
 #error Trap code to exception mapping not defined for this architecture
 #endif
@@ -653,40 +608,41 @@ static DWORD exception_from_trap_code(
     // Trace, breakpoint, etc. Details in subcode field. 
     case EXC_BREAKPOINT:
 #if defined(_X86_) || defined(_AMD64_)
-        if (*(unsigned *)code == EXC_I386_SGL)
+        if (subcodes[0] == EXC_I386_SGL)
         {
-            return EXCEPTION_SINGLE_STEP;
+            exceptionCode = EXCEPTION_SINGLE_STEP;
         }
-        else if (*(unsigned *)code == EXC_I386_BPT)
+        else if (subcodes[0] == EXC_I386_BPT)
         {
-            return EXCEPTION_BREAKPOINT;
+            exceptionCode = EXCEPTION_BREAKPOINT;
         }
 #else
 #error Trap code to exception mapping not defined for this architecture
 #endif
         else
         {
-            WARN("unexpected code %d for EXC_BREAKPOINT");
-            return EXCEPTION_BREAKPOINT;
+            WARN("unexpected subcode %d for EXC_BREAKPOINT", subcodes[0]);
+            exceptionCode = EXCEPTION_BREAKPOINT;
         }
         break;
 
 
     // System call requested. Details in subcode field. 
     case EXC_SYSCALL:
-        return EXCEPTION_ILLEGAL_INSTRUCTION; 
+        exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; 
         break;
 
     // System call with a number in the Mach call range requested. Details in subcode field. 
     case EXC_MACH_SYSCALL:
-        return EXCEPTION_ILLEGAL_INSTRUCTION; 
+        exceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; 
         break;
 
     default:
         ASSERT("Got unknown trap code %d\n", exception);
         break;
     }
-    return EXCEPTION_ILLEGAL_INSTRUCTION;
+
+    pExceptionRecord->ExceptionCode = exceptionCode;
 }
 
 #ifdef _DEBUG
@@ -724,67 +680,60 @@ GetExceptionString(
     }
     return "INVALID CODE";
 }
-#endif // DEBUG
+#endif // _DEBUG
 
 /*++
 Function :
-    catch_exception_raise
+    HijackFaultingThread
+
+    Sets the faulting thread up to return to PAL_DispatchException with an
+    ExceptionRecord, thread CONTEXT and the exception MachMessage.
 
-    called from SEHExceptionThread and does the exception processing
+Parameters:
+    thread - thread the exception happened
+    task - task the exception happened
+    message - exception message
 
 Return value :
-   KERN_SUCCESS if the error is handled
-   MIG_DESTROY_REQUEST if the error was not handled
+    None
 --*/
 
 static
-kern_return_t
-catch_exception_raise(
-   mach_port_t exception_port,          // [in] Mach Port that is listening to the exception
-   mach_port_t thread,                  // [in] thread the exception happened on
-   mach_port_t task,                    // [in] task the exception happened on
-   exception_type_t exception,          // [in] The type of the exception
-   MACH_EH_TYPE(exception_data_t) code, // [in] A machine dependent array indicating a particular instance of exception
-   mach_msg_type_number_t code_count)   // [in] The size of the buffer (in natural-sized units). 
+void
+HijackFaultingThread(
+    mach_port_t thread,             // [in] thread the exception happened on
+    mach_port_t task,               // [in] task the exception happened on
+    MachMessage &message)           // [in] exception message
 {
-    kern_return_t MachRet;
-#if defined(_X86_)
-    x86_thread_state32_t ThreadState;
-    const thread_state_flavor_t ThreadStateFlavor = x86_THREAD_STATE32;
-#elif defined(_AMD64_)
-    x86_thread_state64_t ThreadState;
-    const thread_state_flavor_t ThreadStateFlavor = x86_THREAD_STATE64;
-#else
-#error Thread state not defined for this architecture
-#endif
-    unsigned int count = sizeof(ThreadState)/sizeof(unsigned);
-    CONTEXT ThreadContext;
-    EXCEPTION_RECORD ExceptionRecord;
-    memset(&ExceptionRecord, 0, sizeof(ExceptionRecord));
-
-    ExceptionRecord.ExceptionCode = exception_from_trap_code(exception, code, code_count, &ExceptionRecord
-#if defined(_AMD64_)
-        , thread
-#endif // _AMD64_
-        );
+    thread_state_flavor_t threadStateFlavor;
+    x86_thread_state_t threadState;
+    EXCEPTION_RECORD exceptionRecord;
+    CONTEXT threadContext;
+    kern_return_t machret;
+    unsigned int count;
+
+    // Fill in the exception record from the exception message
+    ExceptionRecordFromMessage(message, &exceptionRecord);
     
-    // Don't save/restore the debug registers because loading them on OSx causes a 
-    // priviledged instruction fault. The "DE" in CR4 is set.
+    // Get the thread state from the exception message and convert the count of bytes into
+    // the count of ints
+    threadStateFlavor = message.GetThreadStateFlavor();
+    count = message.GetThreadState(threadStateFlavor, (thread_state_t)&threadState, thread) / sizeof(natural_t);
+
 #ifdef _X86_
-    ThreadContext.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS
+    threadContext.ContextFlags = CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS
 #else
-    ThreadContext.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT;
+    threadContext.ContextFlags = CONTEXT_FLOATING_POINT;
 #endif
+    // Get just the floating point registers directly from the thread because the message context is only
+    // the general registers.
+    machret = CONTEXT_GetThreadContextFromPort(thread, &threadContext);
+    CHECK_MACH("CONTEXT_GetThreadContextFromPort", machret);
 
-    MachRet = CONTEXT_GetThreadContextFromPort(thread, &ThreadContext);
-    CHECK_MACH("CONTEXT_GetThreadContextFromPort", MachRet);
-
-    // We need to hijack the thread to point to PAL_DispatchException
-    MachRet = thread_get_state(thread,
-                               ThreadStateFlavor,
-                               (thread_state_t)&ThreadState,
-                               &count);
-    CHECK_MACH("thread_get_state", MachRet);
+    // Now get the rest of the registers from the exception message. Don't save/restore the debug registers 
+    // because loading them on OSx causes a privileged instruction fault. The "DE" in CR4 is set.
+    threadContext.ContextFlags |= CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS;
+    CONTEXT_GetThreadContextFromThreadState(threadStateFlavor, (thread_state_t)&threadState, &threadContext);
 
 #if defined(CORECLR) && (defined(_X86_) || defined(_AMD64_))
     // For CoreCLR we look more deeply at access violations to determine whether they're the result of a stack
@@ -833,18 +782,18 @@ catch_exception_raise(
     //          does not do this by default. We have to explicitly provide the -fstack-check compiler option
     //          to enable the behavior.
 #if (defined(_X86_) || defined(_AMD64_)) && defined(__APPLE__)
-    if (ExceptionRecord.ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
+    if (exceptionRecord.ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
     {
         // Assume this AV isn't an SO to begin with.
         bool fIsStackOverflow = false;
 
         // Calculate the page base addresses for the fault and the faulting thread's SP.
         int cbPage = getpagesize();
-        char *pFaultPage = (char*)(ExceptionRecord.ExceptionInformation[1] & ~(cbPage - 1));
+        char *pFaultPage = (char*)(exceptionRecord.ExceptionInformation[1] & ~(cbPage - 1));
 #ifdef _X86_
-        char *pStackTopPage = (char*)(ThreadContext.Esp & ~(cbPage - 1));
+        char *pStackTopPage = (char*)(threadContext.Esp & ~(cbPage - 1));
 #elif defined(_AMD64_)
-        char *pStackTopPage = (char*)(ThreadContext.Rsp & ~(cbPage - 1));
+        char *pStackTopPage = (char*)(threadContext.Rsp & ~(cbPage - 1));
 #endif
 
         if (pFaultPage == pStackTopPage || pFaultPage == (pStackTopPage - cbPage))
@@ -874,9 +823,9 @@ catch_exception_raise(
             vm_address = (vm_address_t)(pFaultPage + cbPage);
 
 #ifdef BIT64
-            MachRet = vm_region_64(
+            machret = vm_region_64(
 #else
-            MachRet = vm_region(
+            machret = vm_region(
 #endif
                                 mach_task_self(),
                                 &vm_address,
@@ -886,9 +835,9 @@ catch_exception_raise(
                                 &infoCnt,
                                 &object_name);
 #ifdef _X86_
-            CHECK_MACH("vm_region", MachRet);
+            CHECK_MACH("vm_region", machret);
 #elif defined(_AMD64_)
-            CHECK_MACH("vm_region_64", MachRet);
+            CHECK_MACH("vm_region_64", machret);
 #endif
 
             // If vm_region updated the address we gave it then that address was not part of a region at all
@@ -904,14 +853,14 @@ catch_exception_raise(
         {
             // Check if we can read pointer sizeD bytes below the target thread's stack pointer.
             // If we are unable to, then it implies we have run into SO.
-            void **targetSP = (void **)ThreadState.__rsp;
+            void **targetSP = (void **)threadState.uts.ts64.__rsp;
             vm_address_t targetAddr = (mach_vm_address_t)(targetSP);
             targetAddr -= sizeof(void *);
             vm_size_t vm_size = sizeof(void *);
             char arr[8];
             vm_size_t data_count = 8;
-            MachRet = vm_read_overwrite(mach_task_self(), targetAddr, vm_size, (pointer_t)arr, &data_count);
-            if (MachRet == KERN_INVALID_ADDRESS)
+            machret = vm_read_overwrite(mach_task_self(), targetAddr, vm_size, (pointer_t)arr, &data_count);
+            if (machret == KERN_INVALID_ADDRESS)
             {
                 fIsStackOverflow = true;
             }
@@ -942,19 +891,21 @@ catch_exception_raise(
 #endif // CORECLR && _X86_
 
 #if defined(_X86_)
+    _ASSERTE((threadStateFlavor == x86_THREAD_STATE32) || ((threadStateFlavor == x86_THREAD_STATE) && (threadState.tsh.flavor == x86_THREAD_STATE32)));
+
     // If we're in single step mode, disable it since we're going to call PAL_DispatchException
-    if (ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP)
+    if (exceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP)
     {
-        ThreadState.eflags &= ~EFL_TF;
+        threadState.uts.ts32.eflags &= ~EFL_TF;
     }
 
-    ExceptionRecord.ExceptionFlags = EXCEPTION_IS_SIGNAL; 
-    ExceptionRecord.ExceptionRecord = NULL;
-    ExceptionRecord.ExceptionAddress = (void *)ThreadContext.Eip;
+    exceptionRecord.ExceptionFlags = EXCEPTION_IS_SIGNAL; 
+    exceptionRecord.ExceptionRecord = NULL;
+    exceptionRecord.ExceptionAddress = (void *)threadContext.Eip;
 
-    void **FramePointer = (void **)ThreadState.esp;
+    void **FramePointer = (void **)threadState.uts.ts32.esp;
 
-    *--FramePointer = (void *)((ULONG_PTR)ThreadState.eip);
+    *--FramePointer = (void *)((ULONG_PTR)threadState.uts.ts32.eip);
 
     // Construct a stack frame for a pretend activation of the function
     // PAL_DispatchExceptionWrapper that serves only to make the stack
@@ -962,47 +913,57 @@ catch_exception_raise(
     // PAL_DispatchExceptionWrapper has an ebp frame, its local variables
     // are the context and exception record, and it has just "called"
     // PAL_DispatchException.
-    *--FramePointer = (void *)ThreadState.ebp;
-    ThreadState.ebp = (unsigned)FramePointer;
+    *--FramePointer = (void *)threadState.uts.ts32.ebp;
+    threadState.uts.ts32.ebp = (unsigned)FramePointer;
 
     // Put the context on the stack
     FramePointer = (void **)((ULONG_PTR)FramePointer - sizeof(CONTEXT));
     // Make sure it's aligned - CONTEXT has 8-byte alignment
     FramePointer = (void **)((ULONG_PTR)FramePointer - ((ULONG_PTR)FramePointer % 8));
     CONTEXT *pContext = (CONTEXT *)FramePointer;
-    *pContext = ThreadContext;
+    *pContext = threadContext;
 
     // Put the exception record on the stack
     FramePointer = (void **)((ULONG_PTR)FramePointer - sizeof(EXCEPTION_RECORD));
     EXCEPTION_RECORD *pExceptionRecord = (EXCEPTION_RECORD *)FramePointer;
-    *pExceptionRecord = ExceptionRecord;
+    *pExceptionRecord = exceptionRecord;
+
+    // Put the exception message on the stack
+    FramePointer = (void **)((ULONG_PTR)FramePointer - sizeof(MachMessage));
+    MachMessage *pMessage = (MachMessage *)FramePointer;
+    pMessage->InitializeFrom(message);
 
     // Push arguments to PAL_DispatchException
-    FramePointer = (void **)((ULONG_PTR)FramePointer - 2 * sizeof(void *));
+    FramePointer = (void **)((ULONG_PTR)FramePointer - 3 * sizeof(void *));
+
     // Make sure it's aligned - ABI requires 16-byte alignment
     FramePointer = (void **)((ULONG_PTR)FramePointer - ((ULONG_PTR)FramePointer % 16));
     FramePointer[0] = pContext;
     FramePointer[1] = pExceptionRecord;
+    FramePointer[2] = pMessage;
+
     // Place the return address to right after the fake call in PAL_DispatchExceptionWrapper
     FramePointer[-1] = (void *)((ULONG_PTR)PAL_DispatchExceptionWrapper + PAL_DispatchExceptionReturnOffset);
 
     // Make the instruction register point to DispatchException
-    ThreadState.eip = (unsigned)PAL_DispatchException;
-    ThreadState.esp = (unsigned)&FramePointer[-1]; // skip return address
+    threadState.uts.ts32.eip = (unsigned)PAL_DispatchException;
+    threadState.uts.ts32.esp = (unsigned)&FramePointer[-1]; // skip return address
 #elif defined(_AMD64_)
+    _ASSERTE((threadStateFlavor == x86_THREAD_STATE64) || ((threadStateFlavor == x86_THREAD_STATE) && (threadState.tsh.flavor == x86_THREAD_STATE64)));
+
     // If we're in single step mode, disable it since we're going to call PAL_DispatchException
-    if (ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP)
+    if (exceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP)
     {
-        ThreadState.__rflags &= ~EFL_TF;
+        threadState.uts.ts64.__rflags &= ~EFL_TF;
     }
 
-    ExceptionRecord.ExceptionFlags = EXCEPTION_IS_SIGNAL; 
-    ExceptionRecord.ExceptionRecord = NULL;
-    ExceptionRecord.ExceptionAddress = (void *)ThreadContext.Rip;
+    exceptionRecord.ExceptionFlags = EXCEPTION_IS_SIGNAL; 
+    exceptionRecord.ExceptionRecord = NULL;
+    exceptionRecord.ExceptionAddress = (void *)threadContext.Rip;
 
-    void **FramePointer = (void **)ThreadState.__rsp;
+    void **FramePointer = (void **)threadState.uts.ts64.__rsp;
 
-    *--FramePointer = (void *)((ULONG_PTR)ThreadState.__rip);
+    *--FramePointer = (void *)((ULONG_PTR)threadState.uts.ts64.__rip);
 
     // Construct a stack frame for a pretend activation of the function
     // PAL_DispatchExceptionWrapper that serves only to make the stack
@@ -1010,262 +971,50 @@ catch_exception_raise(
     // PAL_DispatchExceptionWrapper has an ebp frame, its local variables
     // are the context and exception record, and it has just "called"
     // PAL_DispatchException.
-    *--FramePointer = (void *)ThreadState.__rbp;
-    ThreadState.__rbp = (SIZE_T)FramePointer;
+    *--FramePointer = (void *)threadState.uts.ts64.__rbp;
+    threadState.uts.ts64.__rbp = (SIZE_T)FramePointer;
 
     // Put the context on the stack
     FramePointer = (void **)((ULONG_PTR)FramePointer - sizeof(CONTEXT));
     // Make sure it's aligned - CONTEXT has 16-byte alignment
     FramePointer = (void **)((ULONG_PTR)FramePointer - ((ULONG_PTR)FramePointer % 16));
     CONTEXT *pContext = (CONTEXT *)FramePointer;
-    *pContext = ThreadContext;
+    *pContext = threadContext;
 
     // Put the exception record on the stack
     FramePointer = (void **)((ULONG_PTR)FramePointer - sizeof(EXCEPTION_RECORD));
     EXCEPTION_RECORD *pExceptionRecord = (EXCEPTION_RECORD *)FramePointer;
-    *pExceptionRecord = ExceptionRecord;
+    *pExceptionRecord = exceptionRecord;
+
+    // Put the exception message on the stack
+    FramePointer = (void **)((ULONG_PTR)FramePointer - sizeof(MachMessage));
+    MachMessage *pMessage = (MachMessage *)FramePointer;
+    pMessage->InitializeFrom(message);
 
     // Push arguments to PAL_DispatchException
-    FramePointer = (void **)((ULONG_PTR)FramePointer - 2 * sizeof(void *));
+    FramePointer = (void **)((ULONG_PTR)FramePointer - 3 * sizeof(void *));
+
     // Make sure it's aligned - ABI requires 16-byte alignment
     FramePointer = (void **)((ULONG_PTR)FramePointer - ((ULONG_PTR)FramePointer % 16));
     FramePointer[0] = pContext;
     FramePointer[1] = pExceptionRecord;
+    FramePointer[2] = pMessage;
+
     // Place the return address to right after the fake call in PAL_DispatchExceptionWrapper
     FramePointer[-1] = (void *)((ULONG_PTR)PAL_DispatchExceptionWrapper + PAL_DispatchExceptionReturnOffset);
 
     // Make the instruction register point to DispatchException
-    ThreadState.__rip = (SIZE_T)PAL_DispatchException;
-    ThreadState.__rsp = (SIZE_T)&FramePointer[-1]; // skip return address
+    threadState.uts.ts64.__rip = (SIZE_T)PAL_DispatchException;
+    threadState.uts.ts64.__rsp = (SIZE_T)&FramePointer[-1]; // skip return address
 #else
-#error catch_exception_raise not defined for this architecture
+#error HijackFaultingThread not defined for this architecture
 #endif
 
     // Now set the thread state for the faulting thread so that PAL_DispatchException executes next
-    MachRet = thread_set_state(thread,
-                               ThreadStateFlavor,
-                               (thread_state_t)&ThreadState,
-                               count);
-    CHECK_MACH("thread_set_state", MachRet);
-
-    // We're done!
-    return KERN_SUCCESS;
+    machret = thread_set_state(thread, threadStateFlavor, (thread_state_t)&threadState, count);
+    CHECK_MACH("thread_set_state", machret);
 }
 
-//----------------------------------------------------------------------
-
-// Returns true if the given address resides within the memory range into which the CoreCLR binary is mapped.
-bool IsWithinCoreCLR(void *pAddr)
-{
-    static void *s_pLowerBound = NULL;
-    static void *s_pUpperBound = NULL;
-
-    // Have we initialized our cached range values yet?
-    if (s_pLowerBound == NULL || s_pUpperBound == NULL)
-    {
-        // No, initialize them now. We could be racing here (though currently only one thread calls this
-        // function) but it doesn't matter since the data computed is invariant.
-
-        // Get the mach_header for this instance of the CoreCLR by looking up out own function's address with
-        // dladdr.
-        Dl_info sInfo;
-        int result = dladdr((void*)IsWithinCoreCLR, &sInfo);
-        if (result == 0)
-            NONPAL_RETAIL_ASSERT("dladdr() failed to locate IsWithinCoreCLR().");
-
-        // Walk the segment commands in the Mach-O command array, looking for the segment with the highest
-        // virtual address mapping. The end of this segment will correspond to the end of memory region that
-        // the CoreCLR has been mapped to.
-#if !defined(_AMD64_)
-        mach_header *pHeader = (mach_header*)sInfo.dli_fbase;
-        unsigned int addrMaxAddress = 0;
-        unsigned int cbMaxSegment = 0;
-        unsigned int iSegmentType = LC_SEGMENT;
-#else // defined(_AMD64_)
-        mach_header_64 *pHeader = (mach_header_64*)sInfo.dli_fbase;
-        DWORD64 addrMaxAddress = 0;
-        DWORD64 cbMaxSegment = 0;
-        unsigned int iSegmentType = LC_SEGMENT_64;
-#endif // !_AMD64_
-
-        load_command *pCommand = (load_command*)(pHeader + 1);
-        for (unsigned int i = 0; i < pHeader->ncmds; i++)
-        {
-            if (pCommand->cmd == iSegmentType)
-            {
-#if !defined(_AMD64_)
-                segment_command *pSegment = (segment_command*)pCommand;
-#else // defined(_AMD64_)
-                segment_command_64 *pSegment = (segment_command_64*)pCommand;
-#endif // !defined(_AMD64_)
-
-                if (pSegment->vmaddr > addrMaxAddress)
-                {
-                    addrMaxAddress = pSegment->vmaddr;
-                    cbMaxSegment = pSegment->vmsize;
-                }
-            }
-
-            pCommand = (load_command*)((unsigned char*)pCommand + pCommand->cmdsize);
-        }
-
-        // The lower bound of the range is defined by the Mach-O image header.
-        s_pLowerBound = pHeader;
-
-        // The upper bound is the end address of the highest mapped segment in the image (the virtual address
-        // we calculated in the previous step is relative to the base address of the image, i.e. the Mach-O
-        // header).
-        s_pUpperBound = (unsigned char*)pHeader + addrMaxAddress + cbMaxSegment;
-
-        NONPAL_TRACE("coreclr s_pLowerBound %p s_pUpperBound %p\n", s_pLowerBound, s_pUpperBound);
-    }
-
-    // Perform the range check.
-    return (pAddr >= s_pLowerBound) && (pAddr < s_pUpperBound);
-}
-
-extern malloc_zone_t *s_pExecutableHeap; // from heap.cpp in #ifdef CACHE_HEAP_ZONE
-
-#pragma mark - 
-#pragma mark malloc_zone utilities
-
-// Ultimately, this may be more appropriate for heap.cpp, and rewritten in terms of
-// a PAL heap and the win32 heap enumeration mechanism.
-
-struct malloc_zone_owns_addr_context_t
-{
-    void *addr;
-    bool fInUse;
-};
-
-static void malloc_zone_owns_addr_helper(task_t task, void *context, unsigned type_mask,
-    vm_range_t *ranges, unsigned range_count)
-{
-    malloc_zone_owns_addr_context_t *our_context = (malloc_zone_owns_addr_context_t *)context;
-    
-    if (our_context->fInUse)
-        return;
-    
-    vm_range_t *pRange = ranges;
-    vm_range_t *pRangeMac = ranges + range_count;
-    void *addr = our_context->addr;
-    for (; pRange < pRangeMac; pRange++)
-    {
-        vm_range_t range = *pRange;
-        
-        if ((range.address <= (vm_address_t)addr) && ((range.address + range.size) > (vm_address_t)addr))
-        {
-            our_context->fInUse = true;
-            return;
-        }
-    }
-}
-
-static bool malloc_zone_owns_addr(malloc_zone_t *zone, void * const addr)
-{
-    malloc_introspection_t *introspect = zone->introspect;
-    malloc_zone_owns_addr_context_t context = { addr, false };
-    
-    (*introspect->enumerator)(mach_task_self(), &context, MALLOC_PTR_IN_USE_RANGE_TYPE, 
-        (vm_address_t)zone, NULL /* memory_reader_t */, &malloc_zone_owns_addr_helper);
-    
-    return context.fInUse;
-}
-
-#pragma mark -
-
-// Given an exception notification message determine whether the exception originated in code belonging to or
-// generated by this instance of the CoreCLR. If true is returned the CoreCLR "owns" the faulting code and we
-// should handle the exception. Otherwise the exception should be forwarded to another handler (if there is
-// one) or the process terminated.
-bool IsHandledException(MachMessage *pNotification, CorUnix::CPalThread *pThread)
-{
-    // Retrieve the state of faulting thread from the message (or directly, if the message doesn't contain
-    // this information).
-    thread_state_flavor_t sThreadStateFlavor;
-#ifdef _X86_
-    x86_thread_state32_t sThreadState;
-    sThreadStateFlavor = x86_THREAD_STATE32;
-#elif defined(_AMD64_)
-    x86_thread_state64_t sThreadState;
-    sThreadStateFlavor = x86_THREAD_STATE64;
-#else
-#error Unexpected architecture.
-#endif
-
-    pNotification->GetThreadState(sThreadStateFlavor, (thread_state_t)&sThreadState);
-
-#ifdef _X86_
-    void *ip = (void*)sThreadState.eip;
-#elif defined(_AMD64_)
-    void *ip = (void*)sThreadState.__rip;
-#else
-#error Unexpected architecture.
-#endif
-
-    // Was the exception raised from within the CoreCLR binary itself?
-    if (IsWithinCoreCLR(ip))
-    {
-        NONPAL_TRACE("    IP (%p) is in CoreCLR.\n", ip);
-        if (IsInDebugBreak(ip))
-        {
-            return false;
-        }
-        return pThread->IsHardwareExceptionsEnabled();
-    }
-
-    // Check inside our executable heap.
-    bool fExecutableHeap = s_pExecutableHeap != NULL && malloc_zone_owns_addr(s_pExecutableHeap, ip);
-    if (fExecutableHeap)
-    {
-        NONPAL_TRACE("    IP (%p) is in the executable heap (%p).\n", ip, s_pExecutableHeap);
-        return true;
-    }
-    
-    // Check inside our virtual alloc reserves.
-    if (VIRTUALOwnedRegion((UINT_PTR)ip))
-    {
-        NONPAL_TRACE("    IP (%p) is in a VirtualAlloc region.\n", ip);
-        return true;
-    }
-
-    // Check for mapped regions, including mapped NGEN images.
-    if (MAPGetRegionInfo(ip, NULL))
-    {
-        NONPAL_TRACE("    IP (%p) is in a memory mapped region.\n", ip);
-        return true;
-    }
-
-#if defined(_AMD64_)
-    // On 64bit, we can have JIT helpers call into supporting functions
-    // where the AV can be triggered. In such a case, we should check if the
-    // caller of faulting function is in CoreCLR. If so, we should handle the exception.
-    //
-    // To get the caller IP, we assume that the faulting library function sets up a RBP frame.
-    // Currently, this validation is limited to JIT_MemCpy/JIT_MemSet, so is easy to ensure.
-    // If this ever becomes more complex, then we should get full context and perform
-    // native unwind to get the caller context.
-    //
-    // Fetch the caller's IP
-    PULONG64 rbpFaultingFunc = (PULONG64)sThreadState.__rbp;
-    void *pCallerIP = (void *)*((PULONG64)(rbpFaultingFunc+1));
-    if (IsWithinCoreCLR(pCallerIP))
-    {
-        NONPAL_TRACE("    CallerIP (%p) is in CoreCLR (IP %p).\n", pCallerIP, ip);
-        return true;
-    }
-#endif // defined(_AMD64_)
-
-    // This doesn't look like an exception caused by our code, don't try to handle it.
-    NONPAL_TRACE("    IP (%p) not apparently owned by this CoreCLR.\n", ip);
-    return false;
-}
-
-static MachMessage sMessage;
-static MachMessage sReplyOrForward;
-
-//----------------------------------------------------------------------
-
 /*++
 Function :
     SEHExceptionThread
@@ -1298,21 +1047,22 @@ Return value :
 --*/
 void *SEHExceptionThread(void *args)
 {
-    ForwardedNotification *pOutstandingForwards = NULL;
+    MachMessage sMessage;
+    MachMessage sReplyOrForward;
 
-    kern_return_t MachRet;
+    kern_return_t machret;
     thread_act_t hThread;
 
     // Loop processing incoming messages forever.
     while (true)
     {
         // Receive the next message.
-        sMessage.Receive(s_ExceptionPortSet);
+        sMessage.Receive(s_ExceptionPort);
 
-        NONPAL_TRACE("Received message %s from %08X to %08X\n",
-                     sMessage.GetMessageTypeName(),
-                     sMessage.GetRemotePort(),
-                     sMessage.GetLocalPort());
+        NONPAL_TRACE("Received message %s from %08x to %08x\n",
+            sMessage.GetMessageTypeName(), 
+            sMessage.GetRemotePort(), 
+            sMessage.GetLocalPort());
 
         if (sMessage.IsSetThreadRequest())
         {
@@ -1322,286 +1072,94 @@ void *SEHExceptionThread(void *args)
 
             while (true)
             {
-                MachRet = thread_suspend(hThread);
-                CHECK_MACH("thread_suspend", MachRet);
+                machret = thread_suspend(hThread);
+                CHECK_MACH("thread_suspend", machret);
 
                 // Ensure that if the thread was running in the kernel, the kernel operation
                 // is safely aborted so that it can be restarted later.
-                MachRet = thread_abort_safely(hThread);
-                if (MachRet == KERN_SUCCESS)
+                machret = thread_abort_safely(hThread);
+                if (machret == KERN_SUCCESS)
                 {
                     break;
                 }
 
                 // The thread was running in the kernel executing a non-atomic operation
                 // that cannot be restarted, so we need to resume the thread and retry
-                MachRet = thread_resume(hThread);
-                CHECK_MACH("thread_resume", MachRet);
+                machret = thread_resume(hThread);
+                CHECK_MACH("thread_resume", machret);
             }
             
-            MachRet = CONTEXT_SetThreadContextOnPort(hThread, &sContext);
-            CHECK_MACH("CONTEXT_SetThreadContextOnPort", MachRet);
+            machret = CONTEXT_SetThreadContextOnPort(hThread, &sContext);
+            CHECK_MACH("CONTEXT_SetThreadContextOnPort", machret);
 
-            MachRet = thread_resume(hThread);
-            CHECK_MACH("thread_resume", MachRet);
+            machret = thread_resume(hThread);
+            CHECK_MACH("thread_resume", machret);
         }
         else if (sMessage.IsExceptionNotification())
         {
             // This is a notification of an exception occurring on another thread.
             hThread = sMessage.GetThread();
 
-            // Determine whether this notification was delivered to our "top" exception handler (one set up
-            // by a host call to ICLRRuntimeHost2::RegisterMacEHPort()) or the "bottom" handler (set up the
-            // first time the CLR saw the thread). This determines which handlers we chain back to if we
-            // decide not to handle the exception ourselves.
-            bool fTopException = sMessage.GetLocalPort() == s_TopExceptionPort;
-
-            // Note that the call to PROCThreadFromMachPort() requires taking the PAL process critical
-            // section, which is dangerous. The assumption we make is that code holding this critical
-            // section (of which there is little) never generates an exception while the lock is still
-            // held.
-            CorUnix::CPalThread *pTargetThread = PROCThreadFromMachPort(hThread);
-            if (pTargetThread == NULL)
-                NONPAL_RETAIL_ASSERT("Failed to translate mach thread to a CPalThread.");
-
-            NONPAL_TRACE("    Notification is for exception %u (%s) on thread id 0x%04lX (sent to the %s exception handler)\n",
+            NONPAL_TRACE("Notification is for exception %u (%s) on thread port %08x flavor %d\n",
                 sMessage.GetException(),
                 GetExceptionString(sMessage.GetException()),
-                pTargetThread->GetThreadId(),
-                fTopException ? "top" : "bottom");
+                hThread,
+                sMessage.GetThreadStateFlavor());
 
-            // Determine if we should handle this exception ourselves or forward it to the previous handler
-            // registered for this exception type (if there is one).
-            if (IsHandledException(&sMessage, pTargetThread))
-            {
-                // This is one of ours, pass the relevant exception data to our handler.
-                MACH_EH_TYPE(exception_data_type_t) rgCodes[2];
-                
-                int cCodes = sMessage.GetExceptionCodeCount();
-                if (cCodes < 0 || cCodes > 2)
-                    NONPAL_RETAIL_ASSERT("Bad exception code count: %d", cCodes);
-                for (int i = 0; i < cCodes; i++)
-                    rgCodes[i] = sMessage.GetExceptionCode(i);
-
-                kern_return_t ret = catch_exception_raise(s_ExceptionPort,
-                                                          hThread,
-                                                          mach_task_self(),
-                                                          sMessage.GetException(),
-                                                          rgCodes,
-                                                          cCodes);
-
-                // Send the result of handling the exception back in a reply.
-                sReplyOrForward.ReplyToNotification(&sMessage, ret);
-
-                NONPAL_TRACE("    Handled request\n");
-            }
-            else
-            {
-                // We didn't recognize the exception as one of ours. Attempt to forward the notification to
-                // any handler previously registered for this kind of exception.
-
-                // Locate the record of previously installed handlers that the target thread keeps.
-                CorUnix::CThreadMachExceptionHandlers *pHandlers = pTargetThread->GetSavedMachHandlers();
-
-                // Check whether there's even a handler for the particular exception we've been handed.
-                CorUnix::MachExceptionHandler sHandler;
-                if (!pHandlers->GetHandler(sMessage.GetException(), fTopException, &sHandler))
-                {
-                    // There's no previous handler to forward this notification to. Reply with a failure
-                    // status to let the kernel know we can't handle the exception after all (maybe there's a
-                    // handler at the task level).
-                    sReplyOrForward.ReplyToNotification(&sMessage, KERN_FAILURE);
+            HijackFaultingThread(hThread, mach_task_self(), sMessage);
 
-                    NONPAL_TRACE("    Unhandled request and no chain-back. Replying with failure.\n");
-                }
-                else
-                {
-                    // Check that we don't currently have an outstanding forward for the same thread. If we do
-                    // it indicates a cycle (we've forwarded to someone that has ultimately forwarded the
-                    // notification back to us). There's not much we can do in this case: forwarding again
-                    // will almost certainly lead to a busy loop, dropping the notification is dangerous and
-                    // we've already established we don't know enough about the exception to safely handle it.
-                    // So we reply to the notification with a failure. The kernel will either find a handler
-                    // at the task level or will kill the process.
-                    // There is one situation in which it is legal to see the same notification twice: if we
-                    // received and forwarded a notification from our top exception port (one established via
-                    // ICLRRuntimeHost2::RegisterMacEHPort()) we might see it again on our bottom port and use
-                    // the opportunity to forward it to a handler established before we ever saw the thread.
-                    bool fReplied = false;
-                    ForwardedNotification *pReq = pOutstandingForwards;
-                    while (pReq)
-                    {
-                        // We have a cycle if we have a previous request with the same thread and either this
-                        // is a new request to the top exception handler or the old forward we found was for
-                        // the bottom handler. That is, if we were notified on the top handler we don't ever
-                        // expect to find a notification for the same thread. If not (i.e. the notification
-                        // came to the bottom handler) we don't expect to find a notification forwarded from
-                        // the bottom handler. The only legal case for a thread match is if we're the bottom
-                        // exception handler seeing the forward from the top handler.
-                        if (pReq->m_hTargetThread == hThread &&
-                            (fTopException || !pReq->m_fTopException))
-                        {
-                            NONPAL_TRACE("    Detected a cycle in exception handlers.\n");
-                            sReplyOrForward.ReplyToNotification(&sMessage, KERN_FAILURE);
-                            fReplied = true;
-                            break;
-                        }
-
-                        pReq = pReq->m_pNext;
-                    }
-                    
-                    if (!fReplied)
-                    {
-                        // Store enough detail about the notification that we can create a reply once the
-                        // forwarded notification is replied to us.
-                        ForwardedNotification *pNewNotification =
-                            (ForwardedNotification*)malloc(sizeof(ForwardedNotification));
-                        if (pNewNotification == NULL)
-                            NONPAL_RETAIL_ASSERT("Exception thread ran out of memory to track forwarded exception notifications/");
-                        pNewNotification->m_hForwardReplyPort = sMessage.GetRemotePort();
-                        pNewNotification->m_hTargetThread = hThread;
-                        pNewNotification->m_eNotificationType = sMessage.GetMessageType();
-                        pNewNotification->m_eNotificationFlavor = sMessage.GetThreadStateFlavor();
-                        pNewNotification->m_fTopException = fTopException;
-    
-                        // Forward the notification. A port is returned upon which the reply will be received at
-                        // some point.
-                        pNewNotification->m_hListenReplyPort = sReplyOrForward.ForwardNotification(&sHandler,
-                                                                                                   &sMessage);
-    
-                        // Move the reply port into the listen set so we'll receive the reply as soon as it's sent.
-                        MachRet = mach_port_move_member(mach_task_self(),
-                                                        pNewNotification->m_hListenReplyPort,
-                                                        s_ExceptionPortSet);
-                        CHECK_MACH("mach_port_move_member", MachRet);
-    
-                        // Link the forward records into our list of outstanding forwards.
-                        pNewNotification->m_pNext = pOutstandingForwards;
-                        pOutstandingForwards = pNewNotification;
-    
-                        NONPAL_TRACE("    Forwarded request to %08X (reply expected on %08X).\n",
-                                     sHandler.m_handler,
-                                     pNewNotification->m_hListenReplyPort);
-                     }
-                }
-            }
+            // Send the result of handling the exception back in a reply.
+            sReplyOrForward.ReplyToNotification(&sMessage, KERN_SUCCESS);
         }
         else if (sMessage.IsExceptionReply())
         {
-            // We've received a reply to an exception notification we forwarded.
-
-            // Locate the forwarding context we stored away to track this notification.
-            bool fFoundNotification = false;
-            ForwardedNotification *pReq = pOutstandingForwards;
-            ForwardedNotification *pPrevReq = NULL;
-            while (pReq)
-            {
-                // We match the reply to the original request based on the port the reply was sent to (we
-                // allocate a new port for every notification we forward).
-                if (pReq->m_hListenReplyPort == sMessage.GetLocalPort())
-                {
-                    fFoundNotification = true;
-
-                    // Use the reply plus the original context we saved away to construct a reply to the
-                    // original notification we received (we can't just pass the reply along because the
-                    // format may differ, e.g. a different behavior or thread state flavor was requested).
-                    sReplyOrForward.ForwardReply(pReq->m_hForwardReplyPort,
-                                                 pReq->m_eNotificationType,
-                                                 pReq->m_hTargetThread,
-                                                 pReq->m_eNotificationFlavor,
-                                                 &sMessage);
-
-                    // Unlink the context record we saved and deallocate it now the request has been handled.
-                    if (pPrevReq)
-                        pPrevReq->m_pNext = pReq->m_pNext;
-                    else
-                        pOutstandingForwards = pReq->m_pNext;
-
-                    free(pReq);
-
-                    // Destroy the port we allocated just to receive the reply (this implicitly removes the
-                    // port from the port set).
-                    MachRet = mach_port_destroy(mach_task_self(), sMessage.GetLocalPort());
-                    CHECK_MACH("mach_port_destroy", MachRet);
-
-                    NONPAL_TRACE("    Sent reply back to original sender.\n");
-                    break;
-                }
-
-                pPrevReq = pReq;
-                pReq = pReq->m_pNext;
-            }
-
-            if (!fFoundNotification)
-                NONPAL_RETAIL_ASSERT("Failed to find original request.");
+            NONPAL_TRACE("Exception reply - ignored\n");
         }
-        else if (sMessage.IsSendOnceDestroyedNotify())
+        else
         {
-            // It's possible that when we forward an exception notification that the receiver destroys the
-            // message (by destroying the reply port) rather than replying. In this case we receive this
-            // notification message.
-
-            // Locate the forwarding context we stored away to track this notification.
-            bool fFoundNotification = false;
-            ForwardedNotification *pReq = pOutstandingForwards;
-            ForwardedNotification *pPrevReq = NULL;
-            while (pReq)
-            {
-                // We match the reply to the original request based on the port the notification was sent to
-                // (we allocate a new port for every notification we forward).
-                if (pReq->m_hListenReplyPort == sMessage.GetLocalPort())
-                {
-                    fFoundNotification = true;
-
-                    // Destroy the port we allocated just to receive the reply (this implicitly removes the
-                    // port from the port set).
-                    MachRet = mach_port_destroy(mach_task_self(), sMessage.GetLocalPort());
-                    CHECK_MACH("mach_port_destroy", MachRet);
-
-                    // Destroy the port for the reply to the original notification. This effectively forwards
-                    // the reply we just received (i.e. the exception has been handled and no further reply is
-                    // going to be sent).
-                    MachRet = mach_port_destroy(mach_task_self(), pReq->m_hForwardReplyPort);
-                    CHECK_MACH("mach_port_destroy", MachRet);
+            NONPAL_RETAIL_ASSERT("Unknown message type: %u", sMessage.GetMessageType());
+        }
+    }
+}
 
-                    // Unlink the context record we saved and deallocate it now the request has been handled.
-                    if (pPrevReq)
-                        pPrevReq->m_pNext = pReq->m_pNext;
-                    else
-                        pOutstandingForwards = pReq->m_pNext;
+void ForwardMachException(CPalThread *pThread, MachMessage *pMessage)
+{
+    thread_act_t hThread = pThread->GetMachPortSelf();
+    MachMessage sReplyOrForward;
 
-                    free(pReq);
+    // Locate the record of previously installed handlers that the target thread keeps.
+    CorUnix::CThreadMachExceptionHandlers *pHandlers = pThread->GetSavedMachHandlers();
 
-                    NONPAL_TRACE("    Destroyed original sender's port.\n");
-                    break;
-                }
+    // Check whether there's even a handler for the particular exception we've been handed.
+    CorUnix::MachExceptionHandler sHandler;
+    if (pHandlers->GetHandler(pMessage->GetException(), &sHandler))
+    {
+        NONPAL_TRACE("Forward request to port %08x\n", sHandler.m_handler);
 
-                pPrevReq = pReq;
-                pReq = pReq->m_pNext;
-            }
+        // Forward the notification
+        sReplyOrForward.ForwardNotification(&sHandler, pMessage);
 
-            if (!fFoundNotification)
-                NONPAL_RETAIL_ASSERT("Failed to find original request.");
-        }
-        else
+        // Spin wait until this thread is hijacked or the process is aborted.
+        while (TRUE)
         {
-            NONPAL_RETAIL_ASSERT("Unknown message type: %u", sMessage.GetMessageType());
+            sched_yield();
         }
     }
+    else
+    {
+        // There's no previous handler to forward this notification to.
+        NONPAL_TRACE("Unhandled exception and no chain-back - aborting process\n");
+        PROCAbort();
+    }
 }
-#endif // !DISABLE_EXCEPTIONS
 
-PAL_NORETURN void MachSetThreadContext(CONTEXT *lpContext)
+PAL_NORETURN 
+void MachSetThreadContext(CONTEXT *lpContext)
 {
-#ifndef DISABLE_EXCEPTIONS
     // We need to send a message to the worker thread so that it can set our thread context
     // It is responsible for deallocating the thread port.
     MachMessage sRequest;
     sRequest.SendSetThread(s_ExceptionPort, mach_thread_self(), lpContext);
-#else // !DISABLE_EXCEPTIONS
-    ASSERT("MachSetThreadContext not allowed for DISABLE_EXCEPTIONS\n");
-    TerminateProcess(GetCurrentProcess(), (UINT)(-1));
-#endif // !DISABLE_EXCEPTIONS
 
     // Make sure we don't do anything
     while (TRUE)
@@ -1624,11 +1182,6 @@ Return value :
 --*/
 BOOL SEHInitializeMachExceptions (void)
 {
-#if !DISABLE_EXCEPTIONS
-    // Prime the location of CoreCLR so that we don't deadlock under
-    // dladdr with a pthread_mutex_lock.
-    IsWithinCoreCLR(NULL);
-
     kern_return_t MachRet;
     int CreateRet;
     pthread_t exception_thread;
@@ -1658,72 +1211,6 @@ BOOL SEHInitializeMachExceptions (void)
         return FALSE;
     }
 
-    // Allocate a second port used to receive exceptions after a host has called
-    // ICLRRuntimeHost2::RegisterMacEHPort() on a thread. Hosts do this in case another component has
-    // registered a handler on the thread after the CoreCLR but is not chaining back exceptions to us. In
-    // order to avoid losing the chain-back information we stashed ourselves when we first registered (which
-    // would make us just as badly behaved) we keep two sets of chain back information and register two
-    // exception ports. Which port we receive an exception notification on will tell us which handler we
-    // should chain back to.
-
-    MachRet = mach_port_allocate(mach_task_self(),
-                                 MACH_PORT_RIGHT_RECEIVE,
-                                 &s_TopExceptionPort);
-
-    if (MachRet != KERN_SUCCESS)
-    {
-        ASSERT("mach_port_allocate failed: %d\n", MachRet);
-        UTIL_SetLastErrorFromMach(MachRet);
-        return FALSE;
-    }
-
-    // Insert the send right into the task
-    MachRet = mach_port_insert_right(mach_task_self(),
-                                     s_TopExceptionPort,
-                                     s_TopExceptionPort,
-                                     MACH_MSG_TYPE_MAKE_SEND);
-
-    if (MachRet != KERN_SUCCESS)
-    {
-        ASSERT("mach_port_insert_right failed: %d\n", MachRet);
-        UTIL_SetLastErrorFromMach(MachRet);
-        return FALSE;
-    }
-
-    // Since we now have two exception ports plus additional reply ports used to capture replies to forwarded
-    // notifications we need to be able to wait on more than one port at a time. Therefore we listen on a port
-    // set rather than a single port (the ports allocated above are the only members initially).
-    MachRet = mach_port_allocate(mach_task_self(),
-                                 MACH_PORT_RIGHT_PORT_SET,
-                                 &s_ExceptionPortSet);
-    if (MachRet != KERN_SUCCESS)
-    {
-        ASSERT("mach_port_allocate failed: %d\n", MachRet);
-        UTIL_SetLastErrorFromMach(MachRet);
-        return FALSE;
-    }
-
-    // Move the ports we allocated above into the port set.
-    MachRet = mach_port_move_member(mach_task_self(),
-                                    s_ExceptionPort,
-                                    s_ExceptionPortSet);
-    if (MachRet != KERN_SUCCESS)
-    {
-        ASSERT("mach_port_move_member failed: %d\n", MachRet);
-        UTIL_SetLastErrorFromMach(MachRet);
-        return FALSE;
-    }
-
-    MachRet = mach_port_move_member(mach_task_self(),
-                                    s_TopExceptionPort,
-                                    s_ExceptionPortSet);
-    if (MachRet != KERN_SUCCESS)
-    {
-        ASSERT("mach_port_move_member failed: %d\n", MachRet);
-        UTIL_SetLastErrorFromMach(MachRet);
-        return FALSE;
-    }
-
     // Create the thread that will listen to the exception for all threads
     CreateRet = pthread_create(&exception_thread, NULL, SEHExceptionThread, NULL);
 
@@ -1740,14 +1227,12 @@ BOOL SEHInitializeMachExceptions (void)
         return FALSE;
     }
 #endif // !FEATURE_PAL_SXS
-#endif // !DISABLE_EXCEPTIONS
 
     // Tell the system to ignore SIGPIPE signals rather than use the default
     // behavior of terminating the process. Ignoring SIGPIPE will cause
     // calls that would otherwise raise that signal to return EPIPE instead.
     // The PAL expects EPIPE from those functions and won't handle a
     // SIGPIPE signal.
-// TODO: move to palrt startup code
     signal(SIGPIPE, SIG_IGN);
 
     // We're done
@@ -1766,7 +1251,6 @@ Return value :
 --*/
 void MachExceptionInitializeDebug(void)
 {
-#if !DISABLE_EXCEPTIONS
     if (s_DebugInitialized == FALSE)
     {
 #ifndef FEATURE_PAL_SXS
@@ -1784,7 +1268,6 @@ void MachExceptionInitializeDebug(void)
 #endif // !FEATURE_PAL_SXS
         s_DebugInitialized = TRUE;
     }
-#endif // !DISABLE_EXCEPTIONS
 }
 
 /*++
@@ -1823,7 +1306,7 @@ extern "C" void ActivationHandler(CONTEXT* context)
 extern "C" void ActivationHandlerWrapper();
 extern "C" int ActivationHandlerReturnOffset;
 
-PAL_ERROR InjectActivationInternal(CorUnix::CPalThread* pThread)
+PAL_ERROR InjectActivationInternal(CPalThread* pThread)
 {
     PAL_ERROR palError;
 
index 9424b5e..a06bf8d 100644 (file)
@@ -63,10 +63,17 @@ Abstract:
 MachMessage::MachMessage()
 {
     m_fPortsOwned = false;
-    
     ResetMessage();
 }
 
+void MachMessage::InitializeFrom(const MachMessage& source)
+{
+    m_fPortsOwned = false;
+    ResetMessage();
+
+    memcpy(&m_rgMessageBuffer, &source.m_rgMessageBuffer, sizeof(m_rgMessageBuffer));
+}
+
 // Listen for the next message on the given port and initialize this class with the contents. The message type
 // must match one of the MessageTypes indicated above (or the process will be aborted).
 void MachMessage::Receive(mach_port_t hPort)
@@ -102,7 +109,6 @@ void MachMessage::Receive(mach_port_t hPort)
     case EXCEPTION_RAISE_REPLY_64_MESSAGE_ID:
     case EXCEPTION_RAISE_STATE_REPLY_64_MESSAGE_ID:
     case EXCEPTION_RAISE_STATE_IDENTITY_REPLY_64_MESSAGE_ID:
-    case NOTIFY_SEND_ONCE_MESSAGE_ID:
         break;
     default:
         FATAL_ERROR("Unsupported message type: %u", m_pMessage->header.msgh_id);
@@ -151,12 +157,6 @@ bool MachMessage::IsExceptionReply()
     }
 }
 
-// Indicates whether the message is a notification that a send-once message was destroyed by the receiver.
-bool MachMessage::IsSendOnceDestroyedNotify()
-{
-    return m_pMessage->header.msgh_id == NOTIFY_SEND_ONCE_MESSAGE_ID;
-}
-
 // Returns the type code for a received message.
 MachMessage::MessageType MachMessage::GetMessageType()
 {
@@ -473,7 +473,7 @@ size_t MachMessage::GetThreadState(thread_state_flavor_t eFlavor, thread_state_t
     {
         // There's a state in the message, but we need to check that the flavor matches what the caller's
         // after (if not we'll fall through and get the correct flavor below).
-        if (m_pMessage->data.raise_state.flavor == eFlavor)
+        if (m_pMessage->data.raise_state_identity.flavor == eFlavor)
         {
             cbState = m_pMessage->data.raise_state_identity.old_state_count * sizeof(natural_t);
             memcpy(pState,
@@ -488,7 +488,7 @@ size_t MachMessage::GetThreadState(thread_state_flavor_t eFlavor, thread_state_t
     {
         // There's a state in the message, but we need to check that the flavor matches what the caller's
         // after (if not we'll fall through and get the correct flavor below).
-        if (m_pMessage->data.raise_state_64.flavor == eFlavor)
+        if (m_pMessage->data.raise_state_identity_64.flavor == eFlavor)
         {
             cbState = m_pMessage->data.raise_state_identity_64.old_state_count * sizeof(natural_t);
             memcpy(pState,
@@ -533,7 +533,7 @@ size_t MachMessage::GetThreadState(thread_state_flavor_t eFlavor, thread_state_t
     {
         // There's a state in the message, but we need to check that the flavor matches what the caller's
         // after (if not we'll fall through and get the correct flavor below).
-        if (m_pMessage->data.raise_state_reply.flavor == eFlavor)
+        if (m_pMessage->data.raise_state_identity_reply.flavor == eFlavor)
         {
             cbState = m_pMessage->data.raise_state_identity_reply.new_state_count * sizeof(natural_t);
             memcpy(pState,
@@ -548,7 +548,7 @@ size_t MachMessage::GetThreadState(thread_state_flavor_t eFlavor, thread_state_t
     {
         // There's a state in the message, but we need to check that the flavor matches what the caller's
         // after (if not we'll fall through and get the correct flavor below).
-        if (m_pMessage->data.raise_state_reply_64.flavor == eFlavor)
+        if (m_pMessage->data.raise_state_identity_reply_64.flavor == eFlavor)
         {
             cbState = m_pMessage->data.raise_state_identity_reply_64.new_state_count * sizeof(natural_t);
             memcpy(pState,
@@ -566,10 +566,7 @@ size_t MachMessage::GetThreadState(thread_state_flavor_t eFlavor, thread_state_t
     // No state in the message or the flavor didn't match. Get the requested flavor of state directly from the
     // thread instead.
     mach_msg_type_number_t iStateCount = THREAD_STATE_MAX;
-    machret = thread_get_state(hThread ? hThread : GetThread(),
-                               eFlavor,
-                               (thread_state_t)pState,
-                               &iStateCount);
+    machret = thread_get_state(hThread ? hThread : GetThread(), eFlavor, (thread_state_t)pState, &iStateCount);
     MACH_CHECK("thread_get_state()");
 
     return iStateCount * sizeof(natural_t);
@@ -619,18 +616,9 @@ void MachMessage::SendSetThread(mach_port_t hServerPort, thread_act_t hThread, C
 // the exception type being notified. The new message takes account of the fact that the target handler may
 // not have requested the same notification behavior or flavor as our handler. A new Mach port is created to
 // receive the reply, and this port is returned to the caller. Clean up the message afterwards.
-mach_port_t MachMessage::ForwardNotification(CorUnix::MachExceptionHandler *pHandler,
-                                             MachMessage *pNotification)
+void MachMessage::ForwardNotification(CorUnix::MachExceptionHandler *pHandler, MachMessage *pNotification)
 {
     kern_return_t machret;
-    mach_port_t hReplyPort;
-    
-    // Allocate a new port dedicated to receiving the reply for this forward. This will allow us to match the
-    // reply to the original request later on.
-    machret = mach_port_allocate(mach_task_self(),
-                                 MACH_PORT_RIGHT_RECEIVE,
-                                 &hReplyPort);
-    MACH_CHECK("mach_port_allocate()");
 
     // Set the message type.
     m_pMessage->header.msgh_id = MapBehaviorToNotificationType(pHandler->m_behavior);
@@ -643,9 +631,7 @@ mach_port_t MachMessage::ForwardNotification(CorUnix::MachExceptionHandler *pHan
     // the two messages may be in different formats (e.g. RAISE vs RAISE_STATE). We silently drop data that is
     // not needed in the outgoing message and synthesize any required data that is not present in the incoming
     // message.
-
     SetThread(pNotification->GetThread());
-
     SetException(pNotification->GetException());
 
     int cCodes = pNotification->GetExceptionCodeCount();
@@ -653,6 +639,8 @@ mach_port_t MachMessage::ForwardNotification(CorUnix::MachExceptionHandler *pHan
     for (int i = 0; i < cCodes; i++)
         SetExceptionCode(i, pNotification->GetExceptionCode(i));
 
+    NONPAL_TRACE("ForwardNotification: handler thread flavor %04x\n", pHandler->m_flavor);
+
     // Don't bother fetching thread state unless the destination actually requires it.
     if (pHandler->m_flavor != THREAD_STATE_NONE)
     {
@@ -663,8 +651,8 @@ mach_port_t MachMessage::ForwardNotification(CorUnix::MachExceptionHandler *pHan
 
     // Initialize header fields.
     m_pMessage->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE);
-    m_pMessage->header.msgh_remote_port = pHandler->m_handler;  // Forward to here
-    m_pMessage->header.msgh_local_port = hReplyPort;            // The reply will come here
+    m_pMessage->header.msgh_remote_port = pHandler->m_handler;              // Forward to here
+    m_pMessage->header.msgh_local_port = pNotification->GetLocalPort();     // The reply will come here
 
     // Set the message header size field based on the contents of the message (call this function after all
     // other fields have been initialized).
@@ -682,17 +670,13 @@ mach_port_t MachMessage::ForwardNotification(CorUnix::MachExceptionHandler *pHan
 
     // Erase any stale data.
     ResetMessage();
-
-    // Return the port the reply is expected on.
-    return hReplyPort;
 }
 
 // Initialize the message to represent a reply to the given exception
 // notification and send that reply back to the original sender of the notification. This is used when our
 // handler handles the exception rather than forwarding it to a chain-back handler.
 // Clean up the message afterwards.
-void MachMessage::ReplyToNotification(MachMessage *pNotification,
-                                      kern_return_t eResult)
+void MachMessage::ReplyToNotification(MachMessage *pNotification, kern_return_t eResult)
 {
     kern_return_t machret;
 
@@ -744,74 +728,6 @@ void MachMessage::ReplyToNotification(MachMessage *pNotification,
     ResetMessage();
 }
 
-// Initialize the message to represent a reply to a notification message of
-// the given format given a reply from another handler that might be in another format and send it to the
-// given port. This is used to reply to an exception notification we didn't handle ourselves but instead
-// forwarded to a chain-back handler. Clean up the message afterwards.
-void MachMessage::ForwardReply(mach_port_t hForwardPort,
-                               MessageType eNotificationType,
-                               thread_act_t hThread,
-                               thread_state_flavor_t eNotificationFlavor,
-                               MachMessage *pReply)
-{
-    kern_return_t machret;
-
-    // Set the message type.
-    m_pMessage->header.msgh_id = MapNotificationToReplyType(eNotificationType);
-
-    // Initialize the fields that don't need any further input (this depends on the message type having been
-    // set above).
-    InitFixedFields();
-
-    SetReturnCode(pReply->GetReturnCode());
-
-    thread_state_data_t sThreadState;
-    size_t cbState;
-
-    // If the reply contains a thread state then we're expected to apply this state to the target thread.
-    if (pReply->GetMessageType() != EXCEPTION_RAISE_REPLY_MESSAGE_ID &&
-        pReply->GetMessageType() != EXCEPTION_RAISE_REPLY_64_MESSAGE_ID)
-    {
-        thread_state_flavor_t eReplyFlavor = pReply->GetThreadStateFlavor();
-        cbState = pReply->GetThreadState(eReplyFlavor, (thread_state_t)&sThreadState, hThread);
-
-        machret = thread_set_state(hThread,
-                                   eReplyFlavor,
-                                   (thread_state_t)&sThreadState,
-                                   cbState / sizeof(natural_t));
-        MACH_CHECK("thread_set_state()");
-    }
-
-    if (eNotificationFlavor != THREAD_STATE_NONE)
-    {
-        cbState = pReply->GetThreadState(eNotificationFlavor, (thread_state_t)&sThreadState, hThread);
-        SetThreadState(eNotificationFlavor, (thread_state_t)&sThreadState, cbState);
-    }
-
-    // Initialize header fields.
-    m_pMessage->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0);
-    m_pMessage->header.msgh_remote_port = hForwardPort;     // Reply goes back to the original sender
-    m_pMessage->header.msgh_local_port = 0;                 // No reply to this expected
-
-    // Set the message header size field based on the contents of the message (call this function after all
-    // other fields have been initialized).
-    InitMessageSize();
-
-    // Send the formatted message.
-    machret = mach_msg((mach_msg_header_t*)m_pMessage,
-                       MACH_SEND_MSG | MACH_MSG_OPTION_NONE,
-                       m_pMessage->header.msgh_size,
-                       0,
-                       MACH_PORT_NULL,
-                       MACH_MSG_TIMEOUT_NONE,
-                       MACH_PORT_NULL);
-    MACH_CHECK("mach_msg()");
-
-    // Erase any stale data.
-    ResetMessage();
-
-}
-
 // Re-initializes this data structure (to the same state as default construction, containing no message).
 void MachMessage::ResetMessage()
 {
index cb80890..b0e56d0 100644 (file)
@@ -46,8 +46,8 @@ typedef       mach_exception_data_type_t      mach_exception_subcode_t;
 #ifdef _DEBUG
 
 // Debug-only output with printf-style formatting.
-#define NONPAL_TRACE(_format, ...) do {                                 \
-        if (getenv("NONPAL_TRACING")) printf(_format, ## __VA_ARGS__);  \
+#define NONPAL_TRACE(_format, ...) do {                                                  \
+        if (getenv("NONPAL_TRACING")) printf("NONPAL_TRACE: " _format, ## __VA_ARGS__);  \
     } while (false)
 #else // _DEBUG
 #define NONPAL_TRACE(_format, ...)
@@ -81,9 +81,12 @@ public:
     };
 
     // Construct an empty message. Use Receive() to form a message that can be inspected or SendSetThread(),
-    // ForwardNotification(), ReplyToNotification() or ForwardReply() to construct a message and sent it.
+    // ForwardNotification() or ReplyToNotification() to construct a message and sent it.
     MachMessage();
 
+    // Initializes this message from another
+    void InitializeFrom(const MachMessage& source);
+
     // Listen for the next message on the given port and initialize this class with the contents. The message
     // type must match one of the MessageTypes indicated above (or the process will be aborted).
     void Receive(mach_port_t hPort);
@@ -128,26 +131,14 @@ public:
     // Initialize the message (overwriting any previous content) to represent a forwarded version of the given
     // exception notification message and send that message to the chain-back handler previously registered
     // for the exception type being notified. The new message takes account of the fact that the target
-    // handler may not have requested the same notification behavior or flavor as our handler. A new Mach port
-    // is created to receive the reply, and this port is returned to the caller.
-    mach_port_t ForwardNotification(CorUnix::MachExceptionHandler *pHandler,
-                                    MachMessage *pNotification);
+    // handler may not have requested the same notification behavior or flavor as our handler. Blocks until
+    // the reply is received.
+    void ForwardNotification(CorUnix::MachExceptionHandler *pHandler, MachMessage *pNotification);
 
     // Initialize the message (overwriting any previous content) to represent a reply to the given exception
     // notification and send that reply back to the original sender of the notification. This is used when our
     // handler handles the exception rather than forwarding it to a chain-back handler.
-    void ReplyToNotification(MachMessage *pNotification,
-                             kern_return_t eResult);
-
-    // Initialize the message (overwriting any previous content) to represent a reply to a notification
-    // message of the given format given a reply from another handler that might be in another format and send
-    // it to the given port. This is used to reply to an exception notification we didn't handle ourselves but
-    // instead forwarded to a chain-back handler.
-    void ForwardReply(mach_port_t hForwardPort,
-                      MessageType eNotificationType,
-                      thread_act_t hThread,
-                      thread_state_flavor_t eNotificationFlavor,
-                      MachMessage *pReply);
+    void ReplyToNotification(MachMessage *pNotification, kern_return_t eResult);
 
 private:
     // The maximum size in bytes of any Mach message we can send or receive. Calculating an exact size for
index 513ff0b..e8b17e3 100644 (file)
@@ -425,8 +425,8 @@ Function:
 --*/
 kern_return_t
 CONTEXT_GetThreadContextFromPort(
-        mach_port_t Port,
-        LPCONTEXT lpContext);
+    mach_port_t Port,
+    LPCONTEXT lpContext);
 
 /*++
 Function:
@@ -436,9 +436,20 @@ Function:
 --*/
 kern_return_t
 CONTEXT_SetThreadContextOnPort(
-           mach_port_t Port,
-           IN CONST CONTEXT *lpContext);
+   mach_port_t Port,
+   IN CONST CONTEXT *lpContext);
 
+/*++
+Function:
+  GetThreadContextFromThreadState
+
+  Helper for mach exception support
+--*/
+void
+CONTEXT_GetThreadContextFromThreadState(
+    thread_state_flavor_t stateFlavor,
+    thread_state_t threadState,
+    LPCONTEXT lpContext);
 
 #else // HAVE_MACH_EXCEPTIONS
 /*++
index 3f93df0..c41c5ad 100644 (file)
@@ -153,19 +153,6 @@ Return
 --*/
 BOOL InitializeFlushProcessWriteBuffers();
 
-#if HAVE_MACH_EXCEPTIONS
-/*++
-Function:
-  PROCThreadFromMachPort
-  
-  Given a Mach thread port, return the CPalThread associated with it.
-
-Return
-    CPalThread*
---*/
-CorUnix::CPalThread *PROCThreadFromMachPort(mach_port_t hThread);
-#endif // HAVE_MACH_EXCEPTIONS
-
 #ifdef __cplusplus
 }
 #endif // __cplusplus
index 307c8fb..c5e334d 100644 (file)
@@ -159,7 +159,7 @@ namespace CorUnix
         // Returns a pointer to the handler node that should be initialized next. The first time this is
         // called for a thread the bottom node will be returned. Thereafter the top node will be returned.
         // Also returns the Mach exception port that should be registered.
-        CThreadMachExceptionHandlerNode *GetNodeForInitialization(mach_port_t *pExceptionPort);
+        CThreadMachExceptionHandlerNode *GetNodeForInitialization();
 
         // Returns a pointer to the handler node for cleanup. This will always be the bottom node. This isn't
         // really the right algorithm (because there isn't one). There are lots of reasonable scenarios where
@@ -167,22 +167,18 @@ namespace CorUnix
         // can support a lot more chaining scenarios but we can't pull the same sort of trick when
         // unregistering, in particular we have two sets of chain back handlers and no way to reach into other
         // components and alter what their chain-back information is).
-        CThreadMachExceptionHandlerNode *GetNodeForCleanup() { return &m_bottom; }
+        CThreadMachExceptionHandlerNode *GetNodeForCleanup() { return &m_node; }
 
         // Get handler details for a given type of exception. If successful the structure pointed at by
-        // pHandler is filled in and true is returned. Otherwise false is returned. The fTopException argument
-        // indicates whether the handlers found at the time of a call to ICLRRuntimeHost2::RegisterMacEHPort()
-        // should be searched (if not, or a handler is not found there, we'll fallback to looking at the
-        // handlers discovered at the point when the CLR first saw this thread).
-        bool GetHandler(exception_type_t eException, bool fTopException, MachExceptionHandler *pHandler);
+        // pHandler is filled in and true is returned. Otherwise false is returned.
+        bool GetHandler(exception_type_t eException, MachExceptionHandler *pHandler);
 
     private:
         // Look for a handler for the given exception within the given handler node. Return its index if
         // successful or -1 otherwise.
         int GetIndexOfHandler(exception_mask_t bmExceptionMask, CThreadMachExceptionHandlerNode *pNode);
 
-        CThreadMachExceptionHandlerNode m_top;
-        CThreadMachExceptionHandlerNode m_bottom;
+        CThreadMachExceptionHandlerNode m_node;
     };
 #endif // HAVE_MACH_EXCEPTIONS
 #endif // FEATURE_PAL_SXS
index 732fe9a..f561c59 100644 (file)
@@ -39,24 +39,6 @@ SET_DEFAULT_DEBUG_CHANNEL(MEM);
 #define DUMMY_HEAP 0x01020304
 #endif // __APPLE__
 
-#ifdef __APPLE__
-#define CACHE_HEAP_ZONE
-#endif // __APPLE__
-
-#ifdef CACHE_HEAP_ZONE
-/* This is a kludge.
- *
- * We need to know whether an instruction pointer fault is in our executable
- * heap, but the intersection between the HeapX functions on Windows and the
- * malloc_zone functions on Mac OS X are somewhat at odds and we'd have to 
- * implement an unnecessarily complicated HeapWalk. Instead, we cache the only
- * "heap" we create, knowing it's the executable heap, and use that instead
- * with the much simpler malloc_zone_from_ptr.
- */
-extern malloc_zone_t *s_pExecutableHeap;
-malloc_zone_t *s_pExecutableHeap = NULL;
-#endif // CACHE_HEAP_ZONE
-
 /*++
 Function:
   RtlMoveMemory
@@ -172,13 +154,6 @@ GetProcessHeap(
 #else
     malloc_zone_t *pZone = malloc_default_zone();
     ret = (HANDLE)pZone;
-#ifdef CACHE_HEAP_ZONE
-    if (s_pExecutableHeap == NULL)
-    {
-        s_pExecutableHeap = pZone;
-        TRACE("s_pExecutableHeap is %p (process heap).\n", s_pExecutableHeap);
-    }
-#endif // CACHE_HEAP_ZONE
 #endif // HEAP_HANDLES_ARE_REAL_HANDLES
 #else
     ret = (HANDLE) DUMMY_HEAP;
index 644b1d5..1202320 100644 (file)
@@ -30,7 +30,7 @@ Abstract:
 #include <errno.h>
 #include <unistd.h>
 
-SET_DEFAULT_DEBUG_CHANNEL(DEBUG);
+SET_DEFAULT_DEBUG_CHANNEL(THREAD);
 
 extern PGET_GCMARKER_EXCEPTION_CODE g_getGcMarkerExceptionCode;
 
@@ -832,8 +832,8 @@ Function:
 --*/
 kern_return_t
 CONTEXT_GetThreadContextFromPort(
-        mach_port_t Port,
-        LPCONTEXT lpContext)
+    mach_port_t Port,
+    LPCONTEXT lpContext)
 {
     // Extract the CONTEXT from the Mach thread.
     
@@ -841,7 +841,7 @@ CONTEXT_GetThreadContextFromPort(
     mach_msg_type_number_t StateCount;
     thread_state_flavor_t StateFlavor;
   
-    if (lpContext->ContextFlags & (CONTEXT_CONTROL|CONTEXT_INTEGER))
+    if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS))
     {
 #ifdef _X86_  
         x86_thread_state32_t State;
@@ -852,67 +852,15 @@ CONTEXT_GetThreadContextFromPort(
 #else
 #error Unexpected architecture.
 #endif
-
         StateCount = sizeof(State) / sizeof(natural_t);
-
-        MachRet = thread_get_state(Port,
-           StateFlavor,
-           (thread_state_t)&State,
-           &StateCount);
+        MachRet = thread_get_state(Port, StateFlavor, (thread_state_t)&State, &StateCount);
         if (MachRet != KERN_SUCCESS)
         {
             ASSERT("thread_get_state(THREAD_STATE) failed: %d\n", MachRet);
-            goto EXIT;
+            goto exit;
         }
 
-        // Copy in the GPRs and the various other control registers
-#ifdef _X86_
-        lpContext->Eax = State.eax;
-        lpContext->Ebx = State.ebx;
-        lpContext->Ecx = State.ecx;
-        lpContext->Edx = State.edx;
-        lpContext->Edi = State.edi;
-        lpContext->Esi = State.esi;
-        lpContext->Ebp = State.ebp;
-        lpContext->Esp = State.esp;
-        lpContext->SegSs = State.ss;
-        lpContext->EFlags = State.eflags;
-        lpContext->Eip = State.eip;
-        lpContext->SegCs = State.cs;
-        lpContext->SegDs_PAL_Undefined = State.ds;
-        lpContext->SegEs_PAL_Undefined = State.es;
-        lpContext->SegFs_PAL_Undefined = State.fs;
-        lpContext->SegGs_PAL_Undefined = State.gs;
-#elif defined(_AMD64_)
-        lpContext->Rax = State.__rax;
-        lpContext->Rbx = State.__rbx;
-        lpContext->Rcx = State.__rcx;
-        lpContext->Rdx = State.__rdx;
-        lpContext->Rdi = State.__rdi;
-        lpContext->Rsi = State.__rsi;
-        lpContext->Rbp = State.__rbp;
-        lpContext->Rsp = State.__rsp;
-        lpContext->R8 = State.__r8;
-        lpContext->R9 = State.__r9;
-        lpContext->R10 = State.__r10;
-        lpContext->R11 = State.__r11;
-        lpContext->R12 = State.__r12;
-        lpContext->R13 = State.__r13;
-        lpContext->R14 = State.__r14;
-        lpContext->R15 = State.__r15;
-        lpContext->EFlags = State.__rflags;
-        lpContext->Rip = State.__rip;
-        lpContext->SegCs = State.__cs;
-        // RtlRestoreContext uses the actual ss instead of this one
-        // to build the iret frame so just set it zero.
-        lpContext->SegSs = 0;
-        lpContext->SegDs = 0;
-        lpContext->SegEs = 0;
-        lpContext->SegFs = State.__fs;
-        lpContext->SegGs = State.__gs;
-#else
-#error Unexpected architecture.
-#endif
+        CONTEXT_GetThreadContextFromThreadState(StateFlavor, (thread_state_t)&State, lpContext);
     }
     
     if (lpContext->ContextFlags & CONTEXT_ALL_FLOATING) {
@@ -926,73 +874,173 @@ CONTEXT_GetThreadContextFromPort(
 #error Unexpected architecture.
 #endif
         StateCount = sizeof(State) / sizeof(natural_t);
-        
-        MachRet = thread_get_state(Port,
-            StateFlavor,
-            (thread_state_t)&State,
-            &StateCount);
+        MachRet = thread_get_state(Port, StateFlavor, (thread_state_t)&State, &StateCount);
         if (MachRet != KERN_SUCCESS)
         {
             ASSERT("thread_get_state(FLOAT_STATE) failed: %d\n", MachRet);
-            goto EXIT;
+            goto exit;
         }
         
-        if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT)
-        {
-            // Copy the FPRs
+        CONTEXT_GetThreadContextFromThreadState(StateFlavor, (thread_state_t)&State, lpContext);
+    }
+
+exit:
+    return MachRet;
+}
+
+/*++
+Function:
+  CONTEXT_GetThreadContextFromThreadState
+
+--*/
+void
+CONTEXT_GetThreadContextFromThreadState(
+    thread_state_flavor_t threadStateFlavor,
+    thread_state_t threadState,
+    LPCONTEXT lpContext)
+{
+    switch (threadStateFlavor)
+    {
 #ifdef _X86_
-            lpContext->FloatSave.ControlWord = *(DWORD*)&State.fpu_fcw;
-            lpContext->FloatSave.StatusWord = *(DWORD*)&State.fpu_fsw;
-            lpContext->FloatSave.TagWord = State.fpu_ftw;
-            lpContext->FloatSave.ErrorOffset = State.fpu_ip;
-            lpContext->FloatSave.ErrorSelector = State.fpu_cs;
-            lpContext->FloatSave.DataOffset = State.fpu_dp;
-            lpContext->FloatSave.DataSelector = State.fpu_ds;
-            lpContext->FloatSave.Cr0NpxState = State.fpu_mxcsr;
-            
-            // Windows stores the floating point registers in a packed layout (each 10-byte register end to end
-            // for a total of 80 bytes). But Mach returns each register in an 16-bit structure (presumably for
-            // alignment purposes). So we can't just memcpy the registers over in a single block, we need to copy
-            // them individually.
-            for (int i = 0; i < 8; i++)
-                memcpy(&lpContext->FloatSave.RegisterArea[i * 10], (&State.fpu_stmm0)[i].mmst_reg, 10);
+        case x86_THREAD_STATE32:
+            if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS))
+            {
+                x86_thread_state32_t *pState = (x86_thread_state32_t *)threadState;
+
+                lpContext->Eax = pState->eax;
+                lpContext->Ebx = pState->ebx;
+                lpContext->Ecx = pState->ecx;
+                lpContext->Edx = pState->edx;
+                lpContext->Edi = pState->edi;
+                lpContext->Esi = pState->esi;
+                lpContext->Ebp = pState->ebp;
+                lpContext->Esp = pState->esp;
+                lpContext->SegSs = pState->ss;
+                lpContext->EFlags = pState->eflags;
+                lpContext->Eip = pState->eip;
+                lpContext->SegCs = pState->cs;
+                lpContext->SegDs_PAL_Undefined = pState->ds;
+                lpContext->SegEs_PAL_Undefined = pState->es;
+                lpContext->SegFs_PAL_Undefined = pState->fs;
+                lpContext->SegGs_PAL_Undefined = pState->gs;
+            }
+            break;
+
+        case x86_FLOAT_STATE32:
+        {
+            x86_float_state32_t *pState = (x86_float_state32_t *)threadState;
+
+            if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT)
+            {
+                lpContext->FloatSave.ControlWord = *(DWORD*)&pState->fpu_fcw;
+                lpContext->FloatSave.StatusWord = *(DWORD*)&pState->fpu_fsw;
+                lpContext->FloatSave.TagWord = pState->fpu_ftw;
+                lpContext->FloatSave.ErrorOffset = pState->fpu_ip;
+                lpContext->FloatSave.ErrorSelector = pState->fpu_cs;
+                lpContext->FloatSave.DataOffset = pState->fpu_dp;
+                lpContext->FloatSave.DataSelector = pState->fpu_ds;
+                lpContext->FloatSave.Cr0NpxState = pState->fpu_mxcsr;
+
+                // Windows stores the floating point registers in a packed layout (each 10-byte register end to end
+                // for a total of 80 bytes). But Mach returns each register in an 16-bit structure (presumably for
+                // alignment purposes). So we can't just memcpy the registers over in a single block, we need to copy
+                // them individually.
+                for (int i = 0; i < 8; i++)
+                    memcpy(&lpContext->FloatSave.RegisterArea[i * 10], (&pState->fpu_stmm0)[i].mmst_reg, 10);
+            }
+
+            if (lpContext->ContextFlags & CONTEXT_EXTENDED_REGISTERS)
+            {
+                // The only extended register information that Mach will tell us about are the xmm register values.
+                // Both Windows and Mach store the registers in a packed layout (each of the 8 registers is 16 bytes)
+                // so we can simply memcpy them across.
+                memcpy(lpContext->ExtendedRegisters + CONTEXT_EXREG_XMM_OFFSET, &pState->fpu_xmm0, 8 * 16);
+            }
+        }
+        break;
+
 #elif defined(_AMD64_)
-            lpContext->FltSave.ControlWord = *(DWORD*)&State.__fpu_fcw;
-            lpContext->FltSave.StatusWord = *(DWORD*)&State.__fpu_fsw;
-            lpContext->FltSave.TagWord = State.__fpu_ftw;
-            lpContext->FltSave.ErrorOffset = State.__fpu_ip;
-            lpContext->FltSave.ErrorSelector = State.__fpu_cs;
-            lpContext->FltSave.DataOffset = State.__fpu_dp;
-            lpContext->FltSave.DataSelector = State.__fpu_ds;
-            lpContext->FltSave.MxCsr = State.__fpu_mxcsr;
-            lpContext->FltSave.MxCsr_Mask = State.__fpu_mxcsrmask; // note: we don't save the mask for x86
-            
-            // Windows stores the floating point registers in a packed layout (each 10-byte register end to end
-            // for a total of 80 bytes). But Mach returns each register in an 16-bit structure (presumably for
-            // alignment purposes). So we can't just memcpy the registers over in a single block, we need to copy
-            // them individually.
-            for (int i = 0; i < 8; i++)
-                memcpy(&lpContext->FltSave.FloatRegisters[i], (&State.__fpu_stmm0)[i].__mmst_reg, 10);
-            
-            // AMD64's FLOATING_POINT includes the xmm registers.
-            memcpy(&lpContext->Xmm0, &State.__fpu_xmm0, 8 * 16);
+        case x86_THREAD_STATE64:
+            if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS))
+            {
+                x86_thread_state64_t *pState = (x86_thread_state64_t *)threadState;
+
+                lpContext->Rax = pState->__rax;
+                lpContext->Rbx = pState->__rbx;
+                lpContext->Rcx = pState->__rcx;
+                lpContext->Rdx = pState->__rdx;
+                lpContext->Rdi = pState->__rdi;
+                lpContext->Rsi = pState->__rsi;
+                lpContext->Rbp = pState->__rbp;
+                lpContext->Rsp = pState->__rsp;
+                lpContext->R8 = pState->__r8;
+                lpContext->R9 = pState->__r9;
+                lpContext->R10 = pState->__r10;
+                lpContext->R11 = pState->__r11;
+                lpContext->R12 = pState->__r12;
+                lpContext->R13 = pState->__r13;
+                lpContext->R14 = pState->__r14;
+                lpContext->R15 = pState->__r15;
+                lpContext->EFlags = pState->__rflags;
+                lpContext->Rip = pState->__rip;
+                lpContext->SegCs = pState->__cs;
+                // RtlRestoreContext uses the actual ss instead of this one
+                // to build the iret frame so just set it zero.
+                lpContext->SegSs = 0;
+                lpContext->SegDs = 0;
+                lpContext->SegEs = 0;
+                lpContext->SegFs = pState->__fs;
+                lpContext->SegGs = pState->__gs;
+            }
+            break;
+
+        case x86_FLOAT_STATE64:
+            if (lpContext->ContextFlags & CONTEXT_FLOATING_POINT)
+            {
+                x86_float_state64_t *pState = (x86_float_state64_t *)threadState;
+
+                lpContext->FltSave.ControlWord = *(DWORD*)&pState->__fpu_fcw;
+                lpContext->FltSave.StatusWord = *(DWORD*)&pState->__fpu_fsw;
+                lpContext->FltSave.TagWord = pState->__fpu_ftw;
+                lpContext->FltSave.ErrorOffset = pState->__fpu_ip;
+                lpContext->FltSave.ErrorSelector = pState->__fpu_cs;
+                lpContext->FltSave.DataOffset = pState->__fpu_dp;
+                lpContext->FltSave.DataSelector = pState->__fpu_ds;
+                lpContext->FltSave.MxCsr = pState->__fpu_mxcsr;
+                lpContext->FltSave.MxCsr_Mask = pState->__fpu_mxcsrmask; // note: we don't save the mask for x86
+
+                // Windows stores the floating point registers in a packed layout (each 10-byte register end to end
+                // for a total of 80 bytes). But Mach returns each register in an 16-bit structure (presumably for
+                // alignment purposes). So we can't just memcpy the registers over in a single block, we need to copy
+                // them individually.
+                for (int i = 0; i < 8; i++)
+                    memcpy(&lpContext->FltSave.FloatRegisters[i], (&pState->__fpu_stmm0)[i].__mmst_reg, 10);
+
+                // AMD64's FLOATING_POINT includes the xmm registers.
+                memcpy(&lpContext->Xmm0, &pState->__fpu_xmm0, 8 * 16);
+            }
+            break;
 #else
 #error Unexpected architecture.
 #endif
+        case x86_THREAD_STATE:
+        {
+            x86_thread_state_t *pState = (x86_thread_state_t *)threadState;
+            CONTEXT_GetThreadContextFromThreadState((thread_state_flavor_t)pState->tsh.flavor, (thread_state_t)&pState->uts, lpContext);
         }
+        break;
 
-#ifdef _X86_
-        if (lpContext->ContextFlags & CONTEXT_EXTENDED_REGISTERS) {
-            // The only extended register information that Mach will tell us about are the xmm register values.
-            // Both Windows and Mach store the registers in a packed layout (each of the 8 registers is 16 bytes)
-            // so we can simply memcpy them across.
-            memcpy(lpContext->ExtendedRegisters + CONTEXT_EXREG_XMM_OFFSET, &State.fpu_xmm0, 8 * 16);
+        case x86_FLOAT_STATE:
+        {
+            x86_float_state_t *pState = (x86_float_state_t *)threadState;
+            CONTEXT_GetThreadContextFromThreadState((thread_state_flavor_t)pState->fsh.flavor, (thread_state_t)&pState->ufs, lpContext);
         }
-#endif
-    }
+        break;
 
-EXIT:
-    return MachRet;
+        default:
+            ASSERT("Invalid thread state flavor %d\n", threadStateFlavor);
+            break;
+    }
 }
 
 /*++
index 3d9a9c4..6e29dc9 100644 (file)
@@ -4290,38 +4290,6 @@ getPath(
     return FALSE;
 }
 
-#if HAVE_MACH_EXCEPTIONS
-/*++
-Function:
-  PROCThreadFromMachPort
-  
-  Given a Mach thread port, return the CPalThread associated with it.
-
-Return
-    CPalThread*
---*/
-CorUnix::CPalThread *PROCThreadFromMachPort(mach_port_t hTargetThread)
-{
-    CorUnix::CPalThread *pThread;
-
-    PROCProcessLock();
-
-    pThread = pGThreadList;
-    while (pThread)
-    {
-        mach_port_t hThread = pThread->GetMachPortSelf();
-        if (hThread == hTargetThread)
-            break;
-
-        pThread = pThread->GetNext();
-    }
-    
-    PROCProcessUnlock();
-
-    return pThread;
-}
-#endif // HAVE_MACH_EXCEPTIONS
-
 /*++
 Function:
     ~CProcProcessLocalData
index 3380715..001a0b9 100644 (file)
@@ -2716,53 +2716,22 @@ PAL_InjectActivation(
 #if HAVE_MACH_EXCEPTIONS
 
 extern mach_port_t s_ExceptionPort;
-extern mach_port_t s_TopExceptionPort;
 
 // Returns a pointer to the handler node that should be initialized next. The first time this is called for a
 // thread the bottom node will be returned. Thereafter the top node will be returned. Also returns the Mach
 // exception port that should be registered.
-CorUnix::CThreadMachExceptionHandlerNode *CorUnix::CThreadMachExceptionHandlers::GetNodeForInitialization(mach_port_t *pExceptionPort)
+CorUnix::CThreadMachExceptionHandlerNode *CorUnix::CThreadMachExceptionHandlers::GetNodeForInitialization()
 {
-    if (m_bottom.m_nPorts == -1)
-    {
-        // Thread hasn't registered handlers before. Return the bottom handler node and exception port.
-        *pExceptionPort = s_ExceptionPort;
-        return &m_bottom;
-    }
-    else
-    {
-        // Othewise use the top handler node and register the top exception port.
-        *pExceptionPort = s_TopExceptionPort;
-        return &m_top;
-    }
+    return &m_node;
 }
 
 // Get handler details for a given type of exception. If successful the structure pointed at by pHandler is
-// filled in and true is returned. Otherwise false is returned. The fTopException argument indicates whether
-// the handlers found at the time of a call to ICLRRuntimeHost2::RegisterMacEHPort() should be searched (if
-// not, or a handler is not found there, we'll fallback to looking at the handlers discovered at the point
-// when the CLR first saw this thread).
-bool CorUnix::CThreadMachExceptionHandlers::GetHandler(exception_type_t eException,
-                                                       bool fTopException,
-                                                       CorUnix::MachExceptionHandler *pHandler)
+// filled in and true is returned. Otherwise false is returned.
+bool CorUnix::CThreadMachExceptionHandlers::GetHandler(exception_type_t eException, CorUnix::MachExceptionHandler *pHandler)
 {
     exception_mask_t bmExceptionMask = (1 << eException);
-    int idxHandler = -1;
-    CThreadMachExceptionHandlerNode *pNode = NULL;
-
-    // Check top handlers first if we've been asked to and they have been initialized.
-    if (fTopException && m_top.m_nPorts != -1)
-    {
-        pNode = &m_top;
-        idxHandler = GetIndexOfHandler(bmExceptionMask, pNode);
-    }
-
-    // If we haven't identified a handler yet continue looking with the bottom handlers.
-    if (idxHandler == -1)
-    {
-        pNode = &m_bottom;
-        idxHandler = GetIndexOfHandler(bmExceptionMask, pNode);
-    }
+    CThreadMachExceptionHandlerNode *pNode = &m_node;
+    int idxHandler = GetIndexOfHandler(bmExceptionMask, pNode);
 
     // Did we find a handler?
     if (idxHandler == -1)
index 1928062..470a0ca 100644 (file)
@@ -31,7 +31,7 @@ int DllTest1()
 
     PAL_TRY(VOID*, unused, NULL)
     {
-        volatile int* p = 0x00000000;   /* NULL pointer */
+        volatile int* p = (volatile int *)0x11; /* invalid pointer */
 
         bTry = TRUE;    /* indicate we hit the PAL_TRY block */
         *p = 13;        /* causes an access violation exception */
index 45413d5..c7429a9 100644 (file)
@@ -31,7 +31,7 @@ int DllTest2()
 
     PAL_TRY(VOID*, unused, NULL)
     {
-        volatile int* p = 0x00000000;   /* NULL pointer */
+        volatile int* p = (volatile int *)0x22; /* invalid pointer */
 
         bTry = TRUE;    /* indicate we hit the PAL_TRY block */
         *p = 13;        /* causes an access violation exception */
index 967963a..b9bb344 100644 (file)
@@ -746,15 +746,15 @@ void ClrFlsAssociateCallback(DWORD slot, PTLS_CALLBACK_FUNCTION callback)
     GetExecutionEngine()->TLS_AssociateCallback(slot, callback);
 }
 
-void * __stdcall ClrFlsGetBlockGeneric()
+void ** __stdcall ClrFlsGetBlockGeneric()
 {
     WRAPPER_NO_CONTRACT;
     STATIC_CONTRACT_SO_TOLERANT;
 
-    return GetExecutionEngine()->TLS_GetDataBlock();
+    return (void **) GetExecutionEngine()->TLS_GetDataBlock();
 }
 
-POPTIMIZEDTLSGETTER __ClrFlsGetBlock = (POPTIMIZEDTLSGETTER)ClrFlsGetBlockGeneric;
+CLRFLSGETBLOCK __ClrFlsGetBlock = ClrFlsGetBlockGeneric;
 
 CRITSEC_COOKIE ClrCreateCriticalSection(CrstType crstType, CrstFlags flags)
 {
index 582189c..c1aa6f0 100644 (file)
@@ -32,14 +32,14 @@ static PTLS_CALLBACK_FUNCTION Callbacks[MAX_PREDEFINED_TLS_SLOT];
 HANDLE (*g_fnGetExecutableHeapHandle)();
 #endif
 
-extern LPVOID (*__ClrFlsGetBlock)();
+extern LPVOID* (*__ClrFlsGetBlock)();
 
 //
 // FLS getter to avoid unnecessary indirection via execution engine.
 //
-VOID * ClrFlsGetBlockDirect()
+LPVOID* ClrFlsGetBlockDirect()
 {
-    return UnsafeTlsGetValue(TlsIndex);
+    return (LPVOID*)UnsafeTlsGetValue(TlsIndex);
 }
 
 //
index a65410a..f7830b4 100644 (file)
@@ -75,9 +75,10 @@ bool Disassembler::IsAvailable()
 void Disassembler::StaticInitialize()
 {
     LIMITED_METHOD_CONTRACT;
-    _ASSERTE(!IsAvailable());
 
 #if USE_COREDISTOOLS_DISASSEMBLER
+    _ASSERTE(!IsAvailable());
+
     // TODO: The 'coredistools' library will eventually be part of a NuGet package, need to be able to load
     // that using appropriate search paths
     LPCWSTR libraryName = MAKEDLLNAME(W("coredistools"));
index 7ddbe5e..c9d0704 100644 (file)
@@ -66,4 +66,10 @@ namespace ETW
     } GC_ROOT_KIND;
 };
 
+#ifdef PLATFORM_UNIX
+#define _tcslen wcslen
+#define _tcscpy wcscpy
+#define _tfopen _wfopen
+#endif
+
 #endif // GCENV_H_
index 20fb179..e54c371 100644 (file)
@@ -484,19 +484,6 @@ bool GCToOSInterface::CreateThread(GCThreadFunction function, void* param, GCThr
     return true;
 }
 
-// Open a file
-// Parameters:
-//  filename - name of the file to open
-//  mode     - mode to open the file in (like in the CRT fopen)
-// Return:
-//  FILE* of the opened file
-FILE* GCToOSInterface::OpenFile(const WCHAR* filename, const WCHAR* mode)
-{
-    LIMITED_METHOD_CONTRACT;
-
-    return _wfopen(filename, mode);
-}
-
 // Initialize the critical section
 void CLRCriticalSection::Initialize()
 {
index 345cda5..f7a5fb4 100644 (file)
@@ -694,7 +694,7 @@ __declspec (naked) void BackPatchWorkerAsmStub()
 //
 BOOL isDelegateCall(BYTE *interiorPtr)
 {
-    WRAPPER_NO_CONTRACT; 
+    LIMITED_METHOD_CONTRACT;
 
     if (GCHeap::GetGCHeap()->IsHeapPointer((void*)interiorPtr))
     {
index 719332a..f012c3c 100644 (file)
@@ -1526,11 +1526,11 @@ AppDomain* STDCALL GetAppDomainGeneric()
 // FLS getter to avoid unnecessary indirection via execution engine. It will be used if we get high TLS slot
 // from the OS where we cannot use the fast optimized assembly helpers. (It happens pretty often in hosted scenarios).
 //
-VOID * ClrFlsGetBlockDirect()
+LPVOID* ClrFlsGetBlockDirect()
 {
     LIMITED_METHOD_CONTRACT;
 
-    return UnsafeTlsGetValue(CExecutionEngine::GetTlsIndex());
+    return (LPVOID*)UnsafeTlsGetValue(CExecutionEngine::GetTlsIndex());
 }
 
 extern "C" void * ClrFlsGetBlock();
@@ -1660,10 +1660,10 @@ void InitThreadManager()
     CExecutionEngine::CheckThreadState(0, FALSE);
 
     DWORD masterSlotIndex = CExecutionEngine::GetTlsIndex();
-    POPTIMIZEDTLSGETTER pGetter = MakeOptimizedTlsGetter(masterSlotIndex, (PVOID)ClrFlsGetBlock, TLS_GETTER_MAX_SIZE);
+    CLRFLSGETBLOCK pGetter = (CLRFLSGETBLOCK)MakeOptimizedTlsGetter(masterSlotIndex, (PVOID)ClrFlsGetBlock, TLS_GETTER_MAX_SIZE);
     __ClrFlsGetBlock = pGetter ? pGetter : ClrFlsGetBlockDirect;
 #else
-    __ClrFlsGetBlock = (POPTIMIZEDTLSGETTER) CExecutionEngine::GetTlsData;
+    __ClrFlsGetBlock = CExecutionEngine::GetTlsData;
 #endif // FEATURE_IMPLICIT_TLS
 
     IfFailThrow(Thread::CLRSetThreadStackGuarantee(Thread::STSGuarantee_Force));
index e3f506b..67c8d10 100644 (file)
@@ -333,7 +333,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread19
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [struct01.exe_3246]
 RelativePath=JIT\Generics\Instantiation\Interfaces\struct01\struct01.exe
 WorkingDir=JIT\Generics\Instantiation\Interfaces\struct01
@@ -473,7 +473,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread02
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [converttobyte6.exe_729]
 RelativePath=CoreMangLib\cti\system\convert\ConvertToByte6\ConvertToByte6.exe
 WorkingDir=CoreMangLib\cti\system\convert\ConvertToByte6
@@ -872,7 +872,7 @@ WorkingDir=JIT\Methodical\divrem\div\r8div_cs_do
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_PASS
+Categories=JIT;EXPECTED_PASS;ISSUE_2849;DBG_FAIL
 [_il_relgcval_sideeffect.exe_4581]
 RelativePath=JIT\Methodical\tailcall\_il_relgcval_sideeffect\_il_relgcval_sideeffect.exe
 WorkingDir=JIT\Methodical\tailcall\_il_relgcval_sideeffect
@@ -1194,7 +1194,7 @@ WorkingDir=JIT\Directed\intrinsic\interlocked\IntrinsicTest_Overflow
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_PASS;ISSUE_2823
 [equalitycomparerequals.exe_585]
 RelativePath=CoreMangLib\cti\system\collections\generic\equalitycomparer\EqualityComparerEquals\EqualityComparerEquals.exe
 WorkingDir=CoreMangLib\cti\system\collections\generic\equalitycomparer\EqualityComparerEquals
@@ -1404,7 +1404,7 @@ WorkingDir=JIT\Directed\coverage\oldtests\lclfldadd_cs_do
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_PASS
+Categories=JIT;EXPECTED_PASS;ISSUE_2849;DBG_FAIL
 [25param3b_il_d.exe_4201]
 RelativePath=JIT\Methodical\Invoke\25params\25param3b_il_d\25param3b_il_d.exe
 WorkingDir=JIT\Methodical\Invoke\25params\25param3b_il_d
@@ -1628,7 +1628,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread25
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [overflowexceptionctor3.exe_1593]
 RelativePath=CoreMangLib\cti\system\overflowexception\OverflowExceptionCtor3\OverflowExceptionCtor3.exe
 WorkingDir=CoreMangLib\cti\system\overflowexception\OverflowExceptionCtor3
@@ -1936,7 +1936,7 @@ WorkingDir=JIT\opt\ETW\TailCallCases
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;REL_PASS
 [nested-try-catch02.exe_14]
 RelativePath=baseservices\exceptions\generics\nested-try-catch02\nested-try-catch02.exe
 WorkingDir=baseservices\exceptions\generics\nested-try-catch02
@@ -2118,7 +2118,7 @@ WorkingDir=CoreMangLib\cti\system\threading\interlocked\InterlockedIncrement1
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [int32parse3.exe_1313]
 RelativePath=CoreMangLib\cti\system\int\Int32Parse3\Int32Parse3.exe
 WorkingDir=CoreMangLib\cti\system\int\Int32Parse3
@@ -2244,7 +2244,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread04
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [mathieeeremainder.exe_1489]
 RelativePath=CoreMangLib\cti\system\math\MathIEEERemainder\MathIEEERemainder.exe
 WorkingDir=CoreMangLib\cti\system\math\MathIEEERemainder
@@ -2923,7 +2923,7 @@ WorkingDir=baseservices\threading\readerwriterlockslim\SingleReleaseWriteDDBug71
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [fpmath.exe_2661]
 RelativePath=JIT\CodeGenBringUpTests\FPMath\FPMath.exe
 WorkingDir=JIT\CodeGenBringUpTests\FPMath
@@ -3308,7 +3308,7 @@ WorkingDir=JIT\Regression\CLR-x86-JIT\V1-M11-Beta1\b40721\b40721
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;REL_PASS
 [stringlength.exe_2227]
 RelativePath=CoreMangLib\cti\system\string\StringLength\StringLength.exe
 WorkingDir=CoreMangLib\cti\system\string\StringLength
@@ -4148,7 +4148,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread17
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [rethrow.exe_3103]
 RelativePath=JIT\Directed\throwbox\rethrow\rethrow.exe
 WorkingDir=JIT\Directed\throwbox\rethrow
@@ -4575,7 +4575,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread28
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [b518440.exe_3794]
 RelativePath=JIT\Methodical\Coverage\b518440\b518440.exe
 WorkingDir=JIT\Methodical\Coverage\b518440
@@ -4925,7 +4925,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread08
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [b85566.exe_5672]
 RelativePath=JIT\Regression\VS-ia64-JIT\M00\b85566\b85566\b85566.exe
 WorkingDir=JIT\Regression\VS-ia64-JIT\M00\b85566\b85566
@@ -4939,7 +4939,7 @@ WorkingDir=JIT\Directed\coverage\oldtests\33objref_cs_do
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;REL_PASS
 [uint16equals1.exe_2456]
 RelativePath=CoreMangLib\cti\system\uint16\UInt16Equals1\UInt16Equals1.exe
 WorkingDir=CoreMangLib\cti\system\uint16\UInt16Equals1
@@ -5142,7 +5142,7 @@ WorkingDir=GC\Coverage\LargeObjectAlloc
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_FAIL;REL_PASS
 [textelementenumeratorgettextelement.exe_1218]
 RelativePath=CoreMangLib\cti\system\globalization\textelementenumerator\TextElementEnumeratorGetTextElement\TextElementEnumeratorGetTextElement.exe
 WorkingDir=CoreMangLib\cti\system\globalization\textelementenumerator\TextElementEnumeratorGetTextElement
@@ -5254,7 +5254,7 @@ WorkingDir=JIT\Directed\coverage\oldtests\lclfldrem_cs_ro
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;ISSUE_2849;REL_PASS
 [converttouint168.exe_889]
 RelativePath=CoreMangLib\cti\system\convert\ConvertToUInt168\ConvertToUInt168.exe
 WorkingDir=CoreMangLib\cti\system\convert\ConvertToUInt168
@@ -5541,7 +5541,7 @@ WorkingDir=Interop\NativeCallable\NativeCallableTest
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_FAIL;REL_PASS
 [invalidoperationexceptionctor1.exe_1387]
 RelativePath=CoreMangLib\cti\system\invalidoperationexception\InvalidOperationExceptionctor1\InvalidOperationExceptionctor1.exe
 WorkingDir=CoreMangLib\cti\system\invalidoperationexception\InvalidOperationExceptionctor1
@@ -6199,7 +6199,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread12
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [b10828.exe_5703]
 RelativePath=JIT\Regression\VS-ia64-JIT\V1.2-M02\b10828\b10828\b10828.exe
 WorkingDir=JIT\Regression\VS-ia64-JIT\V1.2-M02\b10828\b10828
@@ -6318,7 +6318,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread30
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [ldc_c_nop.exe_3327]
 RelativePath=JIT\IL_Conformance\Old\Conformance_Base\ldc_c_nop\ldc_c_nop.exe
 WorkingDir=JIT\IL_Conformance\Old\Conformance_Base\ldc_c_nop
@@ -6423,7 +6423,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread02
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [stringbuilderappend14.exe_2298]
 RelativePath=CoreMangLib\cti\system\text\stringbuilder\StringBuilderAppend14\StringBuilderAppend14.exe
 WorkingDir=CoreMangLib\cti\system\text\stringbuilder\StringBuilderAppend14
@@ -6514,7 +6514,7 @@ WorkingDir=JIT\Directed\coverage\oldtests\lclfldmul_cs_ro
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_PASS
+Categories=JIT;EXPECTED_PASS;ISSUE_2849;DBG_FAIL
 [unicodeencodinggetpreamble.exe_2345]
 RelativePath=CoreMangLib\cti\system\text\unicodeencoding\UnicodeEncodingGetPreamble\UnicodeEncodingGetPreamble.exe
 WorkingDir=CoreMangLib\cti\system\text\unicodeencoding\UnicodeEncodingGetPreamble
@@ -6948,7 +6948,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread06
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [float_no_op_cs_r.exe_2794]
 RelativePath=JIT\Directed\cmov\Float_No_Op_cs_r\Float_No_Op_cs_r.exe
 WorkingDir=JIT\Directed\cmov\Float_No_Op_cs_r
@@ -7494,7 +7494,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread01
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [notrmw.exe_2714]
 RelativePath=JIT\CodeGenBringUpTests\NotRMW\NotRMW.exe
 WorkingDir=JIT\CodeGenBringUpTests\NotRMW
@@ -7571,7 +7571,7 @@ WorkingDir=JIT\Methodical\int64\arrays\_speed_rellcs_long
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_PASS
+Categories=JIT;UNSTABLE
 [_speed_rellcs.exe_3607]
 RelativePath=JIT\Methodical\Arrays\lcs\_speed_rellcs\_speed_rellcs.exe
 WorkingDir=JIT\Methodical\Arrays\lcs\_speed_rellcs
@@ -8460,7 +8460,7 @@ WorkingDir=JIT\Directed\intrinsic\interlocked\nullchecksuppress
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_PASS;ISSUE_2823
 [b28805.exe_4947]
 RelativePath=JIT\Regression\CLR-x86-JIT\V1-M09.5-PDC\b28805\b28805\b28805.exe
 WorkingDir=JIT\Regression\CLR-x86-JIT\V1-M09.5-PDC\b28805\b28805
@@ -8614,7 +8614,7 @@ WorkingDir=JIT\Methodical\divrem\rem\r8rem_cs_do
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;ISSUE_2849;REL_PASS
 [structlayoutattributevalue.exe_2118]
 RelativePath=CoreMangLib\cti\system\runtime\interopservices\structlayoutattribute\StructLayoutAttributeValue\StructLayoutAttributeValue.exe
 WorkingDir=CoreMangLib\cti\system\runtime\interopservices\structlayoutattribute\StructLayoutAttributeValue
@@ -9069,7 +9069,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread04
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [_dbgcastclass_ldloc.exe_3693]
 RelativePath=JIT\Methodical\casts\coverage\_dbgcastclass_ldloc\_dbgcastclass_ldloc.exe
 WorkingDir=JIT\Methodical\casts\coverage\_dbgcastclass_ldloc
@@ -9335,7 +9335,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread29
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [unicodecategorylowercaseletter.exe_1239]
 RelativePath=CoreMangLib\cti\system\globalization\unicodecategory\UnicodeCategoryLowercaseLetter\UnicodeCategoryLowercaseLetter.exe
 WorkingDir=CoreMangLib\cti\system\globalization\unicodecategory\UnicodeCategoryLowercaseLetter
@@ -9440,7 +9440,7 @@ WorkingDir=JIT\Methodical\VT\port\_rellcs_gcref
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;REL_PASS
 [arrayindexof2.exe_304]
 RelativePath=CoreMangLib\cti\system\array\ArrayIndexOf2\ArrayIndexOf2.exe
 WorkingDir=CoreMangLib\cti\system\array\ArrayIndexOf2
@@ -11204,7 +11204,7 @@ WorkingDir=JIT\Methodical\divrem\div\r4div_cs_do
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_PASS
+Categories=JIT;EXPECTED_PASS;ISSUE_2849;DBG_FAIL
 [b48990b.exe_5169]
 RelativePath=JIT\Regression\CLR-x86-JIT\V1-M11-Beta1\b48990\b48990b\b48990b.exe
 WorkingDir=JIT\Regression\CLR-x86-JIT\V1-M11-Beta1\b48990\b48990b
@@ -11575,7 +11575,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread22
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [attributetargetsenum.exe_355]
 RelativePath=CoreMangLib\cti\system\attributetargets\AttributeTargetsEnum\AttributeTargetsEnum.exe
 WorkingDir=CoreMangLib\cti\system\attributetargets\AttributeTargetsEnum
@@ -11645,7 +11645,7 @@ WorkingDir=JIT\Methodical\divrem\div\r4div_cs_ro
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_PASS
+Categories=JIT;EXPECTED_PASS;ISSUE_2849;DBG_FAIL
 [box_unbox.exe_2996]
 RelativePath=JIT\Directed\PREFIX\unaligned\4\Box_Unbox\Box_Unbox.exe
 WorkingDir=JIT\Directed\PREFIX\unaligned\4\Box_Unbox
@@ -11701,7 +11701,7 @@ WorkingDir=JIT\Regression\CLR-x86-JIT\V1-M12-Beta2\b57493\b57493
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;REL_PASS
 [converttosbyte.exe_821]
 RelativePath=CoreMangLib\cti\system\convert\ConvertToSByte\ConvertToSByte.exe
 WorkingDir=CoreMangLib\cti\system\convert\ConvertToSByte
@@ -12296,7 +12296,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread21
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [int32iconvertibletobyte.exe_1295]
 RelativePath=CoreMangLib\cti\system\int\Int32IConvertibleToByte\Int32IConvertibleToByte.exe
 WorkingDir=CoreMangLib\cti\system\int\Int32IConvertibleToByte
@@ -13171,7 +13171,7 @@ WorkingDir=GC\Coverage\LargeObjectAlloc2
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_FAIL;REL_PASS
 [typeattributesansiclass.exe_2021]
 RelativePath=CoreMangLib\cti\system\reflection\typeattributes\TypeAttributesAnsiClass\TypeAttributesAnsiClass.exe
 WorkingDir=CoreMangLib\cti\system\reflection\typeattributes\TypeAttributesAnsiClass
@@ -13423,7 +13423,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread12
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [pathgetextension.exe_1449]
 RelativePath=CoreMangLib\cti\system\io\path\PathGetExtension\PathGetExtension.exe
 WorkingDir=CoreMangLib\cti\system\io\path\PathGetExtension
@@ -13528,7 +13528,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread06
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [ldc_sub_ovf_i4.exe_3349]
 RelativePath=JIT\IL_Conformance\Old\Conformance_Base\ldc_sub_ovf_i4\ldc_sub_ovf_i4.exe
 WorkingDir=JIT\IL_Conformance\Old\Conformance_Base\ldc_sub_ovf_i4
@@ -14543,7 +14543,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread15
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [uint_cs_d.exe_4384]
 RelativePath=JIT\Methodical\MDArray\DataTypes\uint_cs_d\uint_cs_d.exe
 WorkingDir=JIT\Methodical\MDArray\DataTypes\uint_cs_d
@@ -15243,7 +15243,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread27
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [cse1_cs_do.exe_2851]
 RelativePath=JIT\Directed\coverage\oldtests\cse1_cs_do\cse1_cs_do.exe
 WorkingDir=JIT\Directed\coverage\oldtests\cse1_cs_do
@@ -15348,7 +15348,7 @@ WorkingDir=JIT\Regression\CLR-x86-JIT\V1-M12-Beta2\b59782\b59782
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;REL_PASS
 [_dbgiface1.exe_3741]
 RelativePath=JIT\Methodical\casts\iface\_dbgiface1\_dbgiface1.exe
 WorkingDir=JIT\Methodical\casts\iface\_dbgiface1
@@ -15425,7 +15425,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread18
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [threadstatic02.exe_247]
 RelativePath=baseservices\threading\threadstatic\ThreadStatic02\ThreadStatic02.exe
 WorkingDir=baseservices\threading\threadstatic\ThreadStatic02
@@ -16251,7 +16251,7 @@ WorkingDir=JIT\Regression\CLR-x86-JIT\V1-M12-Beta2\b50027\b50027
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;REL_PASS
 [stringcompare5.exe_2184]
 RelativePath=CoreMangLib\cti\system\string\StringCompare5\StringCompare5.exe
 WorkingDir=CoreMangLib\cti\system\string\StringCompare5
@@ -16972,7 +16972,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread09
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [_dbgexplicit7.exe_3973]
 RelativePath=JIT\Methodical\explicit\misc\_dbgexplicit7\_dbgexplicit7.exe
 WorkingDir=JIT\Methodical\explicit\misc\_dbgexplicit7
@@ -17210,7 +17210,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread24
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;DBG_FAIL
 [class04.exe_3129]
 RelativePath=JIT\Generics\Arrays\ConstructedTypes\Jagged\class04\class04.exe
 WorkingDir=JIT\Generics\Arrays\ConstructedTypes\Jagged\class04
@@ -17434,7 +17434,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread16
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [stringwriterencoding_psc.exe_1470]
 RelativePath=CoreMangLib\cti\system\io\stringwriter\StringWriterEncoding_PSC\StringWriterEncoding_PSC.exe
 WorkingDir=CoreMangLib\cti\system\io\stringwriter\StringWriterEncoding_PSC
@@ -18701,7 +18701,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread24
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [converttodecimal18.exe_756]
 RelativePath=CoreMangLib\cti\system\convert\ConvertToDecimal18\ConvertToDecimal18.exe
 WorkingDir=CoreMangLib\cti\system\convert\ConvertToDecimal18
@@ -19807,7 +19807,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread25
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [stackctor3.exe_680]
 RelativePath=CoreMangLib\cti\system\collections\generic\stack\StackCtor3\StackCtor3.exe
 WorkingDir=CoreMangLib\cti\system\collections\generic\stack\StackCtor3
@@ -19891,7 +19891,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread19
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [opcodesbgt_un.exe_1672]
 RelativePath=CoreMangLib\cti\system\reflection\emit\opcodes\OpCodesBgt_Un\OpCodesBgt_Un.exe
 WorkingDir=CoreMangLib\cti\system\reflection\emit\opcodes\OpCodesBgt_Un
@@ -20199,7 +20199,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread11
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [opcodesxor.exe_1888]
 RelativePath=CoreMangLib\cti\system\reflection\emit\opcodes\OpCodesXor\OpCodesXor.exe
 WorkingDir=CoreMangLib\cti\system\reflection\emit\opcodes\OpCodesXor
@@ -20409,7 +20409,7 @@ WorkingDir=JIT\Methodical\VT\port\_dbglcs_gcref
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;REL_PASS
 [_speed_dbglcs_ulong.exe_4062]
 RelativePath=JIT\Methodical\int64\arrays\_speed_dbglcs_ulong\_speed_dbglcs_ulong.exe
 WorkingDir=JIT\Methodical\int64\arrays\_speed_dbglcs_ulong
@@ -21011,7 +21011,7 @@ WorkingDir=GC\Regressions\v2.0-beta1\289745\302560
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_FAIL;REL_PASS
 [b158861.exe_5575]
 RelativePath=JIT\Regression\CLR-x86-JIT\v2.1\DDB\b158861\b158861\b158861.exe
 WorkingDir=JIT\Regression\CLR-x86-JIT\v2.1\DDB\b158861\b158861
@@ -21326,7 +21326,7 @@ WorkingDir=JIT\Regression\CLR-x86-JIT\V1-M12-Beta2\b51420\b51420
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;REL_PASS
 [b29343.exe_5723]
 RelativePath=JIT\Regression\VS-ia64-JIT\V1.2-M02\b29343\b29343\b29343.exe
 WorkingDir=JIT\Regression\VS-ia64-JIT\V1.2-M02\b29343\b29343
@@ -21522,14 +21522,14 @@ WorkingDir=CoreMangLib\cti\system\datetime\DateTimeParseExact2
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;UNSTABLE
 [lclflddiv_cs_ro.exe_2867]
 RelativePath=JIT\Directed\coverage\oldtests\lclflddiv_cs_ro\lclflddiv_cs_ro.exe
 WorkingDir=JIT\Directed\coverage\oldtests\lclflddiv_cs_ro
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_PASS
+Categories=JIT;EXPECTED_PASS;ISSUE_2849;DBG_FAIL
 [opcodesldarga.exe_1749]
 RelativePath=CoreMangLib\cti\system\reflection\emit\opcodes\OpCodesLdarga\OpCodesLdarga.exe
 WorkingDir=CoreMangLib\cti\system\reflection\emit\opcodes\OpCodesLdarga
@@ -21935,7 +21935,7 @@ WorkingDir=JIT\Methodical\int64\arrays\_rellcs_ulong
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;REL_PASS
 [listienumerablegetenumerator2.exe_637]
 RelativePath=CoreMangLib\cti\system\collections\generic\list\ListIEnumerableGetEnumerator2\ListIEnumerableGetEnumerator2.exe
 WorkingDir=CoreMangLib\cti\system\collections\generic\list\ListIEnumerableGetEnumerator2
@@ -22544,7 +22544,7 @@ WorkingDir=JIT\Methodical\divrem\div\r8div_cs_ro
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_PASS
+Categories=JIT;EXPECTED_PASS;ISSUE_2849;DBG_FAIL
 [_il_relrefarg_f4.exe_3943]
 RelativePath=JIT\Methodical\explicit\basic\_il_relrefarg_f4\_il_relrefarg_f4.exe
 WorkingDir=JIT\Methodical\explicit\basic\_il_relrefarg_f4
@@ -23454,7 +23454,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread03
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [doubleisinfinity.exe_1061]
 RelativePath=CoreMangLib\cti\system\double\DoubleIsInfinity\DoubleIsInfinity.exe
 WorkingDir=CoreMangLib\cti\system\double\DoubleIsInfinity
@@ -23580,14 +23580,14 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread01
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [lclfldsub_cs_ro.exe_2879]
 RelativePath=JIT\Directed\coverage\oldtests\lclfldsub_cs_ro\lclfldsub_cs_ro.exe
 WorkingDir=JIT\Directed\coverage\oldtests\lclfldsub_cs_ro
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_PASS
+Categories=JIT;EXPECTED_PASS;ISSUE_2849;DBG_FAIL
 [_il_dbgstress2.exe_4532]
 RelativePath=JIT\Methodical\refany\_il_dbgstress2\_il_dbgstress2.exe
 WorkingDir=JIT\Methodical\refany\_il_dbgstress2
@@ -23713,7 +23713,7 @@ WorkingDir=JIT\Regression\CLR-x86-JIT\V1-M11-Beta1\b41621\b41621
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;REL_PASS
 [b30892.exe_4962]
 RelativePath=JIT\Regression\CLR-x86-JIT\V1-M09.5-PDC\b30892\b30892\b30892.exe
 WorkingDir=JIT\Regression\CLR-x86-JIT\V1-M09.5-PDC\b30892\b30892
@@ -23979,7 +23979,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread11
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [sbyteminvalue.exe_2142]
 RelativePath=CoreMangLib\cti\system\sbyte\SByteMinValue\SByteMinValue.exe
 WorkingDir=CoreMangLib\cti\system\sbyte\SByteMinValue
@@ -24035,7 +24035,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread07
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [_speed_reliface1.exe_3746]
 RelativePath=JIT\Methodical\casts\iface\_speed_reliface1\_speed_reliface1.exe
 WorkingDir=JIT\Methodical\casts\iface\_speed_reliface1
@@ -24315,7 +24315,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread08
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [_il_reltest_switch.exe_4589]
 RelativePath=JIT\Methodical\tailcall\_il_reltest_switch\_il_reltest_switch.exe
 WorkingDir=JIT\Methodical\tailcall\_il_reltest_switch
@@ -24427,7 +24427,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread13
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [_il_reliu2.exe_4281]
 RelativePath=JIT\Methodical\Invoke\implicit\_il_reliu2\_il_reliu2.exe
 WorkingDir=JIT\Methodical\Invoke\implicit\_il_reliu2
@@ -24693,7 +24693,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread30
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [genericexceptions08.exe_12]
 RelativePath=baseservices\exceptions\generics\GenericExceptions08\GenericExceptions08.exe
 WorkingDir=baseservices\exceptions\generics\GenericExceptions08
@@ -24777,7 +24777,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread10
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [threadstartulong_3.exe_237]
 RelativePath=baseservices\threading\paramthreadstart\ThreadStartULong_3\ThreadStartULong_3.exe
 WorkingDir=baseservices\threading\paramthreadstart\ThreadStartULong_3
@@ -24868,14 +24868,14 @@ WorkingDir=GC\Regressions\v2.0-beta1\289745\289745
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_FAIL;REL_PASS
 [upgrader.exe_243]
 RelativePath=baseservices\threading\readerwriterlockslim\Upgrader\Upgrader.exe
 WorkingDir=baseservices\threading\readerwriterlockslim\Upgrader
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [ldc_c_cpblk.exe_3325]
 RelativePath=JIT\IL_Conformance\Old\Conformance_Base\ldc_c_cpblk\ldc_c_cpblk.exe
 WorkingDir=JIT\IL_Conformance\Old\Conformance_Base\ldc_c_cpblk
@@ -24889,7 +24889,7 @@ WorkingDir=JIT\Directed\coverage\oldtests\lclfldsub_cs_do
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_PASS
+Categories=JIT;EXPECTED_PASS;ISSUE_2849;DBG_FAIL
 [idictionaryisfixedsize.exe_698]
 RelativePath=CoreMangLib\cti\system\collections\idictionary\IDictionaryIsFixedSize\IDictionaryIsFixedSize.exe
 WorkingDir=CoreMangLib\cti\system\collections\idictionary\IDictionaryIsFixedSize
@@ -26114,7 +26114,7 @@ WorkingDir=JIT\jit64\opt\rngchk\RngchkStress2_o
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;REL_PASS
 [b64026.exe_5343]
 RelativePath=JIT\Regression\CLR-x86-JIT\V1-M12-Beta2\b64026\b64026\b64026.exe
 WorkingDir=JIT\Regression\CLR-x86-JIT\V1-M12-Beta2\b64026\b64026
@@ -26184,7 +26184,7 @@ WorkingDir=JIT\Directed\coverage\oldtests\lclflddiv_cs_do
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_PASS
+Categories=JIT;EXPECTED_PASS;ISSUE_2849;DBG_FAIL
 [stackclear.exe_674]
 RelativePath=CoreMangLib\cti\system\collections\generic\stack\StackClear\StackClear.exe
 WorkingDir=CoreMangLib\cti\system\collections\generic\stack\StackClear
@@ -26352,7 +26352,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread29
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [converttouint3213.exe_896]
 RelativePath=CoreMangLib\cti\system\convert\ConvertToUInt3213\ConvertToUInt3213.exe
 WorkingDir=CoreMangLib\cti\system\convert\ConvertToUInt3213
@@ -26541,7 +26541,7 @@ WorkingDir=JIT\Directed\coverage\oldtests\lclfldmul_cs_do
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_PASS
+Categories=JIT;EXPECTED_PASS;ISSUE_2849;DBG_FAIL
 [listindexof1.exe_646]
 RelativePath=CoreMangLib\cti\system\collections\generic\list\ListIndexOf1\ListIndexOf1.exe
 WorkingDir=CoreMangLib\cti\system\collections\generic\list\ListIndexOf1
@@ -26828,7 +26828,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread17
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [b434481_genericrecurinit.exe_5796]
 RelativePath=Loader\classloader\regressions\434481\b434481_GenericRecurInit\b434481_GenericRecurInit.exe
 WorkingDir=Loader\classloader\regressions\434481\b434481_GenericRecurInit
@@ -27087,7 +27087,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread13
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [listforeach.exe_629]
 RelativePath=CoreMangLib\cti\system\collections\generic\list\ListForEach\ListForEach.exe
 WorkingDir=CoreMangLib\cti\system\collections\generic\list\ListForEach
@@ -27325,7 +27325,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread28
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [instrcnt1.exe_4771]
 RelativePath=JIT\opt\JitMinOpts\Perf\InstrCnt1\InstrCnt1.exe
 WorkingDir=JIT\opt\JitMinOpts\Perf\InstrCnt1
@@ -27682,7 +27682,7 @@ WorkingDir=CoreMangLib\cti\system\threading\interlocked\InterlockedDecrement1
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [jtruelefp.exe_2691]
 RelativePath=JIT\CodeGenBringUpTests\JTrueLeFP\JTrueLeFP.exe
 WorkingDir=JIT\CodeGenBringUpTests\JTrueLeFP
@@ -28480,7 +28480,7 @@ WorkingDir=JIT\Directed\FaultHandlers\Nesting\Nesting
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;REL_PASS
 [float_no_op_cs_d.exe_2792]
 RelativePath=JIT\Directed\cmov\Float_No_Op_cs_d\Float_No_Op_cs_d.exe
 WorkingDir=JIT\Directed\cmov\Float_No_Op_cs_d
@@ -29173,7 +29173,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread05
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [listremoveat.exe_653]
 RelativePath=CoreMangLib\cti\system\collections\generic\list\ListRemoveAt\ListRemoveAt.exe
 WorkingDir=CoreMangLib\cti\system\collections\generic\list\ListRemoveAt
@@ -29705,7 +29705,7 @@ WorkingDir=CoreMangLib\cti\system\threading\interlocked\InterlockedAdd1
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [converttoint64_3.exe_814]
 RelativePath=CoreMangLib\cti\system\convert\ConvertToInt64_3\ConvertToInt64_3.exe
 WorkingDir=CoreMangLib\cti\system\convert\ConvertToInt64_3
@@ -29831,7 +29831,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread07
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [disabletransparencyenforcement.exe_5819]
 RelativePath=Regressions\common\DisableTransparencyEnforcement\DisableTransparencyEnforcement.exe
 WorkingDir=Regressions\common\DisableTransparencyEnforcement
@@ -30272,7 +30272,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread22
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823;DBG_FAIL
 [converttouint648.exe_927]
 RelativePath=CoreMangLib\cti\system\convert\ConvertToUInt648\ConvertToUInt648.exe
 WorkingDir=CoreMangLib\cti\system\convert\ConvertToUInt648
@@ -30566,7 +30566,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread18
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [opcodesadd_ovf.exe_1660]
 RelativePath=CoreMangLib\cti\system\reflection\emit\opcodes\OpCodesAdd_Ovf\OpCodesAdd_Ovf.exe
 WorkingDir=CoreMangLib\cti\system\reflection\emit\opcodes\OpCodesAdd_Ovf
@@ -31371,7 +31371,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread20
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [general_struct_instance01.exe_3211]
 RelativePath=JIT\Generics\Exceptions\general_struct_instance01\general_struct_instance01.exe
 WorkingDir=JIT\Generics\Exceptions\general_struct_instance01
@@ -31434,7 +31434,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread09
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [interlockedaddint_3.exe_152]
 RelativePath=baseservices\threading\interlocked\add\InterlockedAddInt_3\InterlockedAddInt_3.exe
 WorkingDir=baseservices\threading\interlocked\add\InterlockedAddInt_3
@@ -31728,7 +31728,7 @@ WorkingDir=JIT\Directed\coverage\oldtests\lclfldadd_cs_ro
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_PASS
+Categories=JIT;EXPECTED_PASS;ISSUE_2849;DBG_FAIL
 [opcodescall.exe_1692]
 RelativePath=CoreMangLib\cti\system\reflection\emit\opcodes\OpCodesCall\OpCodesCall.exe
 WorkingDir=CoreMangLib\cti\system\reflection\emit\opcodes\OpCodesCall
@@ -33058,7 +33058,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread20
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [double_cs_d.exe_4360]
 RelativePath=JIT\Methodical\MDArray\DataTypes\double_cs_d\double_cs_d.exe
 WorkingDir=JIT\Methodical\MDArray\DataTypes\double_cs_d
@@ -33394,14 +33394,14 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread14
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [gthread14.exe_129]
 RelativePath=baseservices\threading\generics\threadstart\GThread14\GThread14.exe
 WorkingDir=baseservices\threading\generics\threadstart\GThread14
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [converttostring16.exe_847]
 RelativePath=CoreMangLib\cti\system\convert\ConvertToString16\ConvertToString16.exe
 WorkingDir=CoreMangLib\cti\system\convert\ConvertToString16
@@ -34815,7 +34815,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread15
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [idictionaryisreadonly.exe_699]
 RelativePath=CoreMangLib\cti\system\collections\idictionary\IDictionaryIsReadOnly\IDictionaryIsReadOnly.exe
 WorkingDir=CoreMangLib\cti\system\collections\idictionary\IDictionaryIsReadOnly
@@ -34927,7 +34927,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread03
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [uint32iconvertibletouint64.exe_2498]
 RelativePath=CoreMangLib\cti\system\uint32\UInt32IConvertibleToUInt64\UInt32IConvertibleToUInt64.exe
 WorkingDir=CoreMangLib\cti\system\uint32\UInt32IConvertibleToUInt64
@@ -35431,7 +35431,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread10
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [_il_dbgldsfld_mulovf.exe_4151]
 RelativePath=JIT\Methodical\int64\unsigned\_il_dbgldsfld_mulovf\_il_dbgldsfld_mulovf.exe
 WorkingDir=JIT\Methodical\int64\unsigned\_il_dbgldsfld_mulovf
@@ -35676,7 +35676,7 @@ WorkingDir=CoreMangLib\cti\system\console\ConsoleSetOut_PSC
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [converttostring21.exe_853]
 RelativePath=CoreMangLib\cti\system\convert\ConvertToString21\ConvertToString21.exe
 WorkingDir=CoreMangLib\cti\system\convert\ConvertToString21
@@ -35851,7 +35851,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread26
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [methodimplattributesmanagedmask.exe_1997]
 RelativePath=CoreMangLib\cti\system\reflection\methodimplattributes\MethodImplAttributesManagedMask\MethodImplAttributesManagedMask.exe
 WorkingDir=CoreMangLib\cti\system\reflection\methodimplattributes\MethodImplAttributesManagedMask
@@ -37020,7 +37020,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread05
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [typeloadexceptionctor2.exe_2452]
 RelativePath=CoreMangLib\cti\system\typeloadexception\TypeLoadExceptionCtor2\TypeLoadExceptionCtor2.exe
 WorkingDir=CoreMangLib\cti\system\typeloadexception\TypeLoadExceptionCtor2
@@ -37083,7 +37083,7 @@ WorkingDir=JIT\Methodical\divrem\rem\r8rem_cs_ro
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL;REL_PASS
+Categories=JIT;EXPECTED_FAIL;REL_PASS;ISSUE_2849
 [_dbglcs_ulong.exe_4052]
 RelativePath=JIT\Methodical\int64\arrays\_dbglcs_ulong\_dbglcs_ulong.exe
 WorkingDir=JIT\Methodical\int64\arrays\_dbglcs_ulong
@@ -37678,7 +37678,7 @@ WorkingDir=JIT\Directed\coverage\oldtests\lclfldrem_cs_do
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_FAIL;ISSUE_2849;REL_PASS
 [datetimeformatinfogetabbreviateddayname.exe_1151]
 RelativePath=CoreMangLib\cti\system\globalization\datetimeformatinfo\DateTimeFormatInfoGetAbbreviatedDayName\DateTimeFormatInfoGetAbbreviatedDayName.exe
 WorkingDir=CoreMangLib\cti\system\globalization\datetimeformatinfo\DateTimeFormatInfoGetAbbreviatedDayName
@@ -38119,7 +38119,7 @@ WorkingDir=CoreMangLib\cti\system\console\consoleseterror_PSC
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [opcodesblt_s.exe_1679]
 RelativePath=CoreMangLib\cti\system\reflection\emit\opcodes\OpCodesBlt_S\OpCodesBlt_S.exe
 WorkingDir=CoreMangLib\cti\system\reflection\emit\opcodes\OpCodesBlt_S
@@ -38322,7 +38322,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread27
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [_dbgknight.exe_4645]
 RelativePath=JIT\Methodical\VT\etc\_dbgknight\_dbgknight.exe
 WorkingDir=JIT\Methodical\VT\etc\_dbgknight
@@ -38798,7 +38798,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread23
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823;DBG_FAIL
 [vsw405223.exe_5795]
 RelativePath=Loader\classloader\regressions\405223\vsw405223\vsw405223.exe
 WorkingDir=Loader\classloader\regressions\405223\vsw405223
@@ -38910,7 +38910,7 @@ WorkingDir=CoreMangLib\cti\system\array\ArrayGetValue2
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_PASS;REL_FAIL
+Categories=RT;UNSTABLE
 [_il_dbgjumper4.exe_4610]
 RelativePath=JIT\Methodical\VT\callconv\_il_dbgjumper4\_il_dbgjumper4.exe
 WorkingDir=JIT\Methodical\VT\callconv\_il_dbgjumper4
@@ -38945,7 +38945,7 @@ WorkingDir=JIT\Directed\intrinsic\interlocked\cse_cmpxchg
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=JIT;EXPECTED_FAIL
+Categories=JIT;EXPECTED_PASS;ISSUE_2823
 [uint64iconvertibletouint32.exe_2523]
 RelativePath=CoreMangLib\cti\system\uint64\UInt64IConvertibleToUInt32\UInt64IConvertibleToUInt32.exe
 WorkingDir=CoreMangLib\cti\system\uint64\UInt64IConvertibleToUInt32
@@ -38994,7 +38994,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread26
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [bool_or_op_cs_r.exe_2766]
 RelativePath=JIT\Directed\cmov\Bool_Or_Op_cs_r\Bool_Or_Op_cs_r.exe
 WorkingDir=JIT\Directed\cmov\Bool_Or_Op_cs_r
@@ -39078,7 +39078,7 @@ WorkingDir=baseservices\threading\generics\syncdelegate\GThread23
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [opcodesldtoken.exe_1812]
 RelativePath=CoreMangLib\cti\system\reflection\emit\opcodes\OpCodesLdtoken\OpCodesLdtoken.exe
 WorkingDir=CoreMangLib\cti\system\reflection\emit\opcodes\OpCodesLdtoken
@@ -39484,7 +39484,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread21
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [b33922.exe_5044]
 RelativePath=JIT\Regression\CLR-x86-JIT\V1-M11-Beta1\b33922\b33922\b33922.exe
 WorkingDir=JIT\Regression\CLR-x86-JIT\V1-M11-Beta1\b33922\b33922
@@ -40534,7 +40534,7 @@ WorkingDir=baseservices\threading\generics\threadstart\GThread16
 MaxAllowedDurationSeconds=600
 HostStyle=Any
 Expected=100
-Categories=RT;EXPECTED_FAIL
+Categories=RT;EXPECTED_PASS;ISSUE_2823
 [fiborec.exe_2642]
 RelativePath=JIT\CodeGenBringUpTests\FiboRec\FiboRec.exe
 WorkingDir=JIT\CodeGenBringUpTests\FiboRec
index 96d1337..8e62e53 100644 (file)
@@ -91,8 +91,12 @@ set "__TestBinDir=%__RootBinDir%\tests\%__BuildOS%.%__BuildArch%.%__BuildType%\"
 :: We have different managed and native intermediate dirs because the managed bits will include
 :: the configuration information deeper in the intermediates path.
 :: These variables are used by the msbuild project files.
-set "__NativeTestIntermediatesDir=%__RootBinDir%\tests\obj\%__BuildOS%.%__BuildArch%.%__BuildType%\Native"
-set "__ManagedTestIntermediatesDir=%__RootBinDir%\tests\obj\%__BuildOS%.%__BuildArch%.%__BuildType%\Managed"
+
+if not defined __TestIntermediateDir (
+    set "__TestIntermediateDir=tests\obj\%__BuildOS%.%__BuildArch%.%__BuildType%"
+)
+set "__NativeTestIntermediatesDir=%__RootBinDir%\%__TestIntermediateDirDir%\Native"
+set "__ManagedTestIntermediatesDir=%__RootBinDir%\%__TestIntermediateDir%\Managed"
 
 :: Generate path to be set for CMAKE_INSTALL_PREFIX to contain forward slash
 set "__CMakeBinDir=%__TestBinDir%"
index 746f6ef..b419a66 100644 (file)
@@ -888,8 +888,8 @@ public class deltablue
     public static int Main(String[] args)
     {
         deltablue d = new deltablue();
-        d.inst_main(args);
-        return 100;
+        bool result = d.inst_main(args);
+        return (result ? 100 : -1);
     }
 
     [Benchmark]
@@ -906,17 +906,22 @@ public class deltablue
         }
     }
 
-    public void inst_main(String[] args)
+    public bool inst_main(String[] args)
     {
         int iterations = 200; // read iterations from arguments, walter 7/97
-        try
-        {   // read iterations from arguments, walter 7/97
-            iterations = Int32.Parse(args[0]);
-        }
-        catch (Exception)
+        if (args.Length > 0)
         {
+            bool parsed = Int32.TryParse(args[0], out iterations);
+            if (!parsed)
+            {
+                Console.WriteLine("Error: expected iteration count, got '{0}'", args[0]);
+                return false;
+            }
         }
+
         inst_inner(iterations, true);
+
+        return true;
     }
 
     public void inst_inner(int iterations, bool verbose)