-
Notifications
You must be signed in to change notification settings - Fork 18k
regexp/syntax: compilation results in maximum call stack exceeded on js/wasm (safari) #34664
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
/cc @neelance |
It works fine in Chrome and Firefox, so I think this needs a fix on Safari's end. Unfortunately Safari is not investing much in proper support for WebAssembly. |
This seems like a reasonable theory, but it's also a call stack thing where the function is calling itself... so it's also possible that chrome/node are just covering up a bug too. I don't know the internals of the wasm compilation very well, but if I can be of help trying to track this down I will. |
The most likely explanation is that we're hitting some implementation-specific limit and Safari has the lowest limit. Unfortunately the WebAssembly spec does not specify concrete limits:
Source: http://webassembly.github.io/spec/core/appendix/implementation.html?highlight=limits#execution Like I said, Safari is in general not an engaged player in the WebAssembly ecosystem, which is why I am inclined to say that the incompatibility should be fixed by Safari, not Go. |
I agree. Exactly what I said in slack. It is a combination of the regex and Safari implementation. The regex itself generates recursive function calls, so there isn't much the compiler can do. And Safari has this weird limit on call stack size. |
FWIW: I tested the max call stack in WASM on chrome and safari Safari is about 11,300 and chrome is 39,400 Over 11k function calls for a regex compile seems like a lot? Using the following go code: package main
import (
"fmt"
)
func recurse(i int) {
if (i % 100) == 0 {
fmt.Println(i)
}
recurse(i + 1)
}
func main() {
fmt.Println("hello from go")
recurse(0)
} |
Yeah, ideally the regexp package wouldn't require 11k stack frames. |
Specifically, at a704224,
|
Doesn't that imply this is more of a regex issue than a wasm issue ? |
I agree, there should be a way to not require 11k stack frames. Seems like I was a bit too quick with saying that there is nothing to change on Go's side... Is there anyone in particular we should ping who is most familiar with the regexp/syntax package? |
paging @rsc as per owners. |
Kinda both. regexp/syntax could be more economical in its use of stack frames. (that'd be up to @rsc to fix/approve changes) But maybe wasm could handle it better. It works fine on other architectures. Do we know specifically which limit Safari is unhappy about? Is it really call depth, or we hitting memory limits? |
I mean it says: "maximum call stack exceeded" which I think is only recursion. I used to get an out of memory error in mobile, but go 1.13 seems to have fixed that. |
The biggest offender here are the recursive calls to |
@smasher164, thanks! |
FWIW - I found that it choked on any regex with a count in it... like: |
@smasher164 what'd you find out there? This issue is blocking an app I'm working on from loading in Safari |
@joeykrug I'm afraid I haven't had time to look at this recently. I did find that converting regexp's (RE2's) compile procedure from a recursive one to an iterative one would have to be more invasive than just using a stack-based DFS. Additional state needs to be tracked to control which subexpressions are processed, especially for the loops inside I may get back to this in the near term, but if someone else wants to work on it, feel free. Additionally, it may be worthwhile to first check whether leaf functions like |
I am wondering what was the solution from their side ? Because clearly there is something that can be improved in the compiler. |
Judging by the patch notes in Bug 206436
It seems that webkit now reduces the size of a stack frame to allow for a greater stack depth. This addresses the stack depth limit described in Bug 201028
|
The issue seems to be resolved since Safari 13.2. What remains is a possible performance improvement of regexp/syntax. @bradfitz Do we want to relabel this issue to keep track of it or just close it? |
@neelance I think this issue should be closed, since it was a WASM implementation issue. Resolving this on the Go side would require significant refactoring of the regexp package. I'm going ahead and closing it, based on the lack of response. Feel free to reopen if necessary. |
What version of Go are you using (
go version
)?go 1.13 in docker (compiled to wasm)
Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Simple reproduction here: https://xena.greedo.xeserv.us/files/regex_wasm/
Simply including
var labelRegex = regexp.MustCompile(
^\s*([[:ascii:]]{1,256}?)=("[[:ascii:]]{0,256}?")\s*,)
in the main.go causes the go not to run in safari.Note, this does work in chrome and node (and I believe FireFox) and this is only an issue in the safari browser (both desktop and mobile).
What did you expect to see?
A compiled regex
What did you see instead?
Maximum call stack exceeded.
The text was updated successfully, but these errors were encountered: