Bug 123058
Summary: | JSC should have an API for typed arrays | ||
---|---|---|---|
Product: | WebKit | Reporter: | Alexey Proskuryakov <ap> |
Component: | JavaScriptCore | Assignee: | Nobody <webkit-unassigned> |
Status: | RESOLVED DUPLICATE | ||
Severity: | Normal | CC: | fpizlo, ggaren, mhahnenberg |
Priority: | P2 | ||
Version: | 528+ (Nightly build) | ||
Hardware: | Unspecified | ||
OS: | Unspecified |
Alexey Proskuryakov
It seems that JavaScript API clients can't do anything with typed arrays passed to them as arguments.
I'm facing this in bug 86914, implementing testRunner.setAudioData(ArrayBufferView). In DumpRenderTree, I can grudgingly use private JSC functions just like in WebCore, but API clients can't do that.
Attachments | ||
---|---|---|
Add attachment proposed patch, testcase, etc. |
Geoffrey Garen
What would you like to be able to do with them? Surely you can do some things, like read their lengths and access individual elements.
Alexey Proskuryakov
> access individual elements
That's probably not the most reasonable thing to do in cases that warrant TypedArray use :)
Personally, I only needed to get bytes from the buffer efficiently. Not sure if there is anything else that can't be done already, but perhaps some syntactic sugar would help? Also, not sure how efficiently one can create a typed array from C code.
Filip Pizlo
(In reply to comment #2)
> > access individual elements
>
> That's probably not the most reasonable thing to do in cases that warrant TypedArray use :)
>
> Personally, I only needed to get bytes from the buffer efficiently. Not sure if there is anything else that can't be done already, but perhaps some syntactic sugar would help? Also, not sure how efficiently one can create a typed array from C code.
I agree we should have such an API. I think we even have some dup's for this bug - you're not the first to ask for this.
Maybe just the following C API function would be enough:
JSGetTypedArrayBase(JSValueRef) -> returns void* of the first element in the view or the base of the buffer
JSGetTypedArrayByteLength(JSValueRef) -> returns size_t of the number of bytes that the view sees or the byteLength of the buffer.
These will work for any view or buffer and return null/0 for things that aren't typed arrays.
Sound sensible?
Geoffrey Garen
I think Alexey is also asking for a way to create typed arrays.
> JSGetTypedArrayBase(JSValueRef) -> returns void* of the first element in the view or the base of the buffer
> JSGetTypedArrayByteLength(JSValueRef) -> returns size_t of the number of bytes that the view sees or the byteLength of the buffer.
This would be
JSObjectGetTypedArrayBase(JSContextRef, JSValueRef)
JSObjectGetTypedArrayByteLength(JSContextRef, JSValueRef)
Maybe "BytesPtr" is a better name than "Base", to match our string and data APIs.
How would I know the data type in the typed array? How long would the returned pointer remain valid? What happens after neutering?
Geoffrey Garen
> JSObjectGetTypedArrayBase(JSContextRef, JSValueRef)
> JSObjectGetTypedArrayByteLength(JSContextRef, JSValueRef)
Sorry:
JSObjectGetTypedArrayBase(JSContextRef, JSObjectRef)
JSObjectGetTypedArrayByteLength(JSContextRef, JSObjectRef)
Filip Pizlo
(In reply to comment #4)
> I think Alexey is also asking for a way to create typed arrays.
>
> > JSGetTypedArrayBase(JSValueRef) -> returns void* of the first element in the view or the base of the buffer
> > JSGetTypedArrayByteLength(JSValueRef) -> returns size_t of the number of bytes that the view sees or the byteLength of the buffer.
>
> This would be
>
> JSObjectGetTypedArrayBase(JSContextRef, JSValueRef)
> JSObjectGetTypedArrayByteLength(JSContextRef, JSValueRef)
OK, but out of curiosity, does it have to be? You can get a JSGenericTypedArrayView's base and length without an ExecState*.
>
> Maybe "BytesPtr" is a better name than "Base", to match our string and data APIs.
Yeah.
>
> How would I know the data type in the typed array?
Why would a client care? If they did, they can already get the element type using JS constructs.
> How long would the returned pointer remain valid?
Only so long as the JSValueRef of the buffer or view was live and so long as it wasn't neutered.
> What happens after neutering?
It's interesting to note that neutering is purely a DOM construct - it will only happen if you use the JS API in conjunction with a WebView.
Neutering will free the buffer so your pointer will become invalid.
Filip Pizlo
(In reply to comment #6)
> (In reply to comment #4)
> > I think Alexey is also asking for a way to create typed arrays.
> >
> > > JSGetTypedArrayBase(JSValueRef) -> returns void* of the first element in the view or the base of the buffer
> > > JSGetTypedArrayByteLength(JSValueRef) -> returns size_t of the number of bytes that the view sees or the byteLength of the buffer.
> >
> > This would be
> >
> > JSObjectGetTypedArrayBase(JSContextRef, JSValueRef)
> > JSObjectGetTypedArrayByteLength(JSContextRef, JSValueRef)
>
> OK, but out of curiosity, does it have to be? You can get a JSGenericTypedArrayView's base and length without an ExecState*.
>
> >
> > Maybe "BytesPtr" is a better name than "Base", to match our string and data APIs.
>
> Yeah.
>
> >
> > How would I know the data type in the typed array?
>
> Why would a client care? If they did, they can already get the element type using JS constructs.
>
> > How long would the returned pointer remain valid?
>
> Only so long as the JSValueRef of the buffer or view was live and so long as it wasn't neutered.
And to clarify, we will ensure that the returned buffer pointer was pinned by doing slowDownAndWasteMemory().
>
> > What happens after neutering?
>
> It's interesting to note that neutering is purely a DOM construct - it will only happen if you use the JS API in conjunction with a WebView.
>
> Neutering will free the buffer so your pointer will become invalid.
Geoffrey Garen
> > JSObjectGetTypedArrayBase(JSContextRef, JSValueRef)
> > JSObjectGetTypedArrayByteLength(JSContextRef, JSValueRef)
> OK, but out of curiosity, does it have to be? You can get a JSGenericTypedArrayView's base and length without an ExecState*.
Whenever we’ve made the decision to leave out JSContextRef before, we’ve come to regret it. For example, we made that decision for strings, and now we regret it.
In this case, I could imagine some implementations that might require an ExecState* in order to get a backing pointer. For example, if we did pin the pointer, and pinning required a GC allocation, then we would need an ExecState*. Or, if some typed arrays had a super-slow mode, in which their backing buffer pointers were maintained in an external hash table, that would require an ExecState*. Or if some typed arrays had an "I'm currently in GPU memory" mode, that would require an ExecState*.
Filip Pizlo
(In reply to comment #8)
> > > JSObjectGetTypedArrayBase(JSContextRef, JSValueRef)
> > > JSObjectGetTypedArrayByteLength(JSContextRef, JSValueRef)
>
> > OK, but out of curiosity, does it have to be? You can get a JSGenericTypedArrayView's base and length without an ExecState*.
>
> Whenever we’ve made the decision to leave out JSContextRef before, we’ve come to regret it. For example, we made that decision for strings, and now we regret it.
>
> In this case, I could imagine some implementations that might require an ExecState* in order to get a backing pointer. For example, if we did pin the pointer, and pinning required a GC allocation, then we would need an ExecState*. Or, if some typed arrays had a super-slow mode, in which their backing buffer pointers were maintained in an external hash table, that would require an ExecState*. Or if some typed arrays had an "I'm currently in GPU memory" mode, that would require an ExecState*.
Interestingly, slowDownAndWasteMemory() does require VM& but it doesn't take either VM& or ExecState*. It just uses heapFor(). That's because there were too many places that expected to be able to get a native buffer from a JS buffer and they didn't have an ExecState* lying around.
But, sure, we don't have to expose such madness to the C API customers.
Alexey Proskuryakov
Found an older bug, duping to that.
*** This bug has been marked as a duplicate of bug 120112 ***