Просмотр исходного кода

Merge branch 'master' into swb

# Conflicts:
#	build.sh
#	lib/Runtime/Base/FunctionBody.h
Lei Shi 9 лет назад
Родитель
Сommit
2a34df54ce
42 измененных файлов с 442 добавлено и 179 удалено
  1. 1 0
      .gitignore
  2. 1 0
      bin/ChakraCore/CMakeLists.txt
  3. 2 1
      bin/ChakraCore/ChakraCoreShared.cpp
  4. 1 1
      bin/ch/CMakeLists.txt
  5. 2 2
      bin/ch/Debugger.h
  6. 63 0
      bin/ch/jstoc.py
  7. 7 0
      build.sh
  8. 3 0
      lib/Backend/CodeGenNumberAllocator.cpp
  9. 3 2
      lib/Backend/Encoder.cpp
  10. 1 1
      lib/Backend/NativeCodeGenerator.cpp
  11. 1 1
      lib/Common/BackendApi.h
  12. 3 2
      lib/Common/CommonDefines.h
  13. 11 0
      lib/Common/CommonPal.h
  14. 4 1
      lib/Common/Memory/amd64/XDataAllocator.cpp
  15. 135 0
      lib/Common/PlatformAgnostic/Debugger.h
  16. 2 1
      lib/Jsrt/ChakraCore.h
  17. 2 2
      lib/Jsrt/Jsrt.cpp
  18. 7 0
      lib/Parser/Parse.cpp
  19. 2 2
      lib/Runtime/Base/CrossSite.cpp
  20. 7 7
      lib/Runtime/Base/FunctionBody.cpp
  21. 1 1
      lib/Runtime/Base/FunctionBody.h
  22. 61 23
      lib/Runtime/Base/ScriptContext.cpp
  23. 15 11
      lib/Runtime/Base/ScriptContext.h
  24. 1 1
      lib/Runtime/Base/Utf8SourceInfo.cpp
  25. 10 14
      lib/Runtime/ByteCode/ByteCodeGenerator.cpp
  26. 5 0
      lib/Runtime/Language/AsmJsModule.cpp
  27. 7 11
      lib/Runtime/Language/JavascriptStackWalker.cpp
  28. 7 11
      lib/Runtime/Language/amd64/JavascriptOperatorsA.S
  29. 27 58
      lib/Runtime/Language/amd64/amd64_Thunks.S
  30. 8 8
      lib/Runtime/Library/JavascriptFunction.cpp
  31. 2 0
      lib/Runtime/Library/JavascriptFunction.h
  32. 1 1
      lib/Runtime/Library/ScriptFunction.cpp
  33. 1 1
      lib/Runtime/Library/WebAssembly.cpp
  34. 0 2
      lib/Runtime/Library/amd64/JavascriptFunctionA.S
  35. 1 1
      lib/Runtime/Runtime.h
  36. 11 0
      test/AsmJs/bugGH2270.js
  37. 3 0
      test/AsmJs/rlexe.xml
  38. 4 4
      test/Debugger/MultipleContextStack.js
  39. 2 0
      test/Debugger/rlexe.xml
  40. 0 0
      test/DebuggerCommon/array_prototest.js.dbg.baseline
  41. 16 8
      test/DebuggerCommon/rlexe.xml
  42. 1 1
      test/runtests.py

+ 1 - 0
.gitignore

@@ -87,6 +87,7 @@ install_manifest.txt
 *.o
 Makefile
 pal/src/config.h
+DbgController.js.h
 
 # Generated by other tools
 *.orig

+ 1 - 0
bin/ChakraCore/CMakeLists.txt

@@ -23,6 +23,7 @@ target_include_directories (
 #
 if(CC_TARGET_OS_ANDROID OR CC_TARGET_OS_LINUX)
   set(LINKER_START_GROUP
+    -fPIC
     -Wl,--start-group
     -Wl,--whole-archive
     )

+ 2 - 1
bin/ChakraCore/ChakraCoreShared.cpp

@@ -15,6 +15,7 @@ void DummyJSRTCall()
     JsRuntimeHandle *runtime;
     JsRuntimeAttributes attr;
     JsCreateRuntime(attr, nullptr, runtime);
+    JsDiagStartDebugging(runtime, nullptr, nullptr);
 }
 #endif
 
@@ -30,4 +31,4 @@ EXTERN_C BOOL WINAPI DllMain(HINSTANCE hmod, DWORD dwReason, PVOID pvReserved)
     return TRUE;
 }
 
-static_assert(__LINE__ == 33, "You shouldn't add anything to this file or ChakraCoreDllFunc.cpp. Please consider again!");
+static_assert(__LINE__ == 34, "You shouldn't add anything to this file or ChakraCoreDllFunc.cpp. Please consider again!");

+ 1 - 1
bin/ch/CMakeLists.txt

@@ -34,7 +34,7 @@ target_include_directories (ch
 
 if(STATIC_LIBRARY)
   if(CC_TARGET_OS_ANDROID OR CC_TARGET_OS_LINUX)
-    set(LINKER_START_GROUP -Wl,--start-group)
+    set(LINKER_START_GROUP -pie -Wl,--start-group)
     set(LINKER_END_GROUP -Wl,--end-group -static-libstdc++)
   elseif(CC_TARGET_OS_OSX)
     set(LINKER_START_GROUP -Wl,-force_load,)

+ 2 - 2
bin/ch/Debugger.h

@@ -10,9 +10,9 @@ static const char controllerScript[] = {
     '\0'
 };
 #else
-static const char controllerScript[] = { '\0' };
+#include "DbgController.js.h"
 #endif
-    
+
 class Debugger
 {
 public:

+ 63 - 0
bin/ch/jstoc.py

@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+#-------------------------------------------------------------------------------------------------------
+# Copyright (C) Microsoft. All rights reserved.
+# Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+#-------------------------------------------------------------------------------------------------------
+
+from __future__ import with_statement # py 2.5
+import sys
+import os
+
+def print_usage():
+    print "jstoc tool"
+    print "creates a (const char array) from a javascript file."
+    print ""
+    print "usage: jstoc.py <js file path> <variable name>"
+    sys.exit(1)
+
+def convert():
+    if len(sys.argv) < 3:
+        print_usage()
+
+    js_file_name = sys.argv[1]
+    if os.path.isfile(js_file_name) == False:
+        print_usage()
+
+    h_file_name = js_file_name + '.h'
+
+    js_file_time = os.path.getmtime(js_file_name)
+    h_file_time = 0
+    if os.path.isfile(h_file_name):
+        h_file_time = os.path.getmtime(h_file_name)
+
+    str_header = "static const char " + sys.argv[2] + "[] = {\n"
+
+    # if header file is up to date and no update to jstoc.py since, skip..
+    if h_file_time < js_file_time or h_file_time < os.path.getmtime(sys.argv[0]):
+        with open(js_file_name, "rb") as js_file:
+            last_break = len(str_header) # skip first line
+            byte = js_file.read(1)
+            while byte:
+                str_header += str(ord(byte))
+                str_header += ","
+                # beautify a bit. limit column to ~80
+                column_check = (len(str_header) + 1) - last_break
+                if column_check > 5 and column_check % 80 < 5:
+                    last_break = len(str_header) + 1
+                    str_header += "\n"
+                else:
+                    str_header += " "
+                byte = js_file.read(1)
+            str_header += "0\n};"
+
+        h_file = open(h_file_name, "w")
+        h_file.write(str_header)
+        h_file.close()
+        print "-- " + h_file_name + " is created"
+    else:
+        print "-- " + h_file_name + " is up to date. skipping."
+
+if __name__ == '__main__':
+    sys.exit(convert())
+else:
+    print("try without python")

+ 7 - 0
build.sh

@@ -371,6 +371,13 @@ if [[ ${#_CXX} > 0 ]]; then
     CC_PREFIX="-DCMAKE_CXX_COMPILER=$_CXX -DCMAKE_C_COMPILER=$_CC"
 fi
 
+# prepare DbgController.js.h
+CH_DIR="${CHAKRACORE_DIR}/bin/ch"
+"${CH_DIR}/jstoc.py" "${CH_DIR}/DbgController.js" controllerScript
+if [[ $? != 0 ]]; then
+    exit 1
+fi
+
 ################# Write-barrier check/analyze run #################
 WB_FLAG=
 WB_TARGET=

+ 3 - 0
lib/Backend/CodeGenNumberAllocator.cpp

@@ -331,6 +331,9 @@ Js::JavascriptNumber* XProcNumberPageSegmentImpl::AllocateNumber(Func* func, dou
                 Recycler::FillPadNoCheck(pLocalNumber, sizeof(Js::JavascriptNumber), sizeCat, false);
                 pLocalNumber = new (pLocalNumber) Js::JavascriptNumber(localNumber);
             }
+#else
+            Assert(sizeCat == sizeof(Js::JavascriptNumber));
+            __analysis_assume(sizeCat == sizeof(Js::JavascriptNumber));
 #endif
             // change vtable to the remote one
             *(void**)pLocalNumber = (void*)func->GetScriptContextInfo()->GetVTableAddress(VTableValue::VtableJavascriptNumber);

+ 3 - 2
lib/Backend/Encoder.cpp

@@ -295,8 +295,9 @@ Encoder::Encode()
     {
         if (m_func->IsOOPJIT())
         {
-            Js::ThrowMapEntry * throwMap = NativeCodeDataNewArrayNoFixup(m_func->GetNativeCodeDataAllocator(), Js::ThrowMapEntry, m_pragmaInstrToRecordMap->Count());
-            for (int32 i = 0; i < m_pragmaInstrToRecordMap->Count(); i++)
+            int allocSize = m_pragmaInstrToRecordMap->Count();
+            Js::ThrowMapEntry * throwMap = NativeCodeDataNewArrayNoFixup(m_func->GetNativeCodeDataAllocator(), Js::ThrowMapEntry, allocSize);
+            for (int i = 0; i < allocSize; i++)
             {
                 IR::PragmaInstr *inst = m_pragmaInstrToRecordMap->Item(i);
                 throwMap[i].nativeBufferOffset = inst->m_offsetInBuffer;

+ 1 - 1
lib/Backend/NativeCodeGenerator.cpp

@@ -1548,7 +1548,7 @@ NativeCodeGenerator::CheckCodeGen(Js::ScriptFunction * function)
 
     if(!nativeCodeGen->Processor()->PrioritizeJob(nativeCodeGen, entryPoint, function))
     {
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
 #define originalEntryPoint_IS_ProfileDeferredParsingThunk \
             (originalEntryPoint == ProfileDeferredParsingThunk)
 #else

+ 1 - 1
lib/Common/BackendApi.h

@@ -19,7 +19,7 @@
 #define ProfileEntryThunk Js::ScriptContext::DebugProfileProbeThunk
 
 #define DefaultDeferredParsingThunk Js::JavascriptFunction::DeferredParsingThunk
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
 #define ProfileDeferredParsingThunk Js::ScriptContext::ProfileModeDeferredParsingThunk
 #endif
 

+ 3 - 2
lib/Common/CommonDefines.h

@@ -113,8 +113,6 @@
 #ifdef _WIN32
 // dep: TIME_ZONE_INFORMATION, DaylightTimeHelper, Windows.Globalization
 #define ENABLE_GLOBALIZATION
-// dep: IDebugDocumentContext
-#define ENABLE_SCRIPT_DEBUGGING
 // dep: IActiveScriptProfilerCallback, IActiveScriptProfilerHeapEnum
 #define ENABLE_SCRIPT_PROFILING
 #ifndef __clang__
@@ -125,6 +123,9 @@
 #define ENABLE_CUSTOM_ENTROPY
 #endif
 
+// dep: IDebugDocumentContext
+#define ENABLE_SCRIPT_DEBUGGING
+
 // GC features
 #define BUCKETIZE_MEDIUM_ALLOCATIONS 1              // *** TODO: Won't build if disabled currently
 #define SMALLBLOCK_MEDIUM_ALLOC 1                   // *** TODO: Won't build if disabled currently

+ 11 - 0
lib/Common/CommonPal.h

@@ -629,6 +629,16 @@ void TryFinally(const TryFunc& tryFunc, const FinallyFunc& finallyFunc)
     finallyFunc(hasException);
 }
 
+#ifdef DISABLE_SEH
+#define __TRY_FINALLY_BEGIN TryFinally([&]()
+#define __FINALLY           , [&](bool /* hasException */)
+#define __TRY_FINALLY_END   );
+#else
+#define __TRY_FINALLY_BEGIN __try
+#define __FINALLY   __finally
+#define __TRY_FINALLY_END 
+#endif
+
 namespace PlatformAgnostic
 {
     __forceinline unsigned char _BitTestAndSet(LONG *_BitBase, int _BitPos)
@@ -691,3 +701,4 @@ namespace PlatformAgnostic
 #include "PlatformAgnostic/SystemInfo.h"
 #include "PlatformAgnostic/Thread.h"
 #include "PlatformAgnostic/AssemblyCommon.h"
+#include "PlatformAgnostic/Debugger.h"

+ 4 - 1
lib/Common/Memory/amd64/XDataAllocator.cpp

@@ -34,6 +34,7 @@ bool XDataAllocator::Initialize(void* segmentStart, void* segmentEnd)
 
 XDataAllocator::~XDataAllocator()
 {
+    current = nullptr;
     ClearFreeList();
 }
 
@@ -42,7 +43,8 @@ void XDataAllocator::Delete()
     HeapDelete(this);
 }
 
-bool XDataAllocator::Alloc(ULONG_PTR functionStart, DWORD functionSize, ushort pdataCount, ushort xdataSize, SecondaryAllocation* allocation)
+bool XDataAllocator::Alloc(ULONG_PTR functionStart, DWORD functionSize,
+    ushort pdataCount, ushort xdataSize, SecondaryAllocation* allocation)
 {
     XDataAllocation* xdata = static_cast<XDataAllocation*>(allocation);
     Assert(start != nullptr);
@@ -107,6 +109,7 @@ void XDataAllocator::ClearFreeList()
     {
         entry = next;
         next = entry->next;
+        entry->address = nullptr;
         HeapDelete(entry);
     }
     this->freeList = NULL;

+ 135 - 0
lib/Common/PlatformAgnostic/Debugger.h

@@ -0,0 +1,135 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+#ifndef RUNTIME_PLATFORM_AGNOSTIC_DEBUGGER
+#define RUNTIME_PLATFORM_AGNOSTIC_DEBUGGER
+
+#ifndef _WIN32
+
+#define ACTIVPROF_E_PROFILER_PRESENT        0x0200
+#define ACTIVPROF_E_PROFILER_ABSENT         0x0201
+#define ACTIVPROF_E_UNABLE_TO_APPLY_ACTION  0x0202
+#define PROFILER_TOKEN uint
+
+typedef enum {
+    PROFILER_SCRIPT_TYPE_USER,
+    PROFILER_SCRIPT_TYPE_DYNAMIC,
+    PROFILER_SCRIPT_TYPE_NATIVE,
+    PROFILER_SCRIPT_TYPE_DOM
+} PROFILER_SCRIPT_TYPE;
+
+typedef enum {
+    PROFILER_EVENT_MASK_TRACE_SCRIPT_FUNCTION_CALL = 0x00000001,
+    PROFILER_EVENT_MASK_TRACE_NATIVE_FUNCTION_CALL = 0x00000002,
+    PROFILER_EVENT_MASK_TRACE_DOM_FUNCTION_CALL    = 0x00000004,
+    PROFILER_EVENT_MASK_TRACE_ALL =
+    PROFILER_EVENT_MASK_TRACE_SCRIPT_FUNCTION_CALL |
+    PROFILER_EVENT_MASK_TRACE_NATIVE_FUNCTION_CALL,
+    PROFILER_EVENT_MASK_TRACE_ALL_WITH_DOM = PROFILER_EVENT_MASK_TRACE_ALL |
+    PROFILER_EVENT_MASK_TRACE_DOM_FUNCTION_CALL
+} PROFILER_EVENT_MASK;
+
+interface IEnumDebugCodeContexts : IUnknown
+{
+    // HRESULT Next( ..
+
+    // HRESULT Skip( ..
+
+    // HRESULT Reset();
+
+    // HRESULT Clone( ..
+};
+
+interface IDebugDocumentInfo : IUnknown
+{
+    HRESULT GetName(char* dn, BSTR *name);
+
+    HRESULT GetDocumentClassId(CLSID *dclsid);
+};
+
+interface IDebugDocument : IDebugDocumentInfo
+{
+};
+
+interface IDebugDocumentContext : IUnknown
+{
+    HRESULT GetDocument(IDebugDocument **doc);
+
+    HRESULT EnumCodeContexts(IEnumDebugCodeContexts **dctx);
+};
+
+class IActiveScriptProfilerCallback
+{
+public:
+  HRESULT Initialize(DWORD ctx)
+  {
+      return S_OK;
+  }
+
+  HRESULT Shutdown(HRESULT _)
+  {
+      return S_OK;
+  }
+
+  HRESULT Release()
+  {
+      return S_OK;
+  }
+
+  HRESULT QueryInterface(IActiveScriptProfilerCallback **_)
+  {
+      return S_OK;
+  }
+
+  HRESULT ScriptCompiled(PROFILER_TOKEN scriptId, PROFILER_SCRIPT_TYPE type, IUnknown *ctx)
+  {
+      return S_OK;
+  }
+
+  HRESULT FunctionCompiled(PROFILER_TOKEN functionId, PROFILER_TOKEN scriptId,
+      const WCHAR* pwszFunctionName, const WCHAR* pwszFunctionNameHint, IUnknown *ctx)
+  {
+      return S_OK;
+  }
+
+  HRESULT OnFunctionEnter(PROFILER_TOKEN scriptId, PROFILER_TOKEN functionId)
+  {
+      return S_OK;
+  }
+
+  HRESULT OnFunctionExit(PROFILER_TOKEN scriptId, PROFILER_TOKEN functionId)
+  {
+      return S_OK;
+  }
+
+  // IActiveScriptProfilerCallback2
+  HRESULT OnFunctionEnterByName(const WCHAR *functionName, PROFILER_SCRIPT_TYPE _)
+  {
+      return S_OK;
+  }
+
+  HRESULT OnFunctionExitByName(const WCHAR *functionName, PROFILER_SCRIPT_TYPE _)
+  {
+      return S_OK;
+  }
+
+  // IActiveScriptProfilerCallback3
+  HRESULT AddRef()
+  {
+      return S_OK;
+  }
+
+  HRESULT SetWebWorkerId(PROFILER_TOKEN _)
+  {
+      return S_OK;
+  }
+};
+
+#define IActiveScriptProfilerCallback2 IActiveScriptProfilerCallback
+#define IActiveScriptProfilerCallback3 IActiveScriptProfilerCallback
+
+#endif // !_WIN32
+
+#endif // RUNTIME_PLATFORM_AGNOSTIC_DEBUGGER

+ 2 - 1
lib/Jsrt/ChakraCore.h

@@ -163,6 +163,7 @@ JsGetModuleHostInfo(
     _In_ JsModuleHostInfoKind moduleHostInfo,
     _Outptr_result_maybenull_ void** hostInfo);
 
+#ifdef CHAKRACOREBUILD_
 /// <summary>
 ///     Called by the runtime to load the source code of the serialized script.
 /// </summary>
@@ -493,5 +494,5 @@ CHAKRA_API
         _In_ JsSourceContext sourceContext,
         _In_ JsValueRef sourceUrl,
         _Out_ JsValueRef *result);
-
+#endif // CHAKRACOREBUILD_
 #endif // _CHAKRACORE_H_

+ 2 - 2
lib/Jsrt/Jsrt.cpp

@@ -3454,9 +3454,9 @@ CHAKRA_API JsTTDStart()
 
     Js::ScriptContext* scriptContext = currentContext->GetScriptContext();
     TTDAssert(scriptContext->IsTTDRecordOrReplayModeEnabled(), "Need to create in TTD Record Mode.");
-
+#if ENABLE_NATIVE_CODEGEN
     TTDAssert(JITManager::GetJITManager() == nullptr || !JITManager::GetJITManager()->IsOOPJITEnabled(), "TTD cannot run with OOP JIT yet!!!");
-
+#endif
     return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode
     {
         if(scriptContext->IsTTDRecordModeEnabled())

+ 7 - 0
lib/Parser/Parse.cpp

@@ -13455,6 +13455,13 @@ DeferredFunctionStub * BuildDeferredStubTree(ParseNode *pnodeFnc, Recycler *recy
         }
         AssertOrFailFast(i < nestedCount);
 
+        if (pnodeChild->sxFnc.pnodeBody != nullptr)
+        {
+            // Anomalous case of a non-deferred function nested within a deferred one.
+            // Work around by discarding the stub tree.
+            return nullptr;
+        }
+
         if (pnodeChild->sxFnc.IsGeneratedDefault())
         {
             ++i;

+ 2 - 2
lib/Runtime/Base/CrossSite.cpp

@@ -289,14 +289,14 @@ namespace Js
 
     bool CrossSite::IsThunk(JavascriptMethod thunk)
     {
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
         return (thunk == CrossSite::ProfileThunk || thunk == CrossSite::DefaultThunk);
 #else
         return (thunk == CrossSite::DefaultThunk);
 #endif
     }
 
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
     Var CrossSite::ProfileThunk(RecyclableObject* callable, CallInfo callInfo, ...)
     {
         JavascriptFunction* function = JavascriptFunction::FromVar(callable);

+ 7 - 7
lib/Runtime/Base/FunctionBody.cpp

@@ -1612,7 +1612,7 @@ namespace Js
     ParseableFunctionInfo* ParseableFunctionInfo::New(ScriptContext* scriptContext, int nestedCount,
         LocalFunctionId functionId, Utf8SourceInfo* sourceInfo, const char16* displayName, uint displayNameLength, uint displayShortNameOffset, Js::PropertyRecordList* propertyRecords, FunctionInfo::Attributes attributes, FunctionBodyFlags flags)
     {
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
         Assert(
             scriptContext->DeferredParsingThunk == ProfileDeferredParsingThunk ||
             scriptContext->DeferredParsingThunk == DefaultDeferredParsingThunk);
@@ -3459,7 +3459,7 @@ namespace Js
 #endif
         ;
     }
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
     bool FunctionProxy::HasValidProfileEntryPoint() const
     {
         JavascriptMethod directEntryPoint = this->GetDefaultEntryPointInfo()->jsMethod;
@@ -3504,7 +3504,7 @@ namespace Js
         {
             return this->HasValidNonProfileEntryPoint();
         }
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
         if (m_scriptContext->IsProfiling())
         {
             return this->HasValidProfileEntryPoint();
@@ -3519,7 +3519,7 @@ namespace Js
 #endif
     void ParseableFunctionInfo::SetDeferredParsingEntryPoint()
     {
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
         Assert(m_scriptContext->DeferredParsingThunk == ProfileDeferredParsingThunk
             || m_scriptContext->DeferredParsingThunk == DefaultDeferredParsingThunk);
 #else
@@ -3532,7 +3532,7 @@ namespace Js
 
     void ParseableFunctionInfo::SetInitialDefaultEntryPoint()
     {
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
         Assert(m_scriptContext->CurrentThunk == ProfileEntryThunk || m_scriptContext->CurrentThunk == DefaultEntryThunk);
         Assert(this->GetOriginalEntryPoint_Unchecked() == DefaultDeferredParsingThunk ||
                this->GetOriginalEntryPoint_Unchecked() == ProfileDeferredParsingThunk ||
@@ -4955,12 +4955,12 @@ namespace Js
     {
         ProxyEntryPointInfo* defaultEntryPointInfo = this->GetDefaultEntryPointInfo();
         if (defaultEntryPointInfo->jsMethod != DefaultDeferredParsingThunk
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
             && defaultEntryPointInfo->jsMethod != ProfileDeferredParsingThunk
 #endif
             )
         {
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
             // Just change the thunk, the cleanup will be done once the function gets called.
             if (this->m_scriptContext->CurrentThunk == ProfileEntryThunk)
             {

+ 1 - 1
lib/Runtime/Base/FunctionBody.h

@@ -1471,7 +1471,7 @@ namespace Js
 
 #if DBG
         bool HasValidEntryPoint() const;
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
         bool HasValidProfileEntryPoint() const;
 #endif
         bool HasValidNonProfileEntryPoint() const;

+ 61 - 23
lib/Runtime/Base/ScriptContext.cpp

@@ -3071,6 +3071,34 @@ namespace Js
         }
 
         HRESULT hr = S_OK;
+
+#ifndef _WIN32
+        BEGIN_TRANSLATE_OOM_TO_HRESULT_NESTED
+        {
+            // xplat eh_frame handling is a bit different than Windows
+            // RecreateNativeCodeGenerator call below will be cleaning up
+            // XDataAllocation and we won't be able to __DEREGISTER_FRAME
+
+            // xplat-todo: make eh_frame handling better
+            this->sourceList->Map([=](uint i, RecyclerWeakReference<Js::Utf8SourceInfo>* sourceInfoWeakRef) {
+                Js::Utf8SourceInfo* sourceInfo = sourceInfoWeakRef->Get();
+
+                if (sourceInfo != nullptr)
+                {
+                    sourceInfo->MapFunction([](Js::FunctionBody* functionBody) {
+                        functionBody->ResetEntryPoint();
+                    });
+                }
+            });
+        }
+        END_TRANSLATE_OOM_TO_HRESULT(hr);
+
+        if (FAILED(hr))
+        {
+            return hr;
+        }
+#endif
+
         if (!CONFIG_FLAG(ForceDiagnosticsMode))
         {
 #if ENABLE_NATIVE_CODEGEN
@@ -3113,12 +3141,14 @@ namespace Js
                             functionBody->SetEntryToDeferParseForDebugger();
                         });
                     }
+#ifdef _WIN32
                     else
                     {
                         sourceInfo->MapFunction([](Js::FunctionBody* functionBody) {
                             functionBody->ResetEntryPoint();
                         });
                     }
+#endif
                 }
             });
         }
@@ -3134,7 +3164,6 @@ namespace Js
             this->RegisterDebugThunk();
         }
 
-
 #if ENABLE_PROFILE_INFO
 #if DBG_DUMP || defined(DYNAMIC_PROFILE_STORAGE) || defined(RUNTIME_DATA_COLLECTION)
         // Reset the dynamic profile list
@@ -3147,12 +3176,12 @@ namespace Js
         return hr;
     }
 
+#if defined(ENABLE_SCRIPT_DEBUGGING) || defined(ENABLE_SCRIPT_PROFILING)
     // We use ProfileThunk under debugger.
     void ScriptContext::RegisterDebugThunk(bool calledDuringAttach /*= true*/)
     {
         if (this->IsExceptionWrapperForBuiltInsEnabled())
         {
-#ifdef ENABLE_SCRIPT_PROFILING
             this->CurrentThunk = ProfileEntryThunk;
             this->CurrentCrossSiteThunk = CrossSite::ProfileThunk;
 #if ENABLE_NATIVE_CODEGEN
@@ -3163,16 +3192,14 @@ namespace Js
             // are created with entry point set to the ProfileThunk.
             this->javascriptLibrary->SetProfileMode(true);
             this->javascriptLibrary->SetDispatchProfile(true, DispatchProfileInvoke);
+
+#ifdef ENABLE_SCRIPT_PROFILING
             if (!calledDuringAttach)
             {
-#ifdef ENABLE_SCRIPT_PROFILING
                 m_fTraceDomCall = TRUE; // This flag is always needed in DebugMode to wrap external functions with DebugProfileThunk
-#endif
                 // Update the function objects currently present in there.
                 this->SetFunctionInRecyclerToProfileMode(true/*enumerateNonUserFunctionsOnly*/);
             }
-#else
-            AssertMsg(false, "Profiling needs to be enabled to call RegisterDebugThunk");
 #endif
         }
     }
@@ -3194,6 +3221,7 @@ namespace Js
             }
         }
     }
+#endif // defined(ENABLE_SCRIPT_DEBUGGING) || defined(ENABLE_SCRIPT_PROFILING)
 
 #ifdef ENABLE_SCRIPT_PROFILING
     HRESULT ScriptContext::RegisterBuiltinFunctions(RegisterExternalLibraryType RegisterExternalLibrary)
@@ -3389,7 +3417,7 @@ namespace Js
         scriptFunction->ChangeEntryPoint(pBody->GetDefaultFunctionEntryPointInfo(), newEntryPoint);
     }
 
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
     void ScriptContext::RecyclerEnumClassEnumeratorCallback(void *address, size_t size)
     {
         // TODO: we are assuming its function because for now we are enumerating only on functions
@@ -3430,6 +3458,7 @@ namespace Js
             char16 debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
 #endif
 
+#if defined(ENABLE_SCRIPT_PROFILING)
             OUTPUT_TRACE(Js::ScriptProfilerPhase, _u("ScriptContext::RecyclerEnumClassEnumeratorCallback\n"));
             OUTPUT_TRACE(Js::ScriptProfilerPhase, _u("\tFunctionProxy : 0x%08X, FunctionNumber : %s, DeferredParseAttributes : %d, EntryPoint : 0x%08X"),
                 (DWORD_PTR)proxy, proxy->GetDebugNumberSet(debugStringBuffer), proxy->GetAttributes(), (DWORD_PTR)entryPoint);
@@ -3438,6 +3467,7 @@ namespace Js
                 IsTrueOrFalse(IsIntermediateCodeGenThunk(entryPoint)), IsTrueOrFalse(scriptContext->IsNativeAddress(entryPoint)));
 #endif
             OUTPUT_TRACE(Js::ScriptProfilerPhase, _u("\n"));
+#endif
 
 #if ENABLE_NATIVE_CODEGEN
             if (!IsIntermediateCodeGenThunk(entryPoint) && entryPoint != DynamicProfileInfo::EnsureDynamicProfileInfoThunk)
@@ -3448,7 +3478,7 @@ namespace Js
                 ScriptFunction * scriptFunction = ScriptFunction::FromVar(pFunction);
                 scriptFunction->ChangeEntryPoint(proxy->GetDefaultEntryPointInfo(), Js::ScriptContext::GetProfileModeThunk(entryPoint));
 
-#if ENABLE_NATIVE_CODEGEN
+#if ENABLE_NATIVE_CODEGEN && defined(ENABLE_SCRIPT_PROFILING)
                 OUTPUT_TRACE(Js::ScriptProfilerPhase, _u("\tUpdated entrypoint : 0x%08X (isNative : %s)\n"), (DWORD_PTR)pFunction->GetEntryPoint(), IsTrueOrFalse(scriptContext->IsNativeAddress(entryPoint)));
 #endif
             }
@@ -3489,9 +3519,9 @@ namespace Js
 
     JavascriptMethod ScriptContext::GetProfileModeThunk(JavascriptMethod entryPoint)
     {
-#if ENABLE_NATIVE_CODEGEN
+    #if ENABLE_NATIVE_CODEGEN
         Assert(!IsIntermediateCodeGenThunk(entryPoint));
-#endif
+    #endif
         if (entryPoint == DefaultDeferredParsingThunk || entryPoint == ProfileDeferredParsingThunk)
         {
             return ProfileDeferredParsingThunk;
@@ -3508,7 +3538,7 @@ namespace Js
         }
         return ProfileEntryThunk;
     }
-#endif // ENABLE_SCRIPT_PROFILING
+#endif // defined(ENABLE_SCRIPT_PROFILING) || defiend(ENABLE_SCRIPT_DEBUGGING)
 
 #if _M_IX86
     __declspec(naked)
@@ -3717,12 +3747,7 @@ namespace Js
         Assert(!AsmJsScriptFunction::IsWasmScriptFunction(callable));
         JavascriptFunction* function = JavascriptFunction::FromVar(callable);
         ScriptContext* scriptContext = function->GetScriptContext();
-        PROFILER_TOKEN scriptId = -1;
-        PROFILER_TOKEN functionId = -1;
         bool functionEnterEventSent = false;
-
-        const bool isProfilingUserCode = scriptContext->GetThreadContext()->IsProfilingUserCode();
-        const bool isUserCode = !function->IsLibraryCode();
         char16 *pwszExtractedFunctionName = NULL;
         const char16 *pwszFunctionName = NULL;
         HRESULT hrOfEnterEvent = S_OK;
@@ -3730,6 +3755,12 @@ namespace Js
         // We can come here when profiling is not on
         // e.g. User starts profiling, we update all thinks and then stop profiling - we don't update thunk
         // So we still get this call
+#if defined(ENABLE_SCRIPT_PROFILING)
+        PROFILER_TOKEN scriptId = -1;
+        PROFILER_TOKEN functionId = -1;
+        const bool isProfilingUserCode = scriptContext->GetThreadContext()->IsProfilingUserCode();
+        const bool isUserCode = !function->IsLibraryCode();
+
         const bool fProfile = (isUserCode || isProfilingUserCode) // Only report user code or entry library code
             && scriptContext->GetProfileInfo(function, scriptId, functionId);
 
@@ -3754,7 +3785,7 @@ namespace Js
                 }
                 AssertMsg(pBody == NULL || pBody->GetProfileSession() == pBody->GetScriptContext()->GetProfileSession(), "Function info wasn't reported for this profile session");
             }
-#endif
+#endif // DEBUG
 
             if (functionId == -1)
             {
@@ -3803,11 +3834,12 @@ namespace Js
 
             scriptContext->GetThreadContext()->SetIsProfilingUserCode(isUserCode); // Update IsProfilingUserCode state
         }
+#endif // ENABLE_SCRIPT_PROFILING
 
         Var aReturn = NULL;
         JavascriptMethod origEntryPoint = function->GetFunctionInfo()->GetOriginalEntryPoint();
 
-        __try
+        __TRY_FINALLY_BEGIN // SEH is not guaranteed, see the implementation
         {
             Assert(!function->IsScriptFunction() || function->GetFunctionProxy());
 
@@ -3848,14 +3880,15 @@ namespace Js
                     {
                         threadContext->GetDebugManager()->GetDebuggingFlags()->SetIsBuiltInWrapperPresent(false);
                     }
-                    __try
+                    __TRY_FINALLY_BEGIN // SEH is not guaranteed, see the implementation
                     {
                         aReturn = JavascriptFunction::CallFunction<true>(function, origEntryPoint, args);
                     }
-                    __finally
+                    __FINALLY
                     {
                         threadContext->GetDebugManager()->GetDebuggingFlags()->SetIsBuiltInWrapperPresent(isOrigWrapperPresent);
                     }
+                    __TRY_FINALLY_END
                 }
                 else
                 {
@@ -3866,8 +3899,9 @@ namespace Js
                 }
             }
         }
-        __finally
+        __FINALLY
         {
+#if defined(ENABLE_SCRIPT_PROFILING)
             if (fProfile)
             {
                 if (hrOfEnterEvent != ACTIVPROF_E_PROFILER_ABSENT)
@@ -3892,12 +3926,14 @@ namespace Js
 
                 scriptContext->GetThreadContext()->SetIsProfilingUserCode(isProfilingUserCode); // Restore IsProfilingUserCode state
             }
+#endif
 
             if (scriptContext->IsScriptContextInDebugMode())
             {
                 scriptContext->GetDebugContext()->GetProbeContainer()->EndRecordingCall(aReturn, function);
             }
         }
+        __TRY_FINALLY_END
 
         return aReturn;
 #else
@@ -3905,7 +3941,7 @@ namespace Js
 #endif // defined(ENABLE_SCRIPT_DEBUGGING) || defined(ENABLE_SCRIPT_PROFILING)
     }
 
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_DEBUGGING) || defined(ENABLE_SCRIPT_PROFILING)
     // Part of ProfileModeThunk which is called in debug mode (debug or debug & profile).
     Var ScriptContext::ProfileModeThunk_DebugModeWrapper(JavascriptFunction* function, ScriptContext* scriptContext, JavascriptMethod entryPoint, Arguments& args)
     {
@@ -3917,7 +3953,9 @@ namespace Js
 
         return aReturn;
     }
+#endif
 
+#ifdef ENABLE_SCRIPT_PROFILING
     HRESULT ScriptContext::OnScriptCompiled(PROFILER_TOKEN scriptId, PROFILER_SCRIPT_TYPE type, IUnknown *pIDebugDocumentContext)
     {
         // TODO : can we do a delay send of these events or can we send an event before doing all this stuff that could calculate overhead?
@@ -4025,7 +4063,7 @@ namespace Js
 
     HRESULT ScriptContext::RegisterLibraryFunction(const char16 *pwszObjectName, const char16 *pwszFunctionName, Js::PropertyId functionPropertyId, JavascriptMethod entryPoint)
     {
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING)
 #if DEBUG
         const char16 *pwszObjectNameFromProperty = const_cast<char16 *>(GetPropertyName(functionPropertyId)->GetBuffer());
         if (GetPropertyName(functionPropertyId)->IsSymbol())

+ 15 - 11
lib/Runtime/Base/ScriptContext.h

@@ -4,7 +4,7 @@
 //-------------------------------------------------------------------------------------------------------
 #pragma once
 
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(_WIN32) && defined(ENABLE_SCRIPT_PROFILING)
 #include "activprof.h"
 #endif
 
@@ -529,9 +529,11 @@ namespace Js
         bool IsExceptionWrapperForBuiltInsEnabled();
         static bool IsExceptionWrapperForBuiltInsEnabled(ScriptContext* scriptContext);
         static bool IsExceptionWrapperForHelpersEnabled(ScriptContext* scriptContext);
-#ifdef ENABLE_SCRIPT_PROFILING
         bool IsEnumerateNonUserFunctionsOnly() const { return m_enumerateNonUserFunctionsOnly; }
+#ifdef ENABLE_SCRIPT_PROFILING
         bool IsTraceDomCall() const { return !!m_fTraceDomCall; }
+#elif defined(ENABLE_SCRIPT_DEBUGGING)
+        bool IsTraceDomCall() const { return false; }
 #endif
 
         InlineCache * GetValueOfInlineCache() const { return valueOfInlineCache;}
@@ -1516,9 +1518,9 @@ private:
         typedef HRESULT (*RegisterExternalLibraryType)(Js::ScriptContext *pScriptContext);
 #ifdef ENABLE_SCRIPT_PROFILING
         HRESULT RegisterProfileProbe(IActiveScriptProfilerCallback *pProfileCallback, DWORD dwEventMask, DWORD dwContext, RegisterExternalLibraryType RegisterExternalLibrary, JavascriptMethod dispatchInvoke);
+        HRESULT DeRegisterProfileProbe(HRESULT hrReason, JavascriptMethod dispatchInvoke);
 #endif
         HRESULT SetProfileEventMask(DWORD dwEventMask);
-        HRESULT DeRegisterProfileProbe(HRESULT hrReason, JavascriptMethod dispatchInvoke);
 
         HRESULT RegisterScript(Js::FunctionProxy *pFunctionBody, BOOL fRegisterScript = TRUE);
 
@@ -1534,17 +1536,16 @@ private:
         HRESULT RegisterLibraryFunction(const char16 *pwszObjectName, const char16 *pwszFunctionName, Js::PropertyId functionPropertyId, JavascriptMethod entryPoint);
 
         HRESULT RegisterBuiltinFunctions(RegisterExternalLibraryType RegisterExternalLibrary);
-        void RegisterDebugThunk(bool calledDuringAttach = true);
-        void UnRegisterDebugThunk();
-
         void UpdateRecyclerFunctionEntryPointsForDebugger();
         void SetFunctionInRecyclerToProfileMode(bool enumerateNonUserFunctionsOnly = false);
-#ifdef ENABLE_SCRIPT_PROFILING
+
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
+        void RegisterDebugThunk(bool calledDuringAttach = true);
+        void UnRegisterDebugThunk();
         static void SetEntryPointToProfileThunk(JavascriptFunction* function);
         static void RestoreEntryPointFromProfileThunk(JavascriptFunction* function);
-#endif
-
         static void RecyclerEnumClassEnumeratorCallback(void *address, size_t size);
+#endif
         static void RecyclerFunctionCallbackForDebugger(void *address, size_t size);
 
         static ushort ProcessNameAndGetLength(Js::StringBuilder<ArenaAllocator>* nameBuffer, const WCHAR* name);
@@ -1634,10 +1635,13 @@ private:
         static JavascriptMethod ProfileModeDeferredDeserialize(ScriptFunction* function);
         static Var ProfileModeDeferredDeserializeThunk(RecyclableObject* function, CallInfo callInfo, ...);
 
+#if defined(ENABLE_SCRIPT_DEBUGGING) || defined(ENABLE_SCRIPT_PROFILING)
+        static Var ProfileModeThunk_DebugModeWrapper(JavascriptFunction* function, ScriptContext* scriptContext, JavascriptMethod entryPoint, Arguments& args);
+        static JavascriptMethod GetProfileModeThunk(JavascriptMethod entryPoint);
+#endif
+
 #ifdef ENABLE_SCRIPT_PROFILING
         void SetProfileMode(BOOL fSet);
-        static JavascriptMethod GetProfileModeThunk(JavascriptMethod entryPoint);
-        static Var ProfileModeThunk_DebugModeWrapper(JavascriptFunction* function, ScriptContext* scriptContext, JavascriptMethod entryPoint, Arguments& args);
         BOOL GetProfileInfo(
             JavascriptFunction* function,
             PROFILER_TOKEN &scriptId,

+ 1 - 1
lib/Runtime/Base/Utf8SourceInfo.cpp

@@ -411,7 +411,7 @@ namespace Js
 
     bool Utf8SourceInfo::GetDebugDocumentName(BSTR * sourceName)
     {
-#ifdef ENABLE_SCRIPT_DEBUGGING
+#if defined(ENABLE_SCRIPT_DEBUGGING) && defined(_WIN32)
         if (this->HasDebugDocument() && this->GetDebugDocument()->HasDocumentText())
         {
             // ToDo (SaAgarwa): Fix for JsRT debugging

+ 10 - 14
lib/Runtime/ByteCode/ByteCodeGenerator.cpp

@@ -1166,12 +1166,7 @@ ParseNode* VisitBlock(ParseNode *pnode, ByteCodeGenerator* byteCodeGenerator, Pr
 FuncInfo * ByteCodeGenerator::StartBindFunction(const char16 *name, uint nameLength, uint shortNameOffset, bool* pfuncExprWithName, ParseNode *pnode, Js::ParseableFunctionInfo * reuseNestedFunc)
 {
     bool funcExprWithName;
-    union
-    {
-        Js::ParseableFunctionInfo* parseableFunctionInfo;
-        Js::FunctionBody* parsedFunctionBody;
-    };
-    bool isDeferParsed = false;
+    Js::ParseableFunctionInfo* parseableFunctionInfo = nullptr;
 
     if (this->pCurrentFunction &&
         this->pCurrentFunction->IsFunctionParsed())
@@ -1181,7 +1176,7 @@ FuncInfo * ByteCodeGenerator::StartBindFunction(const char16 *name, uint nameLen
 
         // This is the root function for the current AST subtree, and it already has a FunctionBody
         // (created by a deferred parse) which we're now filling in.
-        parsedFunctionBody = this->pCurrentFunction;
+        Js::FunctionBody * parsedFunctionBody = this->pCurrentFunction;
         parsedFunctionBody->RemoveDeferParseAttribute();
 
         if (parsedFunctionBody->GetBoundPropertyRecords() == nullptr)
@@ -1222,18 +1217,18 @@ FuncInfo * ByteCodeGenerator::StartBindFunction(const char16 *name, uint nameLen
                 }
             }
         }
+
+        parseableFunctionInfo = parsedFunctionBody;
     }
     else
     {
         funcExprWithName = *pfuncExprWithName;
         Js::LocalFunctionId functionId = pnode->sxFnc.functionId;
 
-        isDeferParsed = (pnode->sxFnc.pnodeBody == nullptr);
-
         // Create a function body if:
         //  1. The parse node is not defer parsed
         //  2. Or creating function proxies is disallowed
-        bool createFunctionBody = !isDeferParsed && (!reuseNestedFunc || reuseNestedFunc->IsFunctionBody());
+        bool createFunctionBody = (pnode->sxFnc.pnodeBody != nullptr) && (!reuseNestedFunc || reuseNestedFunc->IsFunctionBody());
         if (!CONFIG_FLAG(CreateFunctionProxy)) createFunctionBody = true;
 
         Js::FunctionInfo::Attributes attributes = Js::FunctionInfo::Attributes::None;
@@ -1284,11 +1279,11 @@ FuncInfo * ByteCodeGenerator::StartBindFunction(const char16 *name, uint nameLen
             if (reuseNestedFunc)
             {
                 Assert(reuseNestedFunc->IsFunctionBody());
-                parsedFunctionBody = reuseNestedFunc->GetFunctionBody();
+                parseableFunctionInfo = reuseNestedFunc->GetFunctionBody();
             }
             else
             {
-                parsedFunctionBody = Js::FunctionBody::NewFromRecycler(scriptContext, name, nameLength, shortNameOffset, pnode->sxFnc.nestedCount, m_utf8SourceInfo,
+                parseableFunctionInfo = Js::FunctionBody::NewFromRecycler(scriptContext, name, nameLength, shortNameOffset, pnode->sxFnc.nestedCount, m_utf8SourceInfo,
                     m_utf8SourceInfo->GetSrcInfo()->sourceContextInfo->sourceContextId, functionId, propertyRecordList
                     , attributes
                     , pnode->sxFnc.IsClassConstructor() ?
@@ -1351,7 +1346,7 @@ FuncInfo * ByteCodeGenerator::StartBindFunction(const char16 *name, uint nameLen
 
         sym->SetIsFuncExpr(true);
 
-        sym->SetPosition(parsedFunctionBody->GetOrAddPropertyIdTracked(sym->GetName()));
+        sym->SetPosition(parseableFunctionInfo->GetOrAddPropertyIdTracked(sym->GetName()));
 
         pnode->sxFnc.SetFuncSymbol(sym);
     }
@@ -1398,8 +1393,9 @@ FuncInfo * ByteCodeGenerator::StartBindFunction(const char16 *name, uint nameLen
         funcInfo->SetHasMaybeEscapedNestedFunc(DebugOnly(_u("ArgumentsObjectEscapes")));
     }
 
-    if (!isDeferParsed)
+    if (parseableFunctionInfo->IsFunctionBody())
     {
+        Js::FunctionBody * parsedFunctionBody = parseableFunctionInfo->GetFunctionBody();
         if (parsedFunctionBody->IsReparsed())
         {
             parsedFunctionBody->RestoreState(pnode);

+ 5 - 0
lib/Runtime/Language/AsmJsModule.cpp

@@ -1080,6 +1080,11 @@ namespace Js
     AsmJsFunc* AsmJsModuleCompiler::CreateNewFunctionEntry( ParseNode* pnodeFnc )
     {
         PropertyName name = ParserWrapper::FunctionName( pnodeFnc );
+        if ( !name )
+        {
+            return nullptr;
+        }
+
         GetByteCodeGenerator()->AssignPropertyId(name);
         AsmJsFunc* func = Anew( &mAllocator, AsmJsFunc, name, pnodeFnc, &mAllocator, mCx->scriptContext );
         if( func )

+ 7 - 11
lib/Runtime/Language/JavascriptStackWalker.cpp

@@ -272,7 +272,7 @@ namespace Js
         {
             return inlinedFrameWalker.GetArgv(/* includeThis = */ false);
         }
-        else 
+        else
 #endif
             if (this->GetCurrentFunction()->GetFunctionInfo()->IsCoroutine())
         {
@@ -455,7 +455,7 @@ namespace Js
             tmpFrameWalker.Close();
         }
 
-        if (inlineeOffset != 0 && 
+        if (inlineeOffset != 0 &&
             parentFunction->GetFunctionBody()->GetMatchingStatementMapFromNativeOffset(pCodeAddr, inlineeOffset, data, loopNum, *inlinee))
         {
             offset = data.bytecodeBegin;
@@ -621,10 +621,6 @@ namespace Js
         return nullptr;
     }
 
-#if _M_X64
-    extern "C" void *amd64_ReturnFromCallWithFakeFrame(void);
-#endif
-
     // Note: noinline is to make sure that when we unwind to the unwindToAddress, there is at least one frame to unwind.
     _NOINLINE
     JavascriptStackWalker::JavascriptStackWalker(ScriptContext * scriptContext, bool useEERContext, PVOID returnAddress, bool _forceFullWalk /*=false*/) :
@@ -979,7 +975,7 @@ namespace Js
         {
             return inlinedFrameWalker.GetFunctionObject();
         }
-        else 
+        else
 #endif
             if (this->isNativeLibraryFrame)
         {
@@ -1195,7 +1191,7 @@ namespace Js
         {
             Assert(stackWalker->GetCachedInternalFrameInfo().codeAddress != nullptr);
             InternalFrameInfo lastInternalFrameInfo = stackWalker->GetCachedInternalFrameInfo();
-            
+
             nativeCodeAddress = lastInternalFrameInfo.codeAddress;
             framePointer = lastInternalFrameInfo.framePointer;
         }
@@ -1429,12 +1425,12 @@ namespace Js
         this->frameCount     = frameCount;
         this->currentIndex   = -1;
     }
-    
+
     InlinedFrameWalker::InlinedFrame* InlinedFrameWalker::InlinedFrame::FromPhysicalFrame(StackFrame& currentFrame, const JavascriptStackWalker * const stackWalker, void *entry, EntryPointInfo* entryPointInfo, bool useInternalFrameInfo)
     {
         // If the current javascript frame is a native frame, get the inlined frame from it, otherwise
         // it may be possible that current frame is the interpreter frame for a jitted loop body
-        // If the loop body had some inlinees in it, retrieve the inlined frame using the cached info, 
+        // If the loop body had some inlinees in it, retrieve the inlined frame using the cached info,
         // viz. instruction pointer, frame pointer, and stackCheckCodeHeight, about the loop body frame.
         struct InlinedFrame *inlinedFrame = nullptr;
         void *codeAddr, *framePointer;
@@ -1470,7 +1466,7 @@ namespace Js
         bool hasInlinedFramesOnStack,
         bool previousInterpreterFrameIsFromBailout)
     {
-        // We skip a jitted loop body's native frame when walking the stack and refer to the loop body's interpreter frame to get the function. 
+        // We skip a jitted loop body's native frame when walking the stack and refer to the loop body's interpreter frame to get the function.
         // However, if the loop body has inlinees, to retrieve inlinee frames we need to cache some info about the loop body's native frame.
         this->codeAddress = codeAddress;
         this->framePointer = framePointer;

+ 7 - 11
lib/Runtime/Language/amd64/JavascriptOperatorsA.S

@@ -14,20 +14,13 @@
         // rsi      = original frame pointer.
         // rdi      = target.
 .balign 16
-.text
-C_FUNC(amd64_CallWithFakeFrame):
+NESTED_ENTRY amd64_CallWithFakeFrame, _TEXT, NoHandler
         // xplat-todo: need to have an equivalent function to __chkstk that we can
         // call here to verify that we have enough stack space
 
-        // The stack walker uses this marker to skip this frame.
-        // Note that we use rip-relative addressing here since this
-        // library is shared and therefore the code has to be position independent
-        lea rax, [rip + C_FUNC(amd64_ReturnFromCallWithFakeFrame)]
-        mov [rsp+8h], rax
-
         mov rax, r8             // arg0
 
-        push rbp
+        push_nonvol_reg rbp
         mov rbp, rsi
 
         // Frame spill size.
@@ -59,9 +52,11 @@ C_FUNC(amd64_CallWithFakeFrame):
 
         // rcx = args size.
         // rdx = spill size.
+NESTED_END amd64_CallWithFakeFrame, _TEXT
+
 
 .balign 16
-C_FUNC(amd64_ReturnFromCallWithFakeFrame):
+NESTED_ENTRY amd64_ReturnFromCallWithFakeFrame, _TEXT, NoHandler
         add  rsp, rcx
 
         pop  rbx
@@ -84,7 +79,8 @@ C_FUNC(amd64_ReturnFromCallWithFakeFrame):
 
         add  rsp, rdx
 
-        pop  rbp
+        pop_nonvol_reg rbp
 
         // Return to the real caller.
         ret
+NESTED_END amd64_ReturnFromCallWithFakeFrame, _TEXT

+ 27 - 58
lib/Runtime/Language/amd64/amd64_Thunks.S

@@ -118,47 +118,31 @@ NESTED_END _ZN2Js18DynamicProfileInfo29EnsureDynamicProfileInfoThunkEPNS_16Recyc
 #endif // _ENABLE_DYNAMIC_THUNKS
 
 
-#ifdef ENABLE_SCRIPT_PROFILING
-
 //============================================================================================================
 // ScriptContext::ProfileModeDeferredParsingThunk
 //============================================================================================================
 
-// Js::JavascriptMethod ScriptContext::ProfileModeDeferredParse(ScriptFunction *function)
-extrn ?ProfileModeDeferredParse@ScriptContext@Js@@SAP6APEAXPEAVRecyclableObject@2@UCallInfo@2@ZZPEAPEAVScriptFunction@2@@Z : PROC
+// Js::JavascriptMethod ScriptContext::ProfileModeDeferredParse(ScriptFunction **function)
+// extrn C_FUNC(_ZN2Js13ScriptContext31ProfileModeDeferredParsingThunkEPNS_16RecyclableObjectENS_8CallInfoEz)
 
 // Var ScriptContext::ProfileModeDeferredParsingThunk(RecyclableObject* function, CallInfo callInfo, ...)
-align 16
-?ProfileModeDeferredParsingThunk@ScriptContext@Js@@SAPEAXPEAVRecyclableObject@2@UCallInfo@2@ZZ PROC FRAME
-        // save volatile registers
-        mov qword ptr [rsp + 8h],  rcx
-        mov qword ptr [rsp + 10h], rdx
-        mov qword ptr [rsp + 18h], r8
-        mov qword ptr [rsp + 20h], r9
-
-        push rbp
-        .pushreg rbp
+.balign 16
+NESTED_ENTRY _ZN2Js13ScriptContext31ProfileModeDeferredParsingThunkEPNS_16RecyclableObjectENS_8CallInfoEz, _TEXT, NoHandler
+        push_nonvol_reg rbp
         lea  rbp, [rsp]
-        .setframe rbp, 0
-        .endprolog
 
-        sub rsp, 20h
-        lea rcx, [rsp + 30h]
-        call C_FUNC(?ProfileModeDeferredParse@ScriptContext@Js@@SAP6APEAXPEAVRecyclableObject@2@UCallInfo@2@ZZPEAPEAVScriptFunction@2@@Z)
-
-        add rsp, 20h
+        // save argument registers used by custom calling convention
+        push_register rdi
+        push_register rsi
 
-        lea rsp, [rbp]
-        pop rbp
+        call C_FUNC(_ZN2Js13ScriptContext24ProfileModeDeferredParseEPPNS_14ScriptFunctionE)
 
-        // restore volatile registers
-        mov rcx, qword ptr [rsp + 8h]
-        mov rdx, qword ptr [rsp + 10h]
-        mov r8,  qword ptr [rsp + 18h]
-        mov r9,  qword ptr [rsp + 20h]
+        pop_register rsi
+        pop_register rdi
 
-        rex_jmp_reg rax
-?ProfileModeDeferredParsingThunk@ScriptContext@Js@@SAPEAXPEAVRecyclableObject@2@UCallInfo@2@ZZ ENDP
+        pop_nonvol_reg rbp
+        jmp rax
+NESTED_END _ZN2Js13ScriptContext31ProfileModeDeferredParsingThunkEPNS_16RecyclableObjectENS_8CallInfoEz, _TEXT
 
 //============================================================================================================
 
@@ -168,41 +152,26 @@ align 16
 //============================================================================================================
 
 // Js::JavascriptMethod ScriptContext::ProfileModeDeferredDeserialize(ScriptFunction *function)
-extrn ?ProfileModeDeferredDeserialize@ScriptContext@Js@@SAP6APEAXPEAVRecyclableObject@2@UCallInfo@2@ZZPEAVScriptFunction@2@@Z : PROC
+// extrn ?ProfileModeDeferredDeserialize@ScriptContext@Js@@SAP6APEAXPEAVRecyclableObject@2@UCallInfo@2@ZZPEAVScriptFunction@2@@Z : PROC
 
 // Var ScriptContext::ProfileModeDeferredDeserializeThunk(RecyclableObject* function, CallInfo callInfo, ...)
-align 16
-?ProfileModeDeferredDeserializeThunk@ScriptContext@Js@@SAPEAXPEAVRecyclableObject@2@UCallInfo@2@ZZ PROC FRAME
-        // save volatile registers
-        mov qword ptr [rsp + 8h],  rcx
-        mov qword ptr [rsp + 10h], rdx
-        mov qword ptr [rsp + 18h], r8
-        mov qword ptr [rsp + 20h], r9
-
-        push rbp
-        .pushreg rbp
+.balign 16
+NESTED_ENTRY _ZN2Js13ScriptContext35ProfileModeDeferredDeserializeThunkEPNS_16RecyclableObjectENS_8CallInfoEz, _TEXT, NoHandler
+        push_nonvol_reg rbp
         lea  rbp, [rsp]
-        .setframe rbp, 0
-        .endprolog
-
-        sub rsp, 20h
-        call C_FUNC(?ProfileModeDeferredDeserialize@ScriptContext@Js@@SAP6APEAXPEAVRecyclableObject@2@UCallInfo@2@ZZPEAVScriptFunction@2@@Z)
-
-        add rsp, 20h
 
-        lea rsp, [rbp]
-        pop rbp
+        // save argument registers used by custom calling convention
+        push_register rdi
+        push_register rsi
 
-        // restore volatile registers
-        mov rcx, qword ptr [rsp + 8h]
-        mov rdx, qword ptr [rsp + 10h]
-        mov r8,  qword ptr [rsp + 18h]
-        mov r9,  qword ptr [rsp + 20h]
+        call C_FUNC(_ZN2Js13ScriptContext30ProfileModeDeferredDeserializeEPNS_14ScriptFunctionE)
 
-        rex_jmp_reg rax
-?ProfileModeDeferredDeserializeThunk@ScriptContext@Js@@SAPEAXPEAVRecyclableObject@2@UCallInfo@2@ZZ ENDP
+        pop_register rsi
+        pop_register rdi
 
-#endif // ENABLE_SCRIPT_PROFILING
+        pop_nonvol_reg rbp
+        jmp rax
+NESTED_END _ZN2Js13ScriptContext35ProfileModeDeferredDeserializeThunkEPNS_16RecyclableObjectENS_8CallInfoEz, _TEXT
 
 
 #ifdef _ENABLE_DYNAMIC_THUNKS

+ 8 - 8
lib/Runtime/Library/JavascriptFunction.cpp

@@ -1122,23 +1122,23 @@ namespace Js
 
 #if _M_IX86
 #ifdef ASMJS_PLAT
-    template <> int JavascriptFunction::CallAsmJsFunction<int>(RecyclableObject * function, JavascriptMethod entryPoint, uint argc, Var * argv) 
+    template <> int JavascriptFunction::CallAsmJsFunction<int>(RecyclableObject * function, JavascriptMethod entryPoint, uint argc, Var * argv)
     {
         return CallAsmJsFunctionX86Thunk(function, entryPoint, argc, argv).retIntVal;
     }
-    template <> int64 JavascriptFunction::CallAsmJsFunction<int64>(RecyclableObject * function, JavascriptMethod entryPoint, uint argc, Var * argv) 
+    template <> int64 JavascriptFunction::CallAsmJsFunction<int64>(RecyclableObject * function, JavascriptMethod entryPoint, uint argc, Var * argv)
     {
         return CallAsmJsFunctionX86Thunk(function, entryPoint, argc, argv).retInt64Val;
     }
-    template <> float JavascriptFunction::CallAsmJsFunction<float>(RecyclableObject * function, JavascriptMethod entryPoint, uint argc, Var * argv) 
+    template <> float JavascriptFunction::CallAsmJsFunction<float>(RecyclableObject * function, JavascriptMethod entryPoint, uint argc, Var * argv)
     {
         return CallAsmJsFunctionX86Thunk(function, entryPoint, argc, argv).retFloatVal;
     }
-    template <> double JavascriptFunction::CallAsmJsFunction<double>(RecyclableObject * function, JavascriptMethod entryPoint, uint argc, Var * argv) 
+    template <> double JavascriptFunction::CallAsmJsFunction<double>(RecyclableObject * function, JavascriptMethod entryPoint, uint argc, Var * argv)
     {
         return CallAsmJsFunctionX86Thunk(function, entryPoint, argc, argv).retDoubleVal;
     }
-    template <> AsmJsSIMDValue JavascriptFunction::CallAsmJsFunction<AsmJsSIMDValue>(RecyclableObject * function, JavascriptMethod entryPoint, uint argc, Var * argv) 
+    template <> AsmJsSIMDValue JavascriptFunction::CallAsmJsFunction<AsmJsSIMDValue>(RecyclableObject * function, JavascriptMethod entryPoint, uint argc, Var * argv)
     {
         return CallAsmJsFunctionX86Thunk(function, entryPoint, argc, argv).retSimdVal;
     }
@@ -1149,7 +1149,7 @@ namespace Js
             IsFloat = 1 << AsmJsRetType::Float,
             IsDouble = 1 << AsmJsRetType::Double,
             IsInt64 = 1 << AsmJsRetType::Int64,
-            IsSimd = 
+            IsSimd =
             1 << AsmJsRetType::Int32x4 |
             1 << AsmJsRetType::Bool32x4 |
             1 << AsmJsRetType::Bool16x8 |
@@ -1677,10 +1677,10 @@ LABEL1:
         }
 
         DebugOnly(JavascriptMethod directEntryPoint = funcBody->GetDirectEntryPoint(funcBody->GetDefaultEntryPointInfo()));
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
         Assert(directEntryPoint != DefaultDeferredParsingThunk
             && directEntryPoint != ProfileDeferredParsingThunk);
-#else // !ENABLE_SCRIPT_PROFILING
+#else // !ENABLE_SCRIPT_PROFILING && !ENABLE_SCRIPT_DEBUGGING
         Assert(directEntryPoint != DefaultDeferredParsingThunk);
 #endif
 

+ 2 - 0
lib/Runtime/Library/JavascriptFunction.h

@@ -101,8 +101,10 @@ namespace Js
         Var CallFunction(Arguments args);
         Var CallRootFunction(Arguments args, ScriptContext * scriptContext, bool inScript);
         Var CallRootFunctionInternal(Arguments args, ScriptContext * scriptContext, bool inScript);
+#ifdef ASMJS_PLAT
         template <typename T>
         static T CallAsmJsFunction(RecyclableObject * function, JavascriptMethod entryPoint, uint argc, Var * argv);
+#endif
         static PossibleAsmJsReturnValues CallAsmJsFunctionX86Thunk(RecyclableObject * function, JavascriptMethod entryPoint, uint argc, Var * argv);
         template <bool isConstruct>
         static Var CalloutHelper(RecyclableObject* function, Var thisArg, Var overridingNewTarget, Var argArray, ScriptContext* scriptContext);

+ 1 - 1
lib/Runtime/Library/ScriptFunction.cpp

@@ -287,7 +287,7 @@ namespace Js
 
         // The type has change from the default, it is not share, just use that one.
         JavascriptMethod directEntryPoint = newFunctionInfo->GetDirectEntryPoint(newFunctionInfo->GetDefaultEntryPointInfo());
-#ifdef ENABLE_SCRIPT_PROFILING
+#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
         Assert(directEntryPoint != DefaultDeferredParsingThunk
             && directEntryPoint != ProfileDeferredParsingThunk);
 #else

+ 1 - 1
lib/Runtime/Library/WebAssembly.cpp

@@ -185,4 +185,4 @@ WebAssembly::GetSignatureSize()
 }
 
 }
-#endif // ENABLE_WASM
+#endif // ENABLE_WASM

+ 0 - 2
lib/Runtime/Library/amd64/JavascriptFunctionA.S

@@ -256,8 +256,6 @@ LEAF_ENTRY _ZN2Js18JavascriptFunction17CallAsmJsFunctionIdEET_PNS_16RecyclableOb
 LEAF_END _ZN2Js18JavascriptFunction17CallAsmJsFunctionIdEET_PNS_16RecyclableObjectEPFPvS4_NS_8CallInfoEzEjPS5_, _TEXT
 
 #endif // _ENABLE_DYNAMIC_THUNKS
-
-
 //------------------------------------------------------------------------------
 .balign 16
 NESTED_ENTRY _ZN2Js18JavascriptFunction20DeferredParsingThunkEPNS_16RecyclableObjectENS_8CallInfoEz, _TEXT, NoHandler

+ 1 - 1
lib/Runtime/Runtime.h

@@ -349,7 +349,7 @@ const Js::ModuleID kmodGlobal = 0;
 
 class SourceContextInfo;
 
-#ifdef ENABLE_SCRIPT_DEBUGGING
+#if defined(ENABLE_SCRIPT_DEBUGGING) && defined(_WIN32)
 #include "activdbg100.h"
 #endif
 

+ 11 - 0
test/AsmJs/bugGH2270.js

@@ -0,0 +1,11 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+(function() {
+    "use asm";
+    (function(){});
+})();
+
+print("Pass");

+ 3 - 0
test/AsmJs/rlexe.xml

@@ -813,5 +813,8 @@
       <baseline>vardeclnorhs.baseline</baseline>
       <compile-flags>-testtrace:asmjs -maic:1</compile-flags>
     </default>
+    <default>
+      <files>bugGH2270.js</files>
+    </default>
   </test>
 </regress-exe>

+ 4 - 4
test/Debugger/MultipleContextStack.js

@@ -21,8 +21,8 @@ var script1 = WScript.LoadScript("\
   function Script1Func3() { scriptFunc3(); } \
   function setFunc2(func) { scriptFunc2 = func; } \
   function setFunc3(func) { scriptFunc3 = func; }",
-  "samethread", "Script1.js");
-  
+  "samethread");
+
 var script2 = WScript.LoadScript(" \
   var script1Func2; \
   var script1Func3; \
@@ -31,8 +31,8 @@ var script2 = WScript.LoadScript(" \
   function Script2Func3() { script1Func3(); } \
   function setFunc2(func) { script1Func2 = func; } \
   function setFunc3(func) { script1Func3 = func; }",
-  "samethread", "Script2.js");
-  
+  "samethread");
+
 function Func2() {
   Func1();
 }

+ 2 - 0
test/Debugger/rlexe.xml

@@ -16,6 +16,8 @@
     <default>
       <compile-flags>-debuglaunch -dbgbaseline:JsDiagGetFunctionPosition.js.dbg.baseline</compile-flags>
       <files>JsDiagGetFunctionPosition.js</files>
+      <!-- xplat-todo: enable back [not supported] Intl -->
+      <tags>exclude_xplat</tags>
     </default>
   </test>
   <test>

+ 0 - 0
test/DebuggerCommon/array_protoTest.js.dbg.baseline → test/DebuggerCommon/array_prototest.js.dbg.baseline


+ 16 - 8
test/DebuggerCommon/rlexe.xml

@@ -37,7 +37,8 @@
       <files>ES6_intl_stepinto.js</files>
       <compile-flags>-dbgbaseline:ES6_intl_stepinto.js.dbg.baseline -Intl</compile-flags>
       <baseline>ES6_intl_stepinto.js.baseline</baseline>
-      <tags>fail_mutators,exclude_winglob</tags>
+      <!-- xplat-todo: enable back [intl support] -->
+      <tags>fail_mutators,exclude_winglob,exclude_xplat</tags>
     </default>
   </test>
   <test>
@@ -242,7 +243,8 @@
       <files>ES6_intl_simple_attach.js</files>
       <compile-flags>-dbgbaseline:ES6_intl_simple_attach.js.dbg.baseline -Intl</compile-flags>
       <baseline>ES6_intl_simple_attach.js.baseline</baseline>
-      <tags>fail_mutators,exclude_winglob</tags>
+      <!-- xplat-todo: enable back [intl support] -->
+      <tags>fail_mutators,exclude_winglob,exclude_xplat</tags>
     </default>
   </test>
   <test>
@@ -324,7 +326,8 @@
     <default>
       <files>ES6_intl_stepinto_libexpandos.js</files>
       <compile-flags>-debuglaunch -dbgbaseline:ES6_intl_stepinto_libexpandos.js.dbg.baseline -Intl</compile-flags>
-      <tags>fail_mutators,exclude_winglob</tags>
+      <!-- xplat-todo: enable back [intl support] -->
+      <tags>fail_mutators,exclude_winglob,exclude_xplat</tags>
     </default>
   </test>
   <test>
@@ -513,7 +516,7 @@
   </test>
   <test>
     <default>
-      <files>array_protoTest.js</files>
+      <files>array_prototest.js</files>
       <compile-flags>-debuglaunch -dbgbaseline:array_prototest.js.dbg.baseline</compile-flags>
       <tags>fail_mutators</tags>
     </default>
@@ -571,7 +574,8 @@
     <default>
       <files>attachdetach-delaycapture.js</files>
       <compile-flags>-dbgbaseline:attachdetach-delaycapture.js.dbg.baseline</compile-flags>
-      <tags>BugFix</tags>
+      <!-- xplat-todo: enable back - investigate [background job thread fails] -->
+      <tags>BugFix,exclude_xplat</tags>
     </default>
   </test>
   <test>
@@ -997,7 +1001,7 @@
     </default>
   </test>
   <test>
-    <default>     
+    <default>
       <files>jitAttach.js</files>
       <compile-flags> -maxinterpretcount:1 -off:simpleJit -EnableJitInDiagMode -dbgbaseline:jitAttach.js.dbg.baseline</compile-flags>
       <tags>fail_mutators,exclude_dynapogo</tags>
@@ -1278,14 +1282,16 @@
     <default>
       <files>returnedvaluetests1.js</files>
       <compile-flags>-dbgbaseline:returnedvaluetests1.js.dbg.baseline</compile-flags>
-      <tags>exclude_dynapogo,exclude_serialized</tags>
+      <!-- xplat-todo: enable back [intl support] -->
+      <tags>exclude_dynapogo,exclude_serialized,exclude_xplat</tags>
     </default>
   </test>
   <test>
     <default>
       <files>returnedvaluetests2.js</files>
       <compile-flags>-debugLaunch -dbgbaseline:returnedvaluetests2.js.dbg.baseline</compile-flags>
-      <tags>exclude_dynapogo,exclude_serialized</tags>
+      <!-- xplat-todo: enable back [intl support] -->
+      <tags>exclude_dynapogo,exclude_serialized,exclude_xplat</tags>
     </default>
   </test>
   <test>
@@ -1378,6 +1384,8 @@
     <default>
       <files>TypedArray.js</files>
       <compile-flags>-ES6Species -debuglaunch -dbgbaseline:typedarray.js.dbg.baseline -InspectMaxStringLength:200</compile-flags>
+      <!-- xplat-todo: G.H #2064 -->
+      <tags>exclude_xplat</tags>
     </default>
   </test>
   <test>

+ 1 - 1
test/runtests.py

@@ -123,7 +123,7 @@ not_tags.add('exclude_nightly' if args.nightly else 'nightly')
 if sys.platform != 'win32':
     not_tags.add('exclude_xplat')
     not_tags.add('Intl')
-    not_tags.add('require_debugger')
+
 if sys.platform == 'darwin':
     not_tags.add('exclude_mac')
 not_compile_flags = set(['-simdjs']) \