Title: [279976] trunk
Revision
279976
Author
[email protected]
Date
2021-07-15 21:10:49 -0700 (Thu, 15 Jul 2021)

Log Message

[JSC] SamplingProfiler should recognize RegExp execution
https://bugs.webkit.org/show_bug.cgi?id=201702

Reviewed by Saam Barati.

JSTests:

* stress/sampling-profiler-regexp.js: Added.
(platformSupportsSamplingProfiler.getText):
(platformSupportsSamplingProfiler.test):
(platformSupportsSamplingProfiler.baz):
(platformSupportsSamplingProfiler):
* stress/sampling-profiler/samplingProfiler.js: Extend samplingProfiler to show better error information when VERBOSE = true.
(doesTreeHaveStackTrace):

Source/_javascript_Core:

This patch extends SamplingProfiler to recognize RegExp execution. We record
executing RegExp in VM via MatchingContextHolder so that SamplingProfiler can detect it.
We use MatchingContextHolder even if the RegExp is interpreter mode so that we can still
catch non-JIT RegExp in SamplingProfiler.

The example output is the following.

    Sampling rate: 1000.000000 microseconds. Total samples: 1830
    Top functions as <numSamples  'functionName#hash:sourceID'>
       466    'Exec#<nil>:4'
       225    '/(^|[^\\])\"\\\/Qngr\((-?[0-9]+)\)\\\/\"/g#<nil>:-1'
       173    'runBlock1#<nil>:4'
        88    '/NQ_VQ/g#<nil>:-1'
        83    '/d2/g#<nil>:-1'
        78    '/d1/g#<nil>:-1'
        70    '/\s?;\s?/#<nil>:-1'
        68    'replace#<nil>:3'
        50    '/(((\w+):\/\/)([^\/:]*)(:(\d+))?)?([^#?]*)(\?([^#]*))?(#(.*))?/#<nil>:-1'
        49    'runBlock0#<nil>:4'
        46    '#<nil>:-1'
        24    '/^\s*|\s*$/g#<nil>:-1'

    Sampling rate: 1000.000000 microseconds. Total samples: 1830

    Tier breakdown:
    -----------------------------------
    LLInt:                    13  (0.710383%)
    Baseline:                 54  (2.950820%)
    DFG:                     187  (10.218579%)
    FTL:                     612  (33.442623%)
    js builtin:               73  (3.989071%)
    Wasm:                      0  (0.000000%)
    Host:                      0  (0.000000%)
    RegExp:                  907  (49.562842%)
    C/C++:                     0  (0.000000%)
    Unknown Executable:       57  (3.114754%)

    Hottest bytecodes as <numSamples   'functionName#hash:JITType:bytecodeIndex'>
       378    'Exec#<nil>:FTL:bc#27'
       225    '/(^|[^\\])\"\\\/Qngr\((-?[0-9]+)\)\\\/\"/g#<nil>:RegExp:<nil>'
        88    '/NQ_VQ/g#<nil>:RegExp:<nil>'
        83    '/d2/g#<nil>:RegExp:<nil>'
        78    '/d1/g#<nil>:RegExp:<nil>'
        70    '/\s?;\s?/#<nil>:RegExp:<nil>'
        62    'replace#<nil>:FTL:bc#63'
        53    'Exec#<nil>:DFG:bc#27'
        50    '/(((\w+):\/\/)([^\/:]*)(:(\d+))?)?([^#?]*)(\?([^#]*))?(#(.*))?/#<nil>:RegExp:<nil>'
        46    '#<nil>:None:<nil>'
        42    'runBlock1#<nil>:FTL:bc#1795'
        29    'runBlock1#<nil>:FTL:bc#1849'
        29    'runBlock1#<nil>:FTL:bc#1741'
        24    '/^\s*|\s*$/g#<nil>:RegExp:<nil>'
        17    'runBlock1#<nil>:DFG:bc#1741'
        17    'runBlock1#<nil>:DFG:bc#1795'
        16    '/\b\w+\b/g#<nil>:RegExp:<nil>'
        14    '/TNQP=([^;]*)/i#<nil>:RegExp:<nil>'
        13    '/%\w?$/#<nil>:RegExp:<nil>'
        12    '/^ba/#<nil>:RegExp:<nil>'
        11    '/^\s*(\S*(\s+\S+)*)\s*$/#<nil>:RegExp:<nil>'
        10    'runBlock0#<nil>:FTL:bc#400'
        10    'runBlock1#<nil>:DFG:bc#1849'
        10    'Exec#<nil>:DFG:bc#16'
         9    '/(?:ZFVR.(\d+\.\d+))|(?:(?:Sversbk|TenaCnenqvfb|Vprjrnfry).(\d+\.\d+))|(?:Bcren.(\d+\.\d+))|(?:NccyrJroXvg.(\d+(?:\.\d+)?))/#<nil>:RegExp:<nil>'
         8    '/##yv18##/gi#<nil>:RegExp:<nil>'
         8    '/([a-zA-Z]|\s)+/#<nil>:RegExp:<nil>'
         7    '/JroXvg\/(\S+)/#<nil>:RegExp:<nil>'
         7    'runBlock0#<nil>:FTL:bc#2671'
         7    '/^([#.]?)((?:[\w\u0128-\uffff*_-]|\\.)*)/#<nil>:RegExp:<nil>'
         6    '/##oe##/gi#<nil>:RegExp:<nil>'
         6    'runBlock1#<nil>:FTL:bc#124'
         6    '/[+, ]/#<nil>:RegExp:<nil>'
         6    'runBlock1#<nil>:FTL:bc#1903'
         6    'replace#<nil>:DFG:bc#63'
         5    'runBlock0#<nil>:FTL:bc#3378'
         5    '/'/g#<nil>:RegExp:<nil>'
         5    '/##yv20##/gi#<nil>:RegExp:<nil>'
         4    '/\?[\w\W]*(sevraqvq|punaaryvq|tebhcvq)=([^\&\?#]*)/i#<nil>:RegExp:<nil>'
         4    'load#<nil>:None:<nil>'

* CMakeLists.txt:
* _javascript_Core.xcodeproj/project.pbxproj:
* runtime/RegExp.cpp:
(JSC::RegExp::matchCompareWithInterpreter):
(JSC::RegExp::dumpToStream):
(JSC::appendLineTerminatorEscape<LChar>):
(JSC::appendLineTerminatorEscape<UChar>):
(JSC::escapePattern):
(JSC::RegExp::escapedPattern const): Moved from RegExpPrototype.cpp to implement RegExp::toSourceString and RegExp::escapedPattern.
(JSC::RegExp::toSourceString const):
(JSC::regexpToSourceString): Deleted.
* runtime/RegExp.h:
* runtime/RegExpInlines.h:
(JSC::RegExp::matchInline):
* runtime/RegExpPrototype.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::appendLineTerminatorEscape<LChar>): Deleted.
(JSC::appendLineTerminatorEscape<UChar>): Deleted.
(JSC::regExpProtoGetterSourceInternal): Deleted.
* runtime/SamplingProfiler.cpp:
(JSC::SamplingProfiler::takeSample):
(JSC::SamplingProfiler::processUnverifiedStackTraces):
(JSC::SamplingProfiler::StackFrame::nameFromCallee):
(JSC::SamplingProfiler::StackFrame::displayName):
(JSC::SamplingProfiler::StackFrame::displayNameForJSONTests):
(JSC::SamplingProfiler::StackFrame::functionStartLine):
(JSC::SamplingProfiler::StackFrame::functionStartColumn):
(JSC::SamplingProfiler::StackFrame::sourceID):
(JSC::SamplingProfiler::StackFrame::url):
(JSC::SamplingProfiler::reportTopBytecodes):
(WTF::printInternal):
* runtime/SamplingProfiler.h:
* runtime/VM.h:
* yarr/YarrJIT.cpp:
(JSC::Yarr::MatchingContextHolder::MatchingContextHolder): Deleted.
(JSC::Yarr::MatchingContextHolder::~MatchingContextHolder): Deleted.
* yarr/YarrJIT.h:
(JSC::Yarr::MatchingContextHolder::offsetOfStackLimit): Deleted.
(JSC::Yarr::MatchingContextHolder::offsetOfPatternContextBuffer): Deleted.
(JSC::Yarr::MatchingContextHolder::offsetOfPatternContextBufferSize): Deleted.
* yarr/YarrMatchingContextHolder.h: Added.
(JSC::Yarr::MatchingContextHolder::offsetOfStackLimit):
(JSC::Yarr::MatchingContextHolder::offsetOfPatternContextBuffer):
(JSC::Yarr::MatchingContextHolder::offsetOfPatternContextBufferSize):
(JSC::Yarr::MatchingContextHolder::MatchingContextHolder):
(JSC::Yarr::MatchingContextHolder::~MatchingContextHolder):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (279975 => 279976)


--- trunk/JSTests/ChangeLog	2021-07-16 04:01:38 UTC (rev 279975)
+++ trunk/JSTests/ChangeLog	2021-07-16 04:10:49 UTC (rev 279976)
@@ -1,5 +1,20 @@
 2021-07-15  Yusuke Suzuki  <[email protected]>
 
+        [JSC] SamplingProfiler should recognize RegExp execution
+        https://bugs.webkit.org/show_bug.cgi?id=201702
+
+        Reviewed by Saam Barati.
+
+        * stress/sampling-profiler-regexp.js: Added.
+        (platformSupportsSamplingProfiler.getText):
+        (platformSupportsSamplingProfiler.test):
+        (platformSupportsSamplingProfiler.baz):
+        (platformSupportsSamplingProfiler):
+        * stress/sampling-profiler/samplingProfiler.js: Extend samplingProfiler to show better error information when VERBOSE = true.
+        (doesTreeHaveStackTrace):
+
+2021-07-15  Yusuke Suzuki  <[email protected]>
+
         [JSC] Harden defaultTimeZone retrieval
         https://bugs.webkit.org/show_bug.cgi?id=227996
 

Modified: trunk/JSTests/stress/sampling-profiler/samplingProfiler.js (279975 => 279976)


--- trunk/JSTests/stress/sampling-profiler/samplingProfiler.js	2021-07-16 04:01:38 UTC (rev 279975)
+++ trunk/JSTests/stress/sampling-profiler/samplingProfiler.js	2021-07-16 04:10:49 UTC (rev 279976)
@@ -34,7 +34,9 @@
     }
 }
 
-function doesTreeHaveStackTrace(tree, stackTrace, isRunFromRunTest = true, verbose = false) {
+const VERBOSE = false;
+
+function doesTreeHaveStackTrace(tree, stackTrace, isRunFromRunTest = true) {
     // stack trace should be top-down array with the deepest
     // call frame at index 0.
     if (isRunFromRunTest)
@@ -46,8 +48,10 @@
     for (let i = stackTrace.length; i--; ) {
         node = node.children[stackTrace[i]];
         if (!node) {
-            if (verbose)
+            if (VERBOSE) {
                 print("failing on " + i + " : " + stackTrace[i]);
+                print(JSON.stringify(tree));
+            }
             return false;
         }
     }
@@ -60,7 +64,6 @@
     return root;
 }
 
-const VERBOSE = false;
 // This test suite assumes that "runTest" is being called
 // from the global scope.
 function runTest(func, stackTrace) {

Added: trunk/JSTests/stress/sampling-profiler-regexp.js (0 => 279976)


--- trunk/JSTests/stress/sampling-profiler-regexp.js	                        (rev 0)
+++ trunk/JSTests/stress/sampling-profiler-regexp.js	2021-07-16 04:10:49 UTC (rev 279976)
@@ -0,0 +1,24 @@
+if (platformSupportsSamplingProfiler()) {
+    load("./sampling-profiler/samplingProfiler.js");
+
+    var text = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`.repeat(1000);
+    function getText()
+    {
+        return text;
+    }
+    noInline(getText);
+
+    function test(regexp)
+    {
+        return getText().match(regexp);
+    }
+    noInline(test);
+
+    function baz() {
+        var regexp = /(.+)/gi;
+        for (var i = 0; i < 1e1; ++i)
+            test(regexp);
+    }
+
+    runTest(baz, ["/(.+)/gi", "", "test", "baz"]);
+}

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (279975 => 279976)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2021-07-16 04:01:38 UTC (rev 279975)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2021-07-16 04:10:49 UTC (rev 279976)
@@ -1160,6 +1160,7 @@
     yarr/YarrFlags.h
     yarr/YarrInterpreter.h
     yarr/YarrJIT.h
+    yarr/YarrMatchingContextHolder.h
     yarr/YarrParser.h
     yarr/YarrPattern.h
     yarr/YarrUnicodeProperties.h

Modified: trunk/Source/_javascript_Core/ChangeLog (279975 => 279976)


--- trunk/Source/_javascript_Core/ChangeLog	2021-07-16 04:01:38 UTC (rev 279975)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-07-16 04:10:49 UTC (rev 279976)
@@ -1,5 +1,140 @@
 2021-07-15  Yusuke Suzuki  <[email protected]>
 
+        [JSC] SamplingProfiler should recognize RegExp execution
+        https://bugs.webkit.org/show_bug.cgi?id=201702
+
+        Reviewed by Saam Barati.
+
+        This patch extends SamplingProfiler to recognize RegExp execution. We record
+        executing RegExp in VM via MatchingContextHolder so that SamplingProfiler can detect it.
+        We use MatchingContextHolder even if the RegExp is interpreter mode so that we can still
+        catch non-JIT RegExp in SamplingProfiler.
+
+        The example output is the following.
+
+            Sampling rate: 1000.000000 microseconds. Total samples: 1830
+            Top functions as <numSamples  'functionName#hash:sourceID'>
+               466    'Exec#<nil>:4'
+               225    '/(^|[^\\])\"\\\/Qngr\((-?[0-9]+)\)\\\/\"/g#<nil>:-1'
+               173    'runBlock1#<nil>:4'
+                88    '/NQ_VQ/g#<nil>:-1'
+                83    '/d2/g#<nil>:-1'
+                78    '/d1/g#<nil>:-1'
+                70    '/\s?;\s?/#<nil>:-1'
+                68    'replace#<nil>:3'
+                50    '/(((\w+):\/\/)([^\/:]*)(:(\d+))?)?([^#?]*)(\?([^#]*))?(#(.*))?/#<nil>:-1'
+                49    'runBlock0#<nil>:4'
+                46    '#<nil>:-1'
+                24    '/^\s*|\s*$/g#<nil>:-1'
+
+
+            Sampling rate: 1000.000000 microseconds. Total samples: 1830
+
+            Tier breakdown:
+            -----------------------------------
+            LLInt:                    13  (0.710383%)
+            Baseline:                 54  (2.950820%)
+            DFG:                     187  (10.218579%)
+            FTL:                     612  (33.442623%)
+            js builtin:               73  (3.989071%)
+            Wasm:                      0  (0.000000%)
+            Host:                      0  (0.000000%)
+            RegExp:                  907  (49.562842%)
+            C/C++:                     0  (0.000000%)
+            Unknown Executable:       57  (3.114754%)
+
+
+            Hottest bytecodes as <numSamples   'functionName#hash:JITType:bytecodeIndex'>
+               378    'Exec#<nil>:FTL:bc#27'
+               225    '/(^|[^\\])\"\\\/Qngr\((-?[0-9]+)\)\\\/\"/g#<nil>:RegExp:<nil>'
+                88    '/NQ_VQ/g#<nil>:RegExp:<nil>'
+                83    '/d2/g#<nil>:RegExp:<nil>'
+                78    '/d1/g#<nil>:RegExp:<nil>'
+                70    '/\s?;\s?/#<nil>:RegExp:<nil>'
+                62    'replace#<nil>:FTL:bc#63'
+                53    'Exec#<nil>:DFG:bc#27'
+                50    '/(((\w+):\/\/)([^\/:]*)(:(\d+))?)?([^#?]*)(\?([^#]*))?(#(.*))?/#<nil>:RegExp:<nil>'
+                46    '#<nil>:None:<nil>'
+                42    'runBlock1#<nil>:FTL:bc#1795'
+                29    'runBlock1#<nil>:FTL:bc#1849'
+                29    'runBlock1#<nil>:FTL:bc#1741'
+                24    '/^\s*|\s*$/g#<nil>:RegExp:<nil>'
+                17    'runBlock1#<nil>:DFG:bc#1741'
+                17    'runBlock1#<nil>:DFG:bc#1795'
+                16    '/\b\w+\b/g#<nil>:RegExp:<nil>'
+                14    '/TNQP=([^;]*)/i#<nil>:RegExp:<nil>'
+                13    '/%\w?$/#<nil>:RegExp:<nil>'
+                12    '/^ba/#<nil>:RegExp:<nil>'
+                11    '/^\s*(\S*(\s+\S+)*)\s*$/#<nil>:RegExp:<nil>'
+                10    'runBlock0#<nil>:FTL:bc#400'
+                10    'runBlock1#<nil>:DFG:bc#1849'
+                10    'Exec#<nil>:DFG:bc#16'
+                 9    '/(?:ZFVR.(\d+\.\d+))|(?:(?:Sversbk|TenaCnenqvfb|Vprjrnfry).(\d+\.\d+))|(?:Bcren.(\d+\.\d+))|(?:NccyrJroXvg.(\d+(?:\.\d+)?))/#<nil>:RegExp:<nil>'
+                 8    '/##yv18##/gi#<nil>:RegExp:<nil>'
+                 8    '/([a-zA-Z]|\s)+/#<nil>:RegExp:<nil>'
+                 7    '/JroXvg\/(\S+)/#<nil>:RegExp:<nil>'
+                 7    'runBlock0#<nil>:FTL:bc#2671'
+                 7    '/^([#.]?)((?:[\w\u0128-\uffff*_-]|\\.)*)/#<nil>:RegExp:<nil>'
+                 6    '/##oe##/gi#<nil>:RegExp:<nil>'
+                 6    'runBlock1#<nil>:FTL:bc#124'
+                 6    '/[+, ]/#<nil>:RegExp:<nil>'
+                 6    'runBlock1#<nil>:FTL:bc#1903'
+                 6    'replace#<nil>:DFG:bc#63'
+                 5    'runBlock0#<nil>:FTL:bc#3378'
+                 5    '/'/g#<nil>:RegExp:<nil>'
+                 5    '/##yv20##/gi#<nil>:RegExp:<nil>'
+                 4    '/\?[\w\W]*(sevraqvq|punaaryvq|tebhcvq)=([^\&\?#]*)/i#<nil>:RegExp:<nil>'
+                 4    'load#<nil>:None:<nil>'
+
+        * CMakeLists.txt:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * runtime/RegExp.cpp:
+        (JSC::RegExp::matchCompareWithInterpreter):
+        (JSC::RegExp::dumpToStream):
+        (JSC::appendLineTerminatorEscape<LChar>):
+        (JSC::appendLineTerminatorEscape<UChar>):
+        (JSC::escapePattern):
+        (JSC::RegExp::escapedPattern const): Moved from RegExpPrototype.cpp to implement RegExp::toSourceString and RegExp::escapedPattern.
+        (JSC::RegExp::toSourceString const):
+        (JSC::regexpToSourceString): Deleted.
+        * runtime/RegExp.h:
+        * runtime/RegExpInlines.h:
+        (JSC::RegExp::matchInline):
+        * runtime/RegExpPrototype.cpp:
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+        (JSC::appendLineTerminatorEscape<LChar>): Deleted.
+        (JSC::appendLineTerminatorEscape<UChar>): Deleted.
+        (JSC::regExpProtoGetterSourceInternal): Deleted.
+        * runtime/SamplingProfiler.cpp:
+        (JSC::SamplingProfiler::takeSample):
+        (JSC::SamplingProfiler::processUnverifiedStackTraces):
+        (JSC::SamplingProfiler::StackFrame::nameFromCallee):
+        (JSC::SamplingProfiler::StackFrame::displayName):
+        (JSC::SamplingProfiler::StackFrame::displayNameForJSONTests):
+        (JSC::SamplingProfiler::StackFrame::functionStartLine):
+        (JSC::SamplingProfiler::StackFrame::functionStartColumn):
+        (JSC::SamplingProfiler::StackFrame::sourceID):
+        (JSC::SamplingProfiler::StackFrame::url):
+        (JSC::SamplingProfiler::reportTopBytecodes):
+        (WTF::printInternal):
+        * runtime/SamplingProfiler.h:
+        * runtime/VM.h:
+        * yarr/YarrJIT.cpp:
+        (JSC::Yarr::MatchingContextHolder::MatchingContextHolder): Deleted.
+        (JSC::Yarr::MatchingContextHolder::~MatchingContextHolder): Deleted.
+        * yarr/YarrJIT.h:
+        (JSC::Yarr::MatchingContextHolder::offsetOfStackLimit): Deleted.
+        (JSC::Yarr::MatchingContextHolder::offsetOfPatternContextBuffer): Deleted.
+        (JSC::Yarr::MatchingContextHolder::offsetOfPatternContextBufferSize): Deleted.
+        * yarr/YarrMatchingContextHolder.h: Added.
+        (JSC::Yarr::MatchingContextHolder::offsetOfStackLimit):
+        (JSC::Yarr::MatchingContextHolder::offsetOfPatternContextBuffer):
+        (JSC::Yarr::MatchingContextHolder::offsetOfPatternContextBufferSize):
+        (JSC::Yarr::MatchingContextHolder::MatchingContextHolder):
+        (JSC::Yarr::MatchingContextHolder::~MatchingContextHolder):
+
+2021-07-15  Yusuke Suzuki  <[email protected]>
+
         [JSC] Harden defaultTimeZone retrieval
         https://bugs.webkit.org/show_bug.cgi?id=227996
         rdar://80540300

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (279975 => 279976)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2021-07-16 04:01:38 UTC (rev 279975)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2021-07-16 04:10:49 UTC (rev 279976)
@@ -1929,6 +1929,7 @@
 		E3D3515F241B89D7008DC16E /* MarkedJSValueRefArray.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D3515D241B89CE008DC16E /* MarkedJSValueRefArray.h */; };
 		E3D877741E65C0A000BE945A /* BytecodeDumper.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D877721E65C08900BE945A /* BytecodeDumper.h */; };
 		E3EE137621FBD43500D83C4B /* ErrorType.h in Headers */ = {isa = PBXBuildFile; fileRef = E3EE137421FBD43400D83C4B /* ErrorType.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		E3F0FC9526A11B4A0099FFA0 /* YarrMatchingContextHolder.h in Headers */ = {isa = PBXBuildFile; fileRef = E3F0FC9426A11B4A0099FFA0 /* YarrMatchingContextHolder.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E3F2193724C7882F003AE453 /* IntlSegmentIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E3F2193124C78829003AE453 /* IntlSegmentIterator.h */; };
 		E3F2193824C78831003AE453 /* IntlSegmentIteratorPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = E3F2192F24C78829003AE453 /* IntlSegmentIteratorPrototype.h */; };
 		E3F2193924C78834003AE453 /* IntlSegments.h in Headers */ = {isa = PBXBuildFile; fileRef = E3F2193324C7882A003AE453 /* IntlSegments.h */; };
@@ -5230,6 +5231,7 @@
 		E3E9F8D525D7582F00F9F84B /* process-entitlements.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "process-entitlements.sh"; sourceTree = "<group>"; };
 		E3EE137421FBD43400D83C4B /* ErrorType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErrorType.h; sourceTree = "<group>"; };
 		E3EE137521FBD43400D83C4B /* ErrorType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErrorType.cpp; sourceTree = "<group>"; };
+		E3F0FC9426A11B4A0099FFA0 /* YarrMatchingContextHolder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrMatchingContextHolder.h; path = yarr/YarrMatchingContextHolder.h; sourceTree = "<group>"; };
 		E3F2192F24C78829003AE453 /* IntlSegmentIteratorPrototype.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IntlSegmentIteratorPrototype.h; sourceTree = "<group>"; };
 		E3F2193024C78829003AE453 /* IntlSegmentIterator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = IntlSegmentIterator.cpp; sourceTree = "<group>"; };
 		E3F2193124C78829003AE453 /* IntlSegmentIterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IntlSegmentIterator.h; sourceTree = "<group>"; };
@@ -8081,6 +8083,7 @@
 				86704B7E12DBA33700A9FE7B /* YarrInterpreter.h */,
 				86704B7F12DBA33700A9FE7B /* YarrJIT.cpp */,
 				86704B8012DBA33700A9FE7B /* YarrJIT.h */,
+				E3F0FC9426A11B4A0099FFA0 /* YarrMatchingContextHolder.h */,
 				86704B8112DBA33700A9FE7B /* YarrParser.h */,
 				86704B8212DBA33700A9FE7B /* YarrPattern.cpp */,
 				86704B8312DBA33700A9FE7B /* YarrPattern.h */,
@@ -10843,6 +10846,7 @@
 				A3FF9BC72234749100B1A9AB /* YarrFlags.h in Headers */,
 				86704B8512DBA33700A9FE7B /* YarrInterpreter.h in Headers */,
 				86704B8712DBA33700A9FE7B /* YarrJIT.h in Headers */,
+				E3F0FC9526A11B4A0099FFA0 /* YarrMatchingContextHolder.h in Headers */,
 				86704B8812DBA33700A9FE7B /* YarrParser.h in Headers */,
 				86704B8A12DBA33700A9FE7B /* YarrPattern.h in Headers */,
 				86704B4312DB8A8100A9FE7B /* YarrSyntaxChecker.h in Headers */,

Modified: trunk/Source/_javascript_Core/runtime/RegExp.cpp (279975 => 279976)


--- trunk/Source/_javascript_Core/runtime/RegExp.cpp	2021-07-16 04:01:38 UTC (rev 279975)
+++ trunk/Source/_javascript_Core/runtime/RegExp.cpp	2021-07-16 04:10:49 UTC (rev 279976)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2001, 2004 Harri Porten ([email protected])
- *  Copyright (c) 2007-2020 Apple Inc. All rights reserved.
+ *  Copyright (c) 2007-2021 Apple Inc. All rights reserved.
  *  Copyright (C) 2009 Torch Mobile, Inc.
  *  Copyright (C) 2010 Peter Varga ([email protected]), University of Szeged
  *
@@ -23,6 +23,7 @@
 #include "config.h"
 #include "RegExp.h"
 
+#include "Lexer.h"
 #include "RegExpCache.h"
 #include "RegExpInlines.h"
 #include "YarrJIT.h"
@@ -392,7 +393,7 @@
             differences++;
 
     if (differences) {
-        dataLogF("RegExp Discrepency for /%s/\n    string input ", pattern().utf8().data());
+        dataLog("RegExp Discrepency for ", toSourceString(), "\n    string input ");
         unsigned segmentLen = s.length() - static_cast<unsigned>(startOffset);
 
         dataLogF((segmentLen < 150) ? "\"%s\"\n" : "\"%148s...\"\n", s.utf8().data() + startOffset);
@@ -468,14 +469,127 @@
     }
 #endif
 
-static CString regexpToSourceString(const RegExp* regExp)
+void RegExp::dumpToStream(const JSCell* cell, PrintStream& out)
 {
-    return toCString("/", regExp->pattern().impl(), "/", Yarr::flagsString(regExp->flags()).data());
+    out.print(jsCast<const RegExp*>(cell)->toSourceString());
 }
 
-void RegExp::dumpToStream(const JSCell* cell, PrintStream& out)
+template <typename CharacterType>
+static inline void appendLineTerminatorEscape(StringBuilder&, CharacterType);
+
+template <>
+inline void appendLineTerminatorEscape<LChar>(StringBuilder& builder, LChar lineTerminator)
 {
-    out.print(regexpToSourceString(jsCast<const RegExp*>(cell)));
+    if (lineTerminator == '\n')
+        builder.append('n');
+    else
+        builder.append('r');
 }
 
+template <>
+inline void appendLineTerminatorEscape<UChar>(StringBuilder& builder, UChar lineTerminator)
+{
+    if (lineTerminator == '\n')
+        builder.append('n');
+    else if (lineTerminator == '\r')
+        builder.append('r');
+    else if (lineTerminator == 0x2028)
+        builder.append("u2028");
+    else
+        builder.append("u2029");
+}
+
+template <typename CharacterType>
+static inline String escapePattern(const String& pattern, const CharacterType* characters, unsigned length)
+{
+    bool previousCharacterWasBackslash = false;
+    bool inBrackets = false;
+    bool shouldEscape = false;
+
+    // 15.10.6.4 specifies that RegExp.prototype.toString must return '/' + source + '/',
+    // and also states that the result must be a valid RegularExpressionLiteral. '//' is
+    // not a valid RegularExpressionLiteral (since it is a single line comment), and hence
+    // source cannot ever validly be "". If the source is empty, return a different Pattern
+    // that would match the same thing.
+    if (!length)
+        return "(?:)"_s;
+
+    // early return for strings that don't contain a forwards slash and LineTerminator
+    for (unsigned i = 0; i < length; ++i) {
+        CharacterType ch = characters[i];
+        if (!previousCharacterWasBackslash) {
+            if (inBrackets) {
+                if (ch == ']')
+                    inBrackets = false;
+            } else {
+                if (ch == '/') {
+                    shouldEscape = true;
+                    break;
+                }
+                if (ch == '[')
+                    inBrackets = true;
+            }
+        }
+
+        if (Lexer<CharacterType>::isLineTerminator(ch)) {
+            shouldEscape = true;
+            break;
+        }
+
+        if (previousCharacterWasBackslash)
+            previousCharacterWasBackslash = false;
+        else
+            previousCharacterWasBackslash = ch == '\\';
+    }
+
+    if (!shouldEscape)
+        return pattern;
+
+    previousCharacterWasBackslash = false;
+    inBrackets = false;
+    StringBuilder result;
+    for (unsigned i = 0; i < length; ++i) {
+        CharacterType ch = characters[i];
+        if (!previousCharacterWasBackslash) {
+            if (inBrackets) {
+                if (ch == ']')
+                    inBrackets = false;
+            } else {
+                if (ch == '/')
+                    result.append('\\');
+                else if (ch == '[')
+                    inBrackets = true;
+            }
+        }
+
+        // escape LineTerminator
+        if (Lexer<CharacterType>::isLineTerminator(ch)) {
+            if (!previousCharacterWasBackslash)
+                result.append('\\');
+
+            appendLineTerminatorEscape<CharacterType>(result, ch);
+        } else
+            result.append(ch);
+
+        if (previousCharacterWasBackslash)
+            previousCharacterWasBackslash = false;
+        else
+            previousCharacterWasBackslash = ch == '\\';
+    }
+
+    return result.toString();
+}
+
+String RegExp::escapedPattern() const
+{
+    if (m_patternString.is8Bit())
+        return escapePattern(m_patternString, m_patternString.characters8(), m_patternString.length());
+    return escapePattern(m_patternString, m_patternString.characters16(), m_patternString.length());
+}
+
+String RegExp::toSourceString() const
+{
+    return makeString('/', escapedPattern(), '/', Yarr::flagsString(flags()).data());
+}
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/RegExp.h (279975 => 279976)


--- trunk/Source/_javascript_Core/runtime/RegExp.h	2021-07-16 04:01:38 UTC (rev 279975)
+++ trunk/Source/_javascript_Core/runtime/RegExp.h	2021-07-16 04:10:49 UTC (rev 279976)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten ([email protected])
- *  Copyright (C) 2007-2019 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007-2021 Apple Inc. All rights reserved.
  *  Copyright (C) 2009 Torch Mobile, Inc.
  *
  *  This library is free software; you can redistribute it and/or
@@ -137,6 +137,10 @@
 
     RegExpKey key() { return RegExpKey(m_flags, m_patternString); }
 
+    String escapedPattern() const;
+
+    String toSourceString() const;
+
 private:
     friend class RegExpCache;
     RegExp(VM&, const String&, OptionSet<Yarr::Flags>);

Modified: trunk/Source/_javascript_Core/runtime/RegExpInlines.h (279975 => 279976)


--- trunk/Source/_javascript_Core/runtime/RegExpInlines.h	2021-07-16 04:01:38 UTC (rev 279975)
+++ trunk/Source/_javascript_Core/runtime/RegExpInlines.h	2021-07-16 04:10:49 UTC (rev 279976)
@@ -27,6 +27,7 @@
 #include "Yarr.h"
 #include "YarrInterpreter.h"
 #include "YarrJIT.h"
+#include "YarrMatchingContextHolder.h"
 
 #define REGEXP_FUNC_TEST_DATA_GEN 0
 
@@ -131,7 +132,7 @@
     if (m_state == JITCode) {
         {
             ASSERT(m_regExpJITCode);
-            Yarr::MatchingContextHolder regExpContext(vm, m_regExpJITCode.get(), matchFrom);
+            Yarr::MatchingContextHolder regExpContext(vm, m_regExpJITCode.get(), this, matchFrom);
 
             if (s.is8Bit())
                 result = m_regExpJITCode->execute(s.characters8(), startOffset, s.length(), offsetVector, regExpContext).start;
@@ -144,7 +145,10 @@
             byteCodeCompileIfNecessary(&vm);
             if (m_state == ParseError)
                 return throwError();
-            result = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector));
+            {
+                Yarr::MatchingContextHolder regExpContext(vm, nullptr, this, matchFrom);
+                result = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector));
+            }
         }
 
 #if ENABLE(YARR_JIT_DEBUG)
@@ -157,7 +161,10 @@
 #endif
     } else
 #endif
+    {
+        Yarr::MatchingContextHolder regExpContext(vm, nullptr, this, matchFrom);
         result = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector));
+    }
 
     // FIXME: The YARR engine should handle unsigned or size_t length matches.
     // The YARR Interpreter is "unsigned" clean, while the YARR JIT hasn't been addressed.
@@ -255,12 +262,11 @@
         return throwError();
 
 #if ENABLE(YARR_JIT)
-    MatchResult result;
-
     if (m_state == JITCode) {
+        MatchResult result;
         {
             ASSERT(m_regExpJITCode);
-            Yarr::MatchingContextHolder regExpContext(vm, m_regExpJITCode.get(), matchFrom);
+            Yarr::MatchingContextHolder regExpContext(vm, m_regExpJITCode.get(), this, matchFrom);
 
             if (s.is8Bit())
                 result = m_regExpJITCode->execute(s.characters8(), startOffset, s.length(), regExpContext);
@@ -284,19 +290,23 @@
 
     int offsetVectorSize = (m_numSubpatterns + 1) * 2;
     int* offsetVector;
+    int result;
     Vector<int, 32> nonReturnedOvector;
     nonReturnedOvector.grow(offsetVectorSize);
     offsetVector = nonReturnedOvector.data();
-    int r = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector));
+    {
+        Yarr::MatchingContextHolder regExpContext(vm, nullptr, this, matchFrom);
+        result = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector));
+    }
 #if REGEXP_FUNC_TEST_DATA_GEN
     RegExpFunctionalTestCollector::get()->outputOneTest(this, s, startOffset, offsetVector, result);
 #endif
 
-    if (r >= 0) {
+    if (result >= 0) {
 #if ENABLE(REGEXP_TRACING)
         m_rtMatchOnlyFoundCount++;
 #endif
-        return MatchResult(r, reinterpret_cast<unsigned*>(offsetVector)[1]);
+        return MatchResult(result, reinterpret_cast<unsigned*>(offsetVector)[1]);
     }
 
     return MatchResult::failed();

Modified: trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp (279975 => 279976)


--- trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp	2021-07-16 04:01:38 UTC (rev 279975)
+++ trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp	2021-07-16 04:10:49 UTC (rev 279976)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten ([email protected])
- *  Copyright (C) 2003-2020 Apple Inc. All Rights Reserved.
+ *  Copyright (C) 2003-2021 Apple Inc. All Rights Reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -27,7 +27,6 @@
 #include "JSCJSValue.h"
 #include "JSGlobalObject.h"
 #include "JSStringInlines.h"
-#include "Lexer.h"
 #include "RegExpObject.h"
 #include "RegExpObjectInlines.h"
 #include "StringRecursionChecker.h"
@@ -339,113 +338,6 @@
     return JSValue::encode(jsString(vm, flags.data()));
 }
 
-template <typename CharacterType>
-static inline void appendLineTerminatorEscape(StringBuilder&, CharacterType);
-
-template <>
-inline void appendLineTerminatorEscape<LChar>(StringBuilder& builder, LChar lineTerminator)
-{
-    if (lineTerminator == '\n')
-        builder.append('n');
-    else
-        builder.append('r');
-}
-
-template <>
-inline void appendLineTerminatorEscape<UChar>(StringBuilder& builder, UChar lineTerminator)
-{
-    if (lineTerminator == '\n')
-        builder.append('n');
-    else if (lineTerminator == '\r')
-        builder.append('r');
-    else if (lineTerminator == 0x2028)
-        builder.append("u2028");
-    else
-        builder.append("u2029");
-}
-
-template <typename CharacterType>
-static inline JSValue regExpProtoGetterSourceInternal(JSGlobalObject* globalObject, const String& pattern, const CharacterType* characters, unsigned length)
-{
-    VM& vm = globalObject->vm();
-    bool previousCharacterWasBackslash = false;
-    bool inBrackets = false;
-    bool shouldEscape = false;
-
-    // 15.10.6.4 specifies that RegExp.prototype.toString must return '/' + source + '/',
-    // and also states that the result must be a valid RegularExpressionLiteral. '//' is
-    // not a valid RegularExpressionLiteral (since it is a single line comment), and hence
-    // source cannot ever validly be "". If the source is empty, return a different Pattern
-    // that would match the same thing.
-    if (!length)
-        return jsNontrivialString(vm, "(?:)"_s);
-
-    // early return for strings that don't contain a forwards slash and LineTerminator
-    for (unsigned i = 0; i < length; ++i) {
-        CharacterType ch = characters[i];
-        if (!previousCharacterWasBackslash) {
-            if (inBrackets) {
-                if (ch == ']')
-                    inBrackets = false;
-            } else {
-                if (ch == '/') {
-                    shouldEscape = true;
-                    break;
-                }
-                if (ch == '[')
-                    inBrackets = true;
-            }
-        }
-
-        if (Lexer<CharacterType>::isLineTerminator(ch)) {
-            shouldEscape = true;
-            break;
-        }
-
-        if (previousCharacterWasBackslash)
-            previousCharacterWasBackslash = false;
-        else
-            previousCharacterWasBackslash = ch == '\\';
-    }
-
-    if (!shouldEscape)
-        return jsString(vm, pattern);
-
-    previousCharacterWasBackslash = false;
-    inBrackets = false;
-    StringBuilder result;
-    for (unsigned i = 0; i < length; ++i) {
-        CharacterType ch = characters[i];
-        if (!previousCharacterWasBackslash) {
-            if (inBrackets) {
-                if (ch == ']')
-                    inBrackets = false;
-            } else {
-                if (ch == '/')
-                    result.append('\\');
-                else if (ch == '[')
-                    inBrackets = true;
-            }
-        }
-
-        // escape LineTerminator
-        if (Lexer<CharacterType>::isLineTerminator(ch)) {
-            if (!previousCharacterWasBackslash)
-                result.append('\\');
-
-            appendLineTerminatorEscape<CharacterType>(result, ch);
-        } else
-            result.append(ch);
-
-        if (previousCharacterWasBackslash)
-            previousCharacterWasBackslash = false;
-        else
-            previousCharacterWasBackslash = ch == '\\';
-    }
-
-    return jsString(vm, result.toString());
-}
-
 JSC_DEFINE_HOST_FUNCTION(regExpProtoGetterSource, (JSGlobalObject* globalObject, CallFrame* callFrame))
 {
     VM& vm = globalObject->vm();
@@ -459,10 +351,7 @@
         return throwVMTypeError(globalObject, scope, "The RegExp.prototype.source getter can only be called on a RegExp object"_s);
     }
 
-    String pattern = regexp->regExp()->pattern();
-    if (pattern.is8Bit())
-        return JSValue::encode(regExpProtoGetterSourceInternal(globalObject, pattern, pattern.characters8(), pattern.length()));
-    return JSValue::encode(regExpProtoGetterSourceInternal(globalObject, pattern, pattern.characters16(), pattern.length()));
+    return JSValue::encode(jsString(vm, regexp->regExp()->escapedPattern()));
 }
 
 JSC_DEFINE_HOST_FUNCTION(regExpProtoFuncSearchFast, (JSGlobalObject* globalObject, CallFrame* callFrame))

Modified: trunk/Source/_javascript_Core/runtime/SamplingProfiler.cpp (279975 => 279976)


--- trunk/Source/_javascript_Core/runtime/SamplingProfiler.cpp	2021-07-16 04:01:38 UTC (rev 279975)
+++ trunk/Source/_javascript_Core/runtime/SamplingProfiler.cpp	2021-07-16 04:10:49 UTC (rev 279976)
@@ -366,6 +366,7 @@
             CallFrame* callFrame;
             void* machinePC;
             bool topFrameIsLLInt = false;
+            RegExp* regExp = nullptr;
             void* llintPC;
             {
                 PlatformRegisters registers;
@@ -385,16 +386,16 @@
             // FIXME: Lets have a way of detecting when we're parsing code.
             // https://bugs.webkit.org/show_bug.cgi?id=152761
             if (ExecutableAllocator::singleton().isValidExecutableMemory(executableAllocatorLocker, machinePC)) {
-                if (m_vm.isExecutingInRegExpJIT) {
-                    // FIXME: We're executing a regexp. Lets gather more intersting data.
-                    // https://bugs.webkit.org/show_bug.cgi?id=152729
+                regExp = m_vm.m_executingRegExp;
+                if (regExp)
                     callFrame = m_vm.topCallFrame; // We need to do this or else we'd fail our backtrace validation b/c this isn't a JS frame.
-                }
             } else if (LLInt::isLLIntPC(machinePC)) {
                 topFrameIsLLInt = true;
                 // We're okay to take a normal stack trace when the PC
                 // is in LLInt code.
             } else {
+                // RegExp evaluation is leaf. So if RegExp evaluation exists, we can say it is RegExp evaluation is the top user-visible frame.
+                regExp = m_vm.m_executingRegExp;
                 // We resort to topCallFrame to see if we can get anything
                 // useful. We usually get here when we're executing C code.
                 callFrame = m_vm.topCallFrame;
@@ -434,7 +435,7 @@
                     stackTrace.uncheckedAppend(frame);
                 }
 
-                m_unprocessedStackTraces.append(UnprocessedStackTrace { nowTime, machinePC, topFrameIsLLInt, llintPC, WTFMove(stackTrace) });
+                m_unprocessedStackTraces.append(UnprocessedStackTrace { nowTime, machinePC, topFrameIsLLInt, llintPC, regExp, WTFMove(stackTrace) });
 
                 if (didRunOutOfVectorSpace)
                     m_currentFrames.grow(m_currentFrames.size() * 1.25);
@@ -592,7 +593,14 @@
         // Prepend the top-most inlined frame if needed and gather
         // location information about where the top frame is executing.
         size_t startIndex = 0;
-        if (unprocessedStackTrace.frames.size() && !!unprocessedStackTrace.frames[0].verifiedCodeBlock) {
+        if (unprocessedStackTrace.regExp) {
+            // If the stack-trace is annotated with RegExp, the top-frame must be RegExp since RegExp evaluation is leaf function.
+            appendEmptyFrame();
+            stackTrace.frames.last().regExp = unprocessedStackTrace.regExp;
+            stackTrace.frames.last().frameType = FrameType::RegExp;
+            stackTrace.frames.last().semanticLocation.isRegExp = true;
+            m_liveCellPointers.add(unprocessedStackTrace.regExp);
+        } else if (!unprocessedStackTrace.frames.isEmpty() && !!unprocessedStackTrace.frames[0].verifiedCodeBlock) {
             CodeBlock* topCodeBlock = unprocessedStackTrace.frames[0].verifiedCodeBlock;
             if (unprocessedStackTrace.topFrameIsLLInt) {
                 // We reuse LLInt CodeBlocks for the baseline JIT, so we need to check for both jit types.
@@ -735,8 +743,11 @@
 
 String SamplingProfiler::StackFrame::nameFromCallee(VM& vm)
 {
-    if (!callee)
+    if (!callee) {
+        if (regExp)
+            return regExp->toSourceString();
         return String();
+    }
 
     DeferTermination deferScope(vm);
     auto scope = DECLARE_CATCH_SCOPE(vm);
@@ -782,6 +793,7 @@
         }
 #endif
         return "(unknown C PC)"_s;
+
     case FrameType::Unknown:
         return "(unknown)"_s;
 
@@ -788,6 +800,9 @@
     case FrameType::Host:
         return "(host)"_s;
 
+    case FrameType::RegExp:
+        return "(regexp)"_s;
+
     case FrameType::Wasm:
 #if ENABLE(WEBASSEMBLY)
         if (wasmIndexOrName)
@@ -826,6 +841,9 @@
     case FrameType::C:
         return "(unknown)"_s;
 
+    case FrameType::RegExp:
+        return "(regexp)"_s;
+
     case FrameType::Host:
         return "(host)"_s;
 
@@ -866,6 +884,7 @@
     switch (frameType) {
     case FrameType::Unknown:
     case FrameType::Host:
+    case FrameType::RegExp:
     case FrameType::C:
     case FrameType::Wasm:
         return -1;
@@ -884,6 +903,7 @@
     switch (frameType) {
     case FrameType::Unknown:
     case FrameType::Host:
+    case FrameType::RegExp:
     case FrameType::C:
     case FrameType::Wasm:
         return std::numeric_limits<unsigned>::max();
@@ -903,6 +923,7 @@
     switch (frameType) {
     case FrameType::Unknown:
     case FrameType::Host:
+    case FrameType::RegExp:
     case FrameType::C:
     case FrameType::Wasm:
         return internalSourceID;
@@ -922,6 +943,7 @@
     switch (frameType) {
     case FrameType::Unknown:
     case FrameType::Host:
+    case FrameType::RegExp:
     case FrameType::C:
     case FrameType::Wasm:
         return emptyString();
@@ -1115,6 +1137,7 @@
     String builtin = "js builtin"_s;
     String wasm = "Wasm"_s;
     String host = "Host"_s;
+    String regexp = "RegExp"_s;
     String cpp = "C/C++"_s;
     String unknownFrame = "Unknown Frame"_s;
     String unknownExecutable = "Unknown Executable"_s;
@@ -1127,6 +1150,7 @@
         func(builtin);
         func(wasm);
         func(host);
+        func(regexp);
         func(cpp);
         func(unknownFrame);
         func(unknownExecutable);
@@ -1143,7 +1167,7 @@
             if (location.hasBytecodeIndex())
                 bytecodeIndex = toString(location.bytecodeIndex);
             else
-                bytecodeIndex = "<nil>";
+                bytecodeIndex = "<nil>"_s;
 
             if (location.hasCodeBlockHash()) {
                 StringPrintStream stream;
@@ -1150,14 +1174,16 @@
                 location.codeBlockHash.dump(stream);
                 codeBlockHash = stream.toString();
             } else
-                codeBlockHash = "<nil>";
+                codeBlockHash = "<nil>"_s;
 
             if (wasmCompilationMode)
                 jitType = Wasm::makeString(wasmCompilationMode.value());
+            else if (location.isRegExp)
+                jitType = "RegExp"_s;
             else
                 jitType = JITCode::typeName(location.jitType);
 
-            return makeString("#", codeBlockHash, ":", jitType, ":", bytecodeIndex);
+            return makeString('#', codeBlockHash, ':', jitType, ':', bytecodeIndex);
         };
 
         StackFrame& frame = stackTrace.frames.first();
@@ -1207,6 +1233,9 @@
             case SamplingProfiler::FrameType::Host:
                 tierName = host;
                 break;
+            case SamplingProfiler::FrameType::RegExp:
+                tierName = regexp;
+                break;
             case SamplingProfiler::FrameType::C:
                 tierName = cpp;
                 break;
@@ -1291,6 +1320,9 @@
     case SamplingProfiler::FrameType::Host:
         out.print("Host");
         break;
+    case SamplingProfiler::FrameType::RegExp:
+        out.print("RegExp");
+        break;
     case SamplingProfiler::FrameType::C:
     case SamplingProfiler::FrameType::Unknown:
         out.print("Unknown");

Modified: trunk/Source/_javascript_Core/runtime/SamplingProfiler.h (279975 => 279976)


--- trunk/Source/_javascript_Core/runtime/SamplingProfiler.h	2021-07-16 04:01:38 UTC (rev 279975)
+++ trunk/Source/_javascript_Core/runtime/SamplingProfiler.h	2021-07-16 04:10:49 UTC (rev 279976)
@@ -75,6 +75,7 @@
         Executable,
         Wasm,
         Host,
+        RegExp,
         C,
         Unknown,
     };
@@ -94,6 +95,7 @@
         const void* cCodePC { nullptr };
         ExecutableBase* executable { nullptr };
         JSObject* callee { nullptr };
+        RegExp* regExp { nullptr };
 #if ENABLE(WEBASSEMBLY)
         std::optional<Wasm::IndexOrName> wasmIndexOrName;
 #endif
@@ -122,6 +124,7 @@
             BytecodeIndex bytecodeIndex;
             CodeBlockHash codeBlockHash;
             JITType jitType { JITType::None };
+            bool isRegExp { false };
         };
 
         CodeLocation semanticLocation;
@@ -154,6 +157,7 @@
         void* topPC;
         bool topFrameIsLLInt;
         void* llintPC;
+        RegExp* regExp;
         Vector<UnprocessedStackFrame> frames;
     };
 

Modified: trunk/Source/_javascript_Core/runtime/VM.h (279975 => 279976)


--- trunk/Source/_javascript_Core/runtime/VM.h	2021-07-16 04:01:38 UTC (rev 279975)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2021-07-16 04:10:49 UTC (rev 279976)
@@ -217,6 +217,9 @@
 namespace DOMJIT {
 class Signature;
 }
+namespace Yarr {
+class MatchingContextHolder;
+}
 
 struct EntryFrame;
 struct HashTable;
@@ -983,7 +986,7 @@
     const Instruction* targetInterpreterPCForThrow;
     uint32_t osrExitIndex;
     void* osrExitJumpDestination;
-    bool isExecutingInRegExpJIT { false };
+    RegExp* m_executingRegExp { nullptr };
 
     // The threading protocol here is as follows:
     // - You can call scratchBufferForSize from any thread.

Modified: trunk/Source/_javascript_Core/yarr/YarrJIT.cpp (279975 => 279976)


--- trunk/Source/_javascript_Core/yarr/YarrJIT.cpp	2021-07-16 04:01:38 UTC (rev 279975)
+++ trunk/Source/_javascript_Core/yarr/YarrJIT.cpp	2021-07-16 04:10:49 UTC (rev 279976)
@@ -32,6 +32,7 @@
 #include "Yarr.h"
 #include "YarrCanonicalize.h"
 #include "YarrDisassembler.h"
+#include "YarrMatchingContextHolder.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/Threading.h>
 
@@ -44,34 +45,6 @@
 JSC_ANNOTATE_JIT_OPERATION(_JITTarget_vmEntryToYarrJITAfter, vmEntryToYarrJITAfter);
 #endif
 
-MatchingContextHolder::MatchingContextHolder(VM& vm, YarrCodeBlock* yarrCodeBlock, MatchFrom matchFrom)
-    : m_vm(vm)
-{
-    if (matchFrom == MatchFrom::VMThread)
-        m_stackLimit = vm.softStackLimit();
-    else {
-        StackBounds stack = Thread::current().stack();
-        m_stackLimit = stack.recursionLimit(Options::reservedZoneSize());
-    }
-
-#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
-    if (yarrCodeBlock->usesPatternContextBuffer()) {
-        m_patternContextBuffer = m_vm.acquireRegExpPatternContexBuffer();
-        m_patternContextBufferSize = VM::patternContextBufferSize;
-    }
-#else
-    UNUSED_PARAM(yarrCodeBlock);
-#endif
-}
-
-MatchingContextHolder::~MatchingContextHolder()
-{
-#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
-    if (m_patternContextBuffer)
-        m_vm.releaseRegExpPatternContexBuffer();
-#endif
-}
-
 template<YarrJITCompileMode compileMode>
 class YarrGenerator final : public YarrJITInfo, private MacroAssembler {
 
@@ -3771,14 +3744,10 @@
 #elif CPU(MIPS)
         // Do nothing.
 #endif
-
-        store8(TrustedImm32(1), &m_vm->isExecutingInRegExpJIT);
     }
 
     void generateReturn()
     {
-        store8(TrustedImm32(0), &m_vm->isExecutingInRegExpJIT);
-
 #if CPU(X86_64)
 #if OS(WINDOWS)
         // Store the return value in the allocated space pointed by rcx.
@@ -3821,7 +3790,6 @@
 #elif CPU(MIPS)
         // Do nothing
 #endif
-
 #if CPU(ARM64E)
         if (Options::useJITCage())
             farJump(TrustedImmPtr(retagCodePtr<void*, CFunctionPtrTag, OperationPtrTag>(&vmEntryToYarrJITAfter)), OperationPtrTag);

Modified: trunk/Source/_javascript_Core/yarr/YarrJIT.h (279975 => 279976)


--- trunk/Source/_javascript_Core/yarr/YarrJIT.h	2021-07-16 04:01:38 UTC (rev 279975)
+++ trunk/Source/_javascript_Core/yarr/YarrJIT.h	2021-07-16 04:10:49 UTC (rev 279976)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2009-2021 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -42,6 +42,7 @@
 
 namespace Yarr {
 
+class MatchingContextHolder;
 class YarrCodeBlock;
 
 enum class JITFailureReason : uint8_t {
@@ -55,27 +56,6 @@
     ExecutableMemoryAllocationFailure,
 };
 
-class MatchingContextHolder {
-    WTF_FORBID_HEAP_ALLOCATION;
-public:
-    MatchingContextHolder(VM&, YarrCodeBlock*, MatchFrom matchFrom = MatchFrom::VMThread);
-    ~MatchingContextHolder();
-
-    static ptrdiff_t offsetOfStackLimit() { return OBJECT_OFFSETOF(MatchingContextHolder, m_stackLimit); }
-#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
-    static ptrdiff_t offsetOfPatternContextBuffer() { return OBJECT_OFFSETOF(MatchingContextHolder, m_patternContextBuffer); }
-    static ptrdiff_t offsetOfPatternContextBufferSize() { return OBJECT_OFFSETOF(MatchingContextHolder, m_patternContextBufferSize); }
-#endif
-
-private:
-    VM& m_vm;
-    void* m_stackLimit;
-#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
-    void* m_patternContextBuffer { nullptr };
-    unsigned m_patternContextBufferSize { 0 };
-#endif
-};
-
 #if CPU(ARM64E)
 extern "C" EncodedMatchResult vmEntryToYarrJIT(const void* input, unsigned start, unsigned length, int* output, MatchingContextHolder* matchingContext, const void* codePtr);
 extern "C" void vmEntryToYarrJITAfter(void);

Added: trunk/Source/_javascript_Core/yarr/YarrMatchingContextHolder.h (0 => 279976)


--- trunk/Source/_javascript_Core/yarr/YarrMatchingContextHolder.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/yarr/YarrMatchingContextHolder.h	2021-07-16 04:10:49 UTC (rev 279976)
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2009-2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "VM.h"
+#include "Yarr.h"
+#include "YarrJIT.h"
+
+namespace JSC {
+
+class VM;
+class ExecutablePool;
+class RegExp;
+
+namespace Yarr {
+
+class YarrCodeBlock;
+
+class MatchingContextHolder {
+    WTF_FORBID_HEAP_ALLOCATION;
+public:
+    MatchingContextHolder(VM&, YarrCodeBlock*, RegExp*, MatchFrom);
+    ~MatchingContextHolder();
+
+    static ptrdiff_t offsetOfStackLimit() { return OBJECT_OFFSETOF(MatchingContextHolder, m_stackLimit); }
+#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
+    static ptrdiff_t offsetOfPatternContextBuffer() { return OBJECT_OFFSETOF(MatchingContextHolder, m_patternContextBuffer); }
+    static ptrdiff_t offsetOfPatternContextBufferSize() { return OBJECT_OFFSETOF(MatchingContextHolder, m_patternContextBufferSize); }
+#endif
+
+private:
+    VM& m_vm;
+    void* m_stackLimit;
+#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
+    void* m_patternContextBuffer { nullptr };
+    unsigned m_patternContextBufferSize { 0 };
+#endif
+    MatchFrom m_matchFrom;
+};
+
+inline MatchingContextHolder::MatchingContextHolder(VM& vm, YarrCodeBlock* yarrCodeBlock, RegExp* regExp, MatchFrom matchFrom)
+    : m_vm(vm)
+    , m_matchFrom(matchFrom)
+{
+    if (matchFrom == MatchFrom::VMThread) {
+        m_stackLimit = vm.softStackLimit();
+        vm.m_executingRegExp = regExp;
+    } else {
+        StackBounds stack = Thread::current().stack();
+        m_stackLimit = stack.recursionLimit(Options::reservedZoneSize());
+    }
+
+#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
+    if (yarrCodeBlock && yarrCodeBlock->usesPatternContextBuffer()) {
+        m_patternContextBuffer = m_vm.acquireRegExpPatternContexBuffer();
+        m_patternContextBufferSize = VM::patternContextBufferSize;
+    }
+#else
+    UNUSED_PARAM(yarrCodeBlock);
+#endif
+}
+
+inline MatchingContextHolder::~MatchingContextHolder()
+{
+#if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS)
+    if (m_patternContextBuffer)
+        m_vm.releaseRegExpPatternContexBuffer();
+#endif
+    if (m_matchFrom == MatchFrom::VMThread)
+        m_vm.m_executingRegExp = nullptr;
+}
+
+} } // namespace JSC::Yarr
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to