Add allocate/free callbacks to ArrayBuffers (#4801)
Larger buffer allocations will throw error instead of calling jerry_fatal. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
+333
-23
@@ -1457,6 +1457,86 @@ typedef struct
|
||||
- [jerry_source_info_enabled_fields_t](#jerry_source_info_enabled_fields_t)
|
||||
- [jerry_get_source_info](#jerry_get_source_info)
|
||||
|
||||
## jerry_arraybuffer_type_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Enum that contains the JerryScript type of an array buffer:
|
||||
|
||||
- JERRY_ARRAYBUFFER_TYPE_ARRAYBUFFER - the object is an array buffer object
|
||||
- JERRY_ARRAYBUFFER_TYPE_SHARED_ARRAYBUFFER - the object is a shared array buffer object
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_arraybuffer_allocate_t](#jerry_arraybuffer_allocate_t)
|
||||
- [jerry_arraybuffer_free_t](#jerry_arraybuffer_free_t)
|
||||
|
||||
## jerry_arraybuffer_allocate_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Callback for allocating the backing store of array buffer or shared array buffer objects.
|
||||
|
||||
*Note*:
|
||||
- The value referenced by `arraybuffer_user_p` is always NULL unless the buffer is created by
|
||||
[jerry_create_arraybuffer_external](#jerry_create_arraybuffer_external) or
|
||||
[jerry_create_shared_arraybuffer_external](#jerry_create_shared_arraybuffer_external).
|
||||
The value referenced by `arraybuffer_user_p` can be changed, and the new value is passed to
|
||||
[jerry_arraybuffer_free_t](#jerry_arraybuffer_free_t).
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef uint8_t *(*jerry_arraybuffer_allocate_t) (jerry_arraybuffer_type_t buffer_type, uint32_t buffer_size,
|
||||
void **arraybuffer_user_p, void *user_p);
|
||||
```
|
||||
|
||||
- `buffer_type` - type of the array buffer object, see: [jerry_arraybuffer_type_t](#jerry_arraybuffer_type_t).
|
||||
- `buffer_size` - size of the requested buffer.
|
||||
- `arraybuffer_user_p` - [in/out] user pointer assigned to the array buffer or shared array buffer object.
|
||||
- `user_p` - user pointer passed to [jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
- return value
|
||||
- Pointer to the buffer, if the allocation is successful, NULL otherwise.
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
|
||||
## jerry_arraybuffer_free_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Callback for freeing the backing store of array buffer or shared array buffer objects.
|
||||
|
||||
*Note*:
|
||||
- The value passed to `arraybuffer_user_p` is always NULL unless the buffer is created by
|
||||
[jerry_create_arraybuffer_external](#jerry_create_arraybuffer_external) or
|
||||
[jerry_create_shared_arraybuffer_external](#jerry_create_shared_arraybuffer_external),
|
||||
or the value is modified by [jerry_arraybuffer_allocate_t](#jerry_arraybuffer_allocate_t).
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef void (*jerry_arraybuffer_free_t) (jerry_arraybuffer_type_t buffer_type, uint8_t *buffer_p,
|
||||
uint32_t buffer_size, void *arraybuffer_user_p, void *user_p);
|
||||
```
|
||||
|
||||
- `buffer_type` - type of the array buffer object, see: [jerry_arraybuffer_type_t](#jerry_arraybuffer_type_t).
|
||||
- `buffer_p` - pointer to the allocated buffer.
|
||||
- `buffer_size` - size of the allocated buffer.
|
||||
- `arraybuffer_user_p` - [in/out] user pointer assigned to the array buffer or shared array buffer object.
|
||||
- `user_p` - user pointer passed to [jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
|
||||
|
||||
# General engine functions
|
||||
|
||||
@@ -6893,9 +6973,11 @@ jerry_create_array (uint32_t size);
|
||||
Create a jerry_value_t representing an ArrayBuffer object.
|
||||
|
||||
*Note*:
|
||||
- This API depends on the es.next profile.
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
|
||||
when it is no longer needed.
|
||||
- This API depends on a build option (`JERRY_BUILTIN_TYPEDARRAY`) and can be checked
|
||||
in runtime with the `JERRY_FEATURE_TYPEDARRAY` feature enum value,
|
||||
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
|
||||
when it is no longer needed.
|
||||
|
||||
**Prototype**
|
||||
|
||||
@@ -6904,7 +6986,7 @@ jerry_value_t
|
||||
jerry_create_arraybuffer (jerry_length_t size);
|
||||
```
|
||||
|
||||
- `size` - size of the ArrayBuffer to create **in bytes**
|
||||
- `size` - size of the backing store allocated for the array buffer **in bytes**.
|
||||
- return value - the new ArrayBuffer as a `jerry_value_t`
|
||||
|
||||
*New in version 2.0*.
|
||||
@@ -6941,29 +7023,31 @@ After the object is not needed the GC will call the `free_cb`
|
||||
so the user can release the buffer which was provided.
|
||||
|
||||
*Note*:
|
||||
- This API depends on the es.next profile.
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
|
||||
when it is no longer needed.
|
||||
- This API depends on a build option (`JERRY_BUILTIN_TYPEDARRAY`) and can be checked
|
||||
in runtime with the `JERRY_FEATURE_TYPEDARRAY` feature enum value,
|
||||
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
|
||||
- If `buffer_p` is NULL, the buffer is allocated by the allocator callback passed to
|
||||
[jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
|
||||
when it is no longer needed.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerry_create_arraybuffer_external (const jerry_length_t size
|
||||
uint8_t *buffer_p,
|
||||
jerry_value_free_callback_t free_cb);
|
||||
uint8_t *buffer_p, void *arraybuffer_user_p);
|
||||
```
|
||||
|
||||
- `size` - size of the buffer to use **in bytes** (should not be 0)
|
||||
- `buffer_p` - the buffer used for the Array Buffer object (should not be a null pointer)
|
||||
- `free_cb` - the callback function called when the object is released
|
||||
- `size` - size of the buffer **in bytes**.
|
||||
- `buffer_p` - the backing store used by the array buffer object.
|
||||
- `arraybuffer_user_p` - user pointer assigned to the array buffer object.
|
||||
- return value
|
||||
- the new ArrayBuffer as a `jerry_value_t`
|
||||
- if the `size` is zero or `buffer_p` is a null pointer this will return an empty ArrayBuffer.
|
||||
- value of the newly construced array buffer object.
|
||||
|
||||
*New in version 2.0*.
|
||||
|
||||
*Changed in version [[NEXT_RELEASE]]*: type of `free_cb` has been changed.
|
||||
*Changed in version [[NEXT_RELEASE]]*: `free_cb` has been replaced by `arraybuffer_user_p`.
|
||||
|
||||
**Example**
|
||||
|
||||
@@ -6995,7 +7079,7 @@ jerry_create_arraybuffer_external (const jerry_length_t size
|
||||
Create a jerry_value_t representing a SharedArrayBuffer object.
|
||||
|
||||
*Note*:
|
||||
- This API depends on the es.next profile.
|
||||
- This API depends on a build option (`JERRY_BUILTIN_SHAREDARRAYBUFFER`).
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
|
||||
when it is no longer needed.
|
||||
|
||||
@@ -7006,7 +7090,7 @@ jerry_value_t
|
||||
jerry_create_shared_arraybuffer (jerry_length_t size);
|
||||
```
|
||||
|
||||
- `size` - size of the SharedArrayBuffer to create **in bytes**
|
||||
- `size` - size of the backing store allocated for the shared array buffer **in bytes**.
|
||||
- return value - the new SharedArrayBuffer as a `jerry_value_t`
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
@@ -7043,7 +7127,9 @@ After the object is not needed the GC will call the `free_cb`
|
||||
so the user can release the buffer which was provided.
|
||||
|
||||
*Note*:
|
||||
- This API depends on the es.next profile.
|
||||
- This API depends on a build option (`JERRY_BUILTIN_SHAREDARRAYBUFFER`).
|
||||
- If `buffer_p` is NULL, the buffer is allocated by the allocator callback passed to
|
||||
[jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
|
||||
when it is no longer needed.
|
||||
|
||||
@@ -7056,12 +7142,11 @@ jerry_create_shared_arraybuffer_external (const jerry_length_t size
|
||||
jerry_value_free_callback_t free_cb);
|
||||
```
|
||||
|
||||
- `size` - size of the buffer to use **in bytes** (should not be 0)
|
||||
- `buffer_p` - the buffer used for the Shared Array Buffer object (should not be a null pointer)
|
||||
- `free_cb` - the callback function called when the object is released
|
||||
- `size` - size of the buffer **in bytes**.
|
||||
- `buffer_p` - the backing store used by the shared array buffer object.
|
||||
- `arraybuffer_user_p` - user pointer assigned to the shared array buffer object.
|
||||
- return value
|
||||
- the new SharedArrayBuffer as a `jerry_value_t`
|
||||
- if the `size` is zero or `buffer_p` is a null pointer this will return an empty SharedArrayBuffer.
|
||||
- value of the newly construced shared array buffer object.
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
@@ -12702,6 +12787,231 @@ jerry_detach_arraybuffer (const jerry_value_t value);
|
||||
|
||||
- [jerry_is_arraybuffer_detachable](#jerry_is_arraybuffer_detachable)
|
||||
|
||||
## jerry_arraybuffer_has_buffer
|
||||
|
||||
**Summary**
|
||||
|
||||
Checks whether a buffer is currently allocated for an array buffer or typed array.
|
||||
|
||||
*Notes*:
|
||||
- This API depends on a build option (`JERRY_BUILTIN_TYPEDARRAY`) and can be checked
|
||||
in runtime with the `JERRY_FEATURE_TYPEDARRAY` feature enum value,
|
||||
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
bool
|
||||
jerry_arraybuffer_has_buffer (const jerry_value_t value);
|
||||
```
|
||||
|
||||
- `value` - array buffer or typed array value.
|
||||
- return
|
||||
- true, if a buffer is allocated for an array buffer or typed array
|
||||
- false, otherwise
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_value_t array_buffer_value = jerry_create_arraybuffer (1024 * 1024);
|
||||
|
||||
/* By default, the backing store of large array buffers
|
||||
* is allocated when it is used the first time. */
|
||||
|
||||
if (!jerry_arraybuffer_has_buffer (array_buffer_value))
|
||||
{
|
||||
/* Code enters here in this case. */
|
||||
}
|
||||
|
||||
jerry_release_value (array_buffer_value);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_create_arraybuffer_external](#jerry_create_arraybuffer_external)
|
||||
- [jerry_create_shared_arraybuffer_external](#jerry_create_shared_arraybuffer_external)
|
||||
- [jerry_arraybuffer_set_compact_allocation_limit](#jerry_arraybuffer_set_compact_allocation_limit)
|
||||
- [jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
|
||||
## jerry_arraybuffer_set_compact_allocation_limit
|
||||
|
||||
**Summary**
|
||||
|
||||
Array buffers which size is less or equal than the limit passed to this
|
||||
function are allocated in a single memory block. The allocator callbacks set by
|
||||
[jerry_arraybuffer_set_allocation_callbacks](#jerry_arraybuffer_set_allocation_callbacks)
|
||||
are not called for these array buffers.
|
||||
|
||||
*Notes*:
|
||||
- This API depends on a build option (`JERRY_BUILTIN_TYPEDARRAY`) and can be checked
|
||||
in runtime with the `JERRY_FEATURE_TYPEDARRAY` feature enum value,
|
||||
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
|
||||
- The default limit is 256 bytes.
|
||||
- When an array buffer is allocated in a single memory block, its
|
||||
backing store is not freed when the array buffer is detached.
|
||||
- This limit does not affect shared array buffers, their backing store is always
|
||||
allocated by the allocator callback.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void
|
||||
jerry_arraybuffer_set_compact_allocation_limit (const jerry_length_t allocation_limit);
|
||||
```
|
||||
|
||||
- `allocation_limit` - maximum size of compact allocation.
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_arraybuffer_set_compact_allocation_limit (1);
|
||||
|
||||
jerry_value_t array_buffer_value = jerry_create_arraybuffer (1);
|
||||
|
||||
if (jerry_arraybuffer_has_buffer (array_buffer_value))
|
||||
{
|
||||
/* Code enters here because the backing store
|
||||
* is allocated during buffer creation. */
|
||||
}
|
||||
|
||||
jerry_release_value (array_buffer_value);
|
||||
|
||||
array_buffer_value = jerry_create_arraybuffer (2);
|
||||
|
||||
if (jerry_arraybuffer_has_buffer (array_buffer_value))
|
||||
{
|
||||
/* Code does not enter here because the backing store
|
||||
* is allocated when it is used the first time. */
|
||||
}
|
||||
|
||||
jerry_release_value (array_buffer_value);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_arraybuffer_has_buffer](#jerry_arraybuffer_has_buffer)
|
||||
- [jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
|
||||
## jerry_arraybuffer_set_allocator_callbacks
|
||||
|
||||
**Summary**
|
||||
|
||||
Set callbacks for allocating and freeing backing stores for array buffer objects.
|
||||
|
||||
*Notes*:
|
||||
- This API depends on a build option (`JERRY_BUILTIN_TYPEDARRAY`) and can be checked
|
||||
in runtime with the `JERRY_FEATURE_TYPEDARRAY` feature enum value,
|
||||
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
|
||||
- This function is recommended to be called after [jerry_init](#jerry_init) before
|
||||
any array buffer is allocated.
|
||||
- The callbacks can be NULL to use the default callbacks. The default `allocate_callback`
|
||||
allocates memory using [jerry_heap_alloc](#jerry_heap_alloc) and the default
|
||||
`free_callback` frees memory using [jerry_heap_free](#jerry_heap_free).
|
||||
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void
|
||||
jerry_arraybuffer_set_allocator_callbacks (jerry_arraybuffer_allocate_t allocate_callback,
|
||||
jerry_arraybuffer_free_t free_callback,
|
||||
void *user_p)
|
||||
```
|
||||
|
||||
- `allocate_callback` - callback for allocating array buffer memory.
|
||||
- `free_callback` - callback for freeing array buffer memory.
|
||||
- `user_p` - user pointer passed to the callbacks.
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
|
||||
static uint8_t global_buffer[64];
|
||||
|
||||
static void
|
||||
array_buffer_free_cb (jerry_arraybuffer_type_t buffer_type, /**< type of the array buffer object */
|
||||
uint8_t *buffer_p, /**< pointer to the allocated buffer */
|
||||
uint32_t buffer_size, /**< size of the allocated buffer */
|
||||
void *arraybuffer_user_p, /**< user pointer assigned to the array buffer object */
|
||||
void *user_p) /**< user pointer passed to jerry_arraybuffer_set_allocation_callbacks */
|
||||
{
|
||||
(void) buffer_type;
|
||||
(void) user_p;
|
||||
|
||||
/* As for this example, only the free callback is redirected. This callback
|
||||
* function does not free the memory if the arraybuffer_user_p is non-NULL. */
|
||||
|
||||
if (arraybuffer_user_p == NULL)
|
||||
{
|
||||
jerry_heap_free (buffer_p, buffer_size);
|
||||
}
|
||||
} /* array_buffer_free_cb */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_arraybuffer_set_allocator_callbacks (NULL, array_buffer_free_cb, NULL);
|
||||
|
||||
/* The buffer of the array buffer object is allocated by the default
|
||||
* allocator using jerry_heap_alloc and freed by array_buffer_free_cb. */
|
||||
|
||||
const jerry_char_t script[] = "var result = new uint32Array(1024); result[0] = 1; result";
|
||||
jerry_value_t array_buffer_value = jerry_eval (script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS);
|
||||
jerry_release_value (array_buffer_value);
|
||||
|
||||
/* The buffer of the array buffer object has a non-NULL
|
||||
* arraybuffer_user_p value, so it is not freed by array_buffer_free_cb. */
|
||||
|
||||
array_buffer_value = jerry_create_arraybuffer_external (sizeof (global_buffer), global_buffer, global_buffer);
|
||||
jerry_release_value (array_buffer_value);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_arraybuffer_has_buffer](#jerry_arraybuffer_has_buffer)
|
||||
- [jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
|
||||
## jerry_get_dataview_buffer
|
||||
|
||||
**Summary**
|
||||
|
||||
Reference in New Issue
Block a user