Bug 1684123 - Implement GetArrayBufferViewFixedData and dom::TypedArray_base::FixedData(). r=jonco

Differential Revision: https://phabricator.services.mozilla.com/D100426
This commit is contained in:
Steve Fink 2021-01-13 22:17:40 +00:00
Родитель 580169fbfc
Коммит a75149f6b8
4 изменённых файлов: 68 добавлений и 0 удалений

Просмотреть файл

@ -115,6 +115,18 @@ struct TypedArray_base : public SpiderMonkeyInterfaceObjectStorage,
return mData;
}
// Return a pointer to data that will not move during a GC.
//
// For some smaller views, this will copy the data into the provided buffer
// and return that buffer as the pointer. Otherwise, this will return a
// direct pointer to the actual data with no copying. If the provided buffer
// is not large enough, nullptr will be returned. If bufSize is at least
// JS_MaxMovableTypedArraySize(), the data is guaranteed to fit.
inline T* FixedData(uint8_t* buffer, size_t bufSize) const {
MOZ_ASSERT(mComputed);
return JS_GetArrayBufferViewFixedData(mImplObj, buffer, bufSize);
}
inline uint32_t Length() const {
MOZ_ASSERT(mComputed);
return mLength;

Просмотреть файл

@ -378,6 +378,27 @@ extern JS_FRIEND_API double* JS_GetFloat64ArrayData(JSObject* obj,
extern JS_FRIEND_API void* JS_GetArrayBufferViewData(
JSObject* obj, bool* isSharedMemory, const JS::AutoRequireNoGC&);
/**
* Return a "fixed" pointer (one that will not move during a GC) to the
* ArrayBufferView's data. Note that this will not keep the object alive; the
* holding object should be rooted or traced. If the view is storing the data
* inline, this will copy the data to the provided buffer, returning nullptr if
* bufSize is inadequate.
*
* Avoid using this unless necessary. JS_GetArrayBufferViewData is simpler and
* more efficient because it requires the caller to ensure that a GC will not
* occur and thus does not need to handle movable data.
*/
extern JS_FRIEND_API uint8_t* JS_GetArrayBufferViewFixedData(
JSObject* obj, uint8_t* buffer, size_t bufSize);
/**
* If the bufSize passed to JS_GetArrayBufferViewFixedData is at least this
* many bytes, then any copied data is guaranteed to fit into the provided
* buffer.
*/
extern JS_FRIEND_API size_t JS_MaxMovableTypedArraySize();
/**
* Return the ArrayBuffer or SharedArrayBuffer underlying an ArrayBufferView.
* This may return a detached buffer. |obj| must be an object that would

Просмотреть файл

@ -175,6 +175,37 @@ JS_FRIEND_API void* JS_GetArrayBufferViewData(JSObject* obj,
/*safe - caller sees isSharedMemory flag*/);
}
JS_FRIEND_API uint8_t* JS_GetArrayBufferViewFixedData(JSObject* obj,
uint8_t* buffer,
size_t bufSize)
{
ArrayBufferViewObject* view = obj->maybeUnwrapAs<ArrayBufferViewObject>();
if (!view) {
return nullptr;
}
// Disallow shared memory until it is needed.
if (view->isSharedMemory()) {
return nullptr;
}
// TypedArrays (but not DataViews) can have inline data, in which case we
// need to copy into the given buffer.
if (view->is<TypedArrayObject>()) {
TypedArrayObject* ta = &view->as<TypedArrayObject>();
if (ta->hasInlineElements()) {
size_t bytes = ta->byteLength().get();
if (bytes > bufSize) {
return nullptr; // Does not fit.
}
memcpy(buffer, view->dataPointerUnshared(), bytes);
return buffer;
}
}
return static_cast<uint8_t*>(view->dataPointerUnshared());
}
JS_FRIEND_API JSObject* JS_GetArrayBufferViewBuffer(JSContext* cx,
HandleObject obj,
bool* isSharedMemory) {

Просмотреть файл

@ -2622,3 +2622,7 @@ JS_FRIEND_API js::Scalar::Type JS_GetArrayBufferViewType(JSObject* obj) {
}
MOZ_CRASH("invalid ArrayBufferView type");
}
JS_FRIEND_API size_t JS_MaxMovableTypedArraySize() {
return TypedArrayObject::INLINE_BUFFER_LIMIT;
}