[webkit-dev] Seeking help/guidance with ParserError::StackOverflow porting JavaScriptCore to Android
Mark Lam
mark.lam at apple.com
Tue Feb 25 17:06:59 PST 2014
One more time from the right email address:
Eric,
As a rule of thumb, you’ll want the following:
errorModeRequiredStack < requiredStack < total Stack size.
There are some minimum amount of stack space that some reasonable native (C/C++) code can use without needing to do a stack check. Let’s call that amount N_min.
In addition, we will want to be able enter the VM and execute some minimal amount of JS code to throw an exception / error. Let’s call this amount N_exception.
With that, the following should be true:
1. errorModeRequiredStack = N_min
2. requiredStack = N_min + N_exception
We picked 64k as a conservative estimate for both the N values. Your fix should be to determine if you can do with smaller values for N_min and N_exception on your system.
The downside of picking a N_min that is too small is:
1. your app crashes if the stack edge is guarded by a guard page, and you don’t overshoot the stack by more than the size of that guard page.
2. your app corrupts memory beyond the edge of the stack if there isn’t a guard page there, or if you overshoot the stack by more than the size of the guard page.
The downside of pick a N_exception that is too small is that you will get an uninformative StackOverflowError where the JS stack trace may not contain useful info.
If your total stack is that small, you will need to work with smaller N_min and N_exception values.
Regards,
Mark
On Feb 21, 2014, at 6:05 PM, Eric Wing <ewmailing at gmail.com> wrote:
> Please bear with me. I'm trying to articulate a problem that another
> developer run into. Both of us only know certain pieces of the problem
> so I offered to post for both of us.
>
> Quick background: I've been working with Appcelerator to port
> JavaScriptCore to Android. The Appcelerator branch forked off of
> Webkit I think in the July timeframe, shortly after WWDC. There are
> plans to remerge with mainline, but this is down the road.
>
> I currently have a working JavaScriptCore that runs on my 1st gen
> Nexus 7 running 4.4. We wrote a test262 conformance app to check our
> work, and it passes the 11,000+ tests with less than 20 failures.
>
> I was contacted by the other developer (Shuan Zhao) who had found my
> branch reproduced my build of JavaScriptCore for Android. However, on
> their Android devices (Android 4.0.4, 4.1.2 and 4.3 (one HTC Desire
> HD, one CoolPad and one Samsung Galaxy S4), JavaScriptCore fails to
> successfully execute scripts when on the main thread. It appears that
> ParserError::StackOverflow is triggered inside JavaScriptCore.
>
> So our belief is that there is some problem related to the stack space
> on these devices or these versions of Android.
>
> We started in Source/WTF/wtf/StackBounds.cpp, we found:
>
> void StackBounds::initialize()
> {
> void* stackBase = 0;
> size_t stackSize = 0;
>
> pthread_t thread = pthread_self();
> pthread_attr_t sattr;
> pthread_attr_init(&sattr);
> #if HAVE(PTHREAD_NP_H) || OS(NETBSD)
> // e.g. on FreeBSD 5.4, neundorf at kde.org
> pthread_attr_get_np(thread, &sattr);
> #else
> // FIXME: this function is non-portable; other POSIX systems may
> have different np alternatives
> pthread_getattr_np(thread, &sattr);
> #endif
> int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);
> (void)rc; // FIXME: Deal with error code somehow? Seems fatal.
> ASSERT(stackBase);
> pthread_attr_destroy(&sattr);
> m_bound = stackBase;
> m_origin = static_cast<char*>(stackBase) + stackSize;
> }
>
>
> Shuan Zhao says "running on the main thread, the stack size is
> 131072(pthread_attr_getstack and pthread_attr_getstacksize function
> returned the same result), which is 1M when running on a new thread. I
> don't know why it is much smaller on the main thread. The stack size I
> get from program running on my Mac OS is 512K which is also smaller
> than 1M."
>
> Additionally:
> "I see the following code in JSCore. The value returned by
> requiredCapacity is 128K when not in error handling mode which is as
> much as the stack size I get on the main thread. I think this will
> cause isSafeToRecurse to return false which will cause a stack
> overflow exception. I don't know how to fix this."
>
>
> class VMStackBounds {
> public:
> VMStackBounds(VM& vm, const StackBounds& bounds)
> : m_vm(vm)
> , m_bounds(bounds)
> {
> }
>
> bool isSafeToRecurse() const { return
> m_bounds.isSafeToRecurse(requiredCapacity()); }
>
> private:
> inline size_t requiredCapacity() const
> {
> Interpreter* interpreter = m_vm.interpreter;
>
> // We have two separate stack limits, one for regular JS
> execution, and one
> // for when we're handling errors. We need the error stack to be smaller
> // otherwise there would obviously not be any stack left to
> execute JS in when
> // there's a stack overflow.
> //
> // These sizes were derived from the stack usage of a number
> of sites when
> // layout occurs when we've already consumed most of the C stack.
> const size_t requiredStack = 128 * KB;
> const size_t errorModeRequiredStack = 64 * KB;
>
> size_t requiredCapacity = interpreter->isInErrorHandlingMode()
> ? errorModeRequiredStack : requiredStack;
> RELEASE_ASSERT(m_bounds.size() >= requiredCapacity);
> return requiredCapacity;
> }
>
> VM& m_vm;
> const StackBounds& m_bounds;
> };
>
> Finally: "I change the requiredStack variable to 64 * KB, and It works"
>
> Shuan Zhao also noted the current mainline no longer has the
> VMStackBounds class.
>
>
> We really don't know what the correct fix is, so we hoped you could
> give us some guidance on what we should try. (Note: We really don't
> think it's safe for us to re-merge with mainline right now. There are
> still too many unknowns for us.)
>
> Thanks,
> Eric
>
> --
> Beginning iPhone Games Development
> http://playcontrol.net/iphonegamebook/
> _______________________________________________
> webkit-dev mailing list
> webkit-dev at lists.webkit.org
> https://lists.webkit.org/mailman/listinfo/webkit-dev
More information about the webkit-dev
mailing list