[Webkit-unassigned] [Bug 109961] New: Very obscure bug supposedly affecting the JavaScriptCore optimizer

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Fri Feb 15 12:35:04 PST 2013


https://bugs.webkit.org/show_bug.cgi?id=109961

           Summary: Very obscure bug supposedly affecting the
                    JavaScriptCore optimizer
           Product: WebKit
           Version: 528+ (Nightly build)
          Platform: Macintosh Intel
               URL: ttp://paperjs.org/static/webkit-bug/scoped/
        OS/Version: Mac OS X 10.8
            Status: UNCONFIRMED
          Severity: Critical
          Priority: P2
         Component: JavaScriptCore
        AssignedTo: webkit-unassigned at lists.webkit.org
        ReportedBy: lists at scratchdisk.com


I am currently encountering the most bizarre JavaScript issue in 15 years of working with the language, and I am not quite sure as to how to outline it well:

The issue affects the Paper.js library of which I am one of the creators, and happens only on Safari.

When opening the linked example http://paperjs.org/static/webkit-bug/scoped/ on any browser other than Safari, here is what you should encounter:

https://www.dropbox.com/s/jw71clxjefazis9/webkit-bug-expected.png

But when viewing the page on the latest Safari Version 6.0.2 (8536.26.17), here is what you will probably see instead:

https://www.dropbox.com/s/rkq44om11fpr0jc/webkit-bug-encountered.png

As soon as I fire up the Web Inspector to debug the issue, the issue disappears and I see the correct behavior. The only available debugging tool thus is logging to the console.

In this way I have found the place where the issue occurs. In this example, Paper.js draws vector paths that are composed out of segments. When transforming such a path, e.g. by using Item#scale() as in the example, Segment#_transformCoordinates() is called for each segment of the path.

The example first creates a path consisting of 100 segments (each consisting of an anchor point and two handle points), then scales the path by calling  #_transformCoordinates() for each of these segments (which in turn transforms the segment's anchor and handle points), then erases the path again. This call to #scale() is needed to "initiate" the bug. Without it, the code example will display correctly.

After having created and erased this path, it then creates a circular path and scales it as well. The above "initiation" will have messed up #_transformCoordinates() in a way that now causes issues in the scaling of the separate path, with the result displayed above.

If I reduce the amount of segments in the first path, the issue disappears at around 34 segments. It also behaves wrongly in a different way at around 35-40 segments. These values may have to be different on different systems. I couldn't quite tell how it misbehaves, but I have seen familiar numeric values appear in the wrong places, e.g. the y coordinate of a segment's handle ending up in the x coordinate of its anchor point, suggesting that the optimizer is getting pointers or memory offsets confused.

My theory is that in the "initiation" phase of the issue, the JavaScriptCore optimizer decides to apply some JIT magic to #_transformCoordinates() because it is called a lot, and in the process of doing so messes it up. This would explain why it disappears when using the debugger, as I doubt the optimizer is active then, and also why many segments are required to cause the issue.

Another very strange observation that I made has to do with scoping of the whole library: Paper.js is normally scoped. But in the process of trying to find a remedy, I have tried an unscoped version of the library (thus polluting the global scope), and the problem is magically disappearing when using this version:

http://paperjs.org/static/webkit-bug/unscoped/

Another strange half-remedy was adding this nonsensical unreachable code statement after the last return statement inside #_transformCoordinates():

    return coords;
    nop().nop();

This doesn't make the problem disappear completely, but it becomes much sless likely, which is bizarre because the code is pretty much the same, nop() does not exist, and its execution is unreachable due to the return statement above it.

Also note that nop() does not exist, and a simple nop(); alone would not half-fix it, the chaining seemed necessary, and any identifier would do of course. Don't ask how I found out about this one :)

I normally try my best to create a simple test-case, but in this particular instance I don't know where to start simplifying since the issue is affected by so many bizarre side effects.

I hope this can be solved soon since it is affecting our library in a way that forces us to not scope it and pollute global scope, which is considered bad practice.

-- 
Configure bugmail: https://bugs.webkit.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.



More information about the webkit-unassigned mailing list