Looking at it more, this is looking like a pretty deep flaw in how bindings handle typed arrays & similar. When you pass one into a function generated by DOM bindings, the argument is given to the `SpiderMonkeyInterface` stuff that extracts out the data pointers. It has a bunch of machinery, all of which looks correct, for making sure the owning `JSObject*` is properly rooted. The problem here is that rooting isn't enough; because we've grabbed out a pointer, GC can invalidate even a rooted pointer. (Or rather, the rooted pointer itself will be updated properly, but any pointers into its data will not.) Since we do have stack holder objects here, I *could* apply the same fix that I used recently to only hang onto immovable data pointers (at a cost of using stack space for the largest possible movable data, and the performance cost of `memcpy`ing the data). Right now, that's feeling pretty unsatisfying, since it's paying a non-negligible cost all the time for something that is rarely needed, and it would apply to *all* WebIDL interfaces that manipulate array buffers and their views. Another alternative would be to eliminate `TypedArray_base` and friends entirely, and instead fetch the data pointers on demand. I fear that this would just make it harder to detect the underlying problem -- I'm only seeing this problem because I changed those classes to complain. If I eliminated that layer, then the problem might just recur in lots of handwritten, harder to analyze code. Yet another option: change the DOM bindings argument holders so that they still do all of the argument checking they do now, but they don't retrieve the problematic data pointers. Instead, when one of these argument values is needed, you'd "activate" the interface object to read out the data pointers, and then afterward `Reset()` it. (It might actually reset itself whenever it is passed as a parameter, but the analysis might require the explicit `Reset` to properly track what's going on.) In effect, this is similar to the previous alternative -- the interface objects would only be used for rooting, and for informing the analysis of in what ranges of code it is legal to be holding data pointers. The final option I can come up with is something that I tried when I first ran into `TypedArray_base` problems: have an API call that converts typed arrays to using immovable storage (if they aren't already). It has some of the `memcpy` drawbacks, though only once per object. The bigger problem I ran into is that `TypedArray_base`-using code isn't always able to handle or propagate allocation failure properly. Sometimes it's not even on the correct thread.
Bug 1690111 Comment 1 Edit History
Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.
Looking at it more, this is looking like a pretty deep flaw in how bindings handle typed arrays & similar. When you pass one into a function generated by DOM bindings, the argument is given to the `SpiderMonkeyInterface` stuff that extracts out the data pointers. It has a bunch of machinery, all of which looks correct, for making sure the owning `JSObject*` is properly rooted. The problem here is that rooting isn't enough; because we've grabbed out a pointer, GC can invalidate even a rooted pointer. (Or rather, the rooted pointer itself will be updated properly, but any pointers into its data will not.) *Option 1*: Since we do have stack holder objects here, I *could* apply the same fix that I used recently to only hang onto immovable data pointers (at a cost of using stack space for the largest possible movable data, and the performance cost of `memcpy`ing the data). Right now, that's feeling pretty unsatisfying, since it's paying a non-negligible cost all the time for something that is rarely needed, and it would apply to *all* WebIDL interfaces that manipulate array buffers and their views. *Option 2*: Another alternative would be to eliminate `TypedArray_base` and friends entirely, and instead fetch the data pointers on demand. I fear that this would just make it harder to detect the underlying problem -- I'm only seeing this problem because I changed those classes to complain. If I eliminated that layer, then the problem might just recur in lots of handwritten, harder to analyze code. *Option 3*: Yet another option: change the DOM bindings argument holders so that they still do all of the argument checking they do now, but they don't retrieve the problematic data pointers. Instead, when one of these argument values is needed, you'd "activate" the interface object to read out the data pointers, and then afterward `Reset()` it. (It might actually reset itself whenever it is passed as a parameter, but the analysis might require the explicit `Reset` to properly track what's going on.) In effect, this is similar to the previous alternative -- the interface objects would only be used for rooting, and for informing the analysis of in what ranges of code it is legal to be holding data pointers. *Option 4*: The final option I can come up with is something that I tried when I first ran into `TypedArray_base` problems: have an API call that converts typed arrays to using immovable storage (if they aren't already). It has some of the `memcpy` drawbacks, though only once per object. The bigger problem I ran into is that `TypedArray_base`-using code isn't always able to handle or propagate allocation failure properly. Sometimes it's not even on the correct thread.