Add ArrayBuffer with user specified buffer

New API functions:
 - jerry_create_arraybuffer_external
 - jerry_get_arraybuffer_pointer

JerryScript-DCO-1.0-Signed-off-by: Peter Gal pgal.u-szeged@partner.samsung.com
This commit is contained in:
Peter Gal
2018-01-08 15:35:18 +01:00
committed by yichoi
parent 7acd688513
commit 4b699e997a
8 changed files with 416 additions and 5 deletions
+75
View File
@@ -2670,6 +2670,42 @@ jerry_create_arraybuffer (const jerry_length_t size) /**< size of the ArrayBuffe
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
} /* jerry_create_arraybuffer */
/**
* Creates an ArrayBuffer object with user specified buffer.
*
* Notes:
* * the size is specified in bytes.
* * the buffer passed should be at least the specified bytes big.
* * if the typed arrays are disabled this will return a TypeError.
* * if the size is zero or the buffer_p is a null pointer this will return a RangeError.
*
* @return value of the construced ArrayBuffer object
*/
jerry_value_t
jerry_create_arraybuffer_external (const jerry_length_t size, /**< size of the buffer to used */
uint8_t *buffer_p, /**< buffer to use as the ArrayBuffer's backing */
jerry_object_native_free_callback_t free_cb) /**< buffer free callback */
{
jerry_assert_api_available ();
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
if (size == 0 || buffer_p == NULL)
{
return jerry_throw (ecma_raise_range_error (ECMA_ERR_MSG ("invalid buffer size or storage reference")));
}
ecma_object_t *arraybuffer = ecma_arraybuffer_new_object_external (size,
buffer_p,
(ecma_object_native_free_callback_t) free_cb);
return jerry_return (ecma_make_object_value (arraybuffer));
#else /* CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
JERRY_UNUSED (size);
JERRY_UNUSED (buffer_p);
JERRY_UNUSED (free_cb);
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer not supported.")));
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
} /* jerry_create_arraybuffer_external */
/**
* Copy bytes into the ArrayBuffer from a buffer.
*
@@ -2798,6 +2834,45 @@ jerry_get_arraybuffer_byte_length (const jerry_value_t value) /**< ArrayBuffer *
return 0;
} /* jerry_get_arraybuffer_byte_length */
/**
* Get a pointer for the start of the ArrayBuffer.
*
* Note:
* * Only valid for ArrayBuffers created with jerry_create_arraybuffer_external.
* * This is a high-risk operation as the bounds are not checked
* when accessing the pointer elements.
* * jerry_release_value must be called on the ArrayBuffer when the pointer is no longer needed.
*
* @return pointer to the back-buffer of the ArrayBuffer.
* pointer is NULL if the parameter is not an ArrayBuffer with external memory
or it is not an ArrayBuffer at all.
*/
uint8_t *
jerry_get_arraybuffer_pointer (const jerry_value_t value) /**< Array Buffer to use */
{
jerry_assert_api_available ();
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
jerry_value_t buffer = jerry_get_arg_value (value);
if (!ecma_is_arraybuffer (buffer))
{
return NULL;
}
ecma_object_t *buffer_p = ecma_get_object_from_value (buffer);
if (ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY (buffer_p))
{
jerry_acquire_value (value);
lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
return (uint8_t *const) mem_buffer_p;
}
#else /* CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
JERRY_UNUSED (value);
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
return NULL;
} /* jerry_get_arraybuffer_pointer */
/**
* @}
*/
+20 -2
View File
@@ -570,11 +570,29 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
case LIT_MAGIC_STRING_ARRAY_BUFFER_UL:
{
ecma_length_t arraybuffer_length = ext_object_p->u.class_prop.u.length;
size_t size = sizeof (ecma_extended_object_t) + arraybuffer_length;
size_t size;
if (ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY (ext_object_p))
{
size = sizeof (ecma_arraybuffer_external_info);
/* Call external free callback if any. */
ecma_arraybuffer_external_info *array_p = (ecma_arraybuffer_external_info *) ext_object_p;
JERRY_ASSERT (array_p != NULL);
if (array_p->free_cb != NULL)
{
(array_p->free_cb) (array_p->buffer_p);
}
}
else
{
size = sizeof (ecma_extended_object_t) + arraybuffer_length;
}
ecma_dealloc_extended_object (object_p, size);
return;
}
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
case LIT_MAGIC_STRING_PROMISE_UL:
+29
View File
@@ -712,6 +712,8 @@ typedef struct
struct
{
uint16_t class_id; /**< class id of the object */
uint16_t extra_info; /**< extra information for the object
e.g. array buffer type info (external/internal) */
/*
* Description of extra fields. These extra fields depends on the class_id.
@@ -1243,6 +1245,33 @@ typedef struct
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
/**
* Extra information for ArrayBuffers.
*/
typedef enum
{
ECMA_ARRAYBUFFER_INTERNAL_MEMORY = 0u, /* ArrayBuffer memory is handled internally. */
ECMA_ARRAYBUFFER_EXTERNAL_MEMORY = (1u << 0), /* ArrayBuffer created via jerry_create_arraybuffer_external. */
} ecma_arraybuffer_extra_flag_t;
#define ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY(object_p) \
((((ecma_extended_object_t *) object_p)->u.class_prop.extra_info & ECMA_ARRAYBUFFER_EXTERNAL_MEMORY) != 0)
/**
* Struct to store information for ArrayBuffers with external memory.
*
* The following elements are stored in Jerry memory.
*
* buffer_p - pointer to the external memory.
* free_cb - pointer to a callback function which is called when the ArrayBuffer is freed.
*/
typedef struct
{
ecma_extended_object_t extended_object; /**< extended object part */
void *buffer_p; /**< external buffer pointer */
ecma_object_native_free_callback_t free_cb; /**< the free callback for the above buffer pointer */
} ecma_arraybuffer_external_info;
/**
* Some internal properties of TypedArray object.
* It is only used when the offset is not 0, and
@@ -51,6 +51,7 @@ ecma_arraybuffer_new_object (ecma_length_t length) /**< length of the arraybuffe
ECMA_OBJECT_TYPE_CLASS);
ecma_deref_object (prototype_obj_p);
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
ext_object_p->u.class_prop.extra_info = ECMA_ARRAYBUFFER_INTERNAL_MEMORY;
ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_ARRAY_BUFFER_UL;
ext_object_p->u.class_prop.u.length = length;
@@ -60,6 +61,38 @@ ecma_arraybuffer_new_object (ecma_length_t length) /**< length of the arraybuffe
return object_p;
} /* ecma_arraybuffer_new_object */
/**
* Helper function: create arraybuffer object with external buffer backing.
*
* The struct of external arraybuffer object:
* ecma_object_t
* extend_part
* arraybuffer external info part
*
* @return ecma_object_t *, pointer to the created ArrayBuffer object
*/
ecma_object_t *
ecma_arraybuffer_new_object_external (ecma_length_t length, /**< length of the buffer_p to use */
void *buffer_p, /**< pointer for ArrayBuffer's buffer backing */
ecma_object_native_free_callback_t free_cb) /**< buffer free callback */
{
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE);
ecma_object_t *object_p = ecma_create_object (prototype_obj_p,
sizeof (ecma_arraybuffer_external_info),
ECMA_OBJECT_TYPE_CLASS);
ecma_deref_object (prototype_obj_p);
ecma_arraybuffer_external_info *array_object_p = (ecma_arraybuffer_external_info *) object_p;
array_object_p->extended_object.u.class_prop.extra_info = ECMA_ARRAYBUFFER_EXTERNAL_MEMORY;
array_object_p->extended_object.u.class_prop.class_id = LIT_MAGIC_STRING_ARRAY_BUFFER_UL;
array_object_p->extended_object.u.class_prop.u.length = length;
array_object_p->buffer_p = buffer_p;
array_object_p->free_cb = free_cb;
return object_p;
} /* ecma_arraybuffer_new_object_external */
/**
* ArrayBuffer object creation operation.
*
@@ -158,7 +191,16 @@ ecma_arraybuffer_get_buffer (ecma_object_t *object_p) /**< pointer to the ArrayB
JERRY_ASSERT (ecma_object_class_is (object_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL));
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
return (lit_utf8_byte_t *) (ext_object_p + 1);
if (ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY (ext_object_p))
{
ecma_arraybuffer_external_info *array_p = (ecma_arraybuffer_external_info *) ext_object_p;
return (lit_utf8_byte_t *) array_p->buffer_p;
}
else
{
return (lit_utf8_byte_t *) (ext_object_p + 1);
}
} /* ecma_arraybuffer_get_buffer */
/**
@@ -34,6 +34,10 @@ ecma_op_create_arraybuffer_object (const ecma_value_t *, ecma_length_t);
*/
ecma_object_t *
ecma_arraybuffer_new_object (ecma_length_t lengh);
ecma_object_t *
ecma_arraybuffer_new_object_external (ecma_length_t length,
void *buffer_p,
ecma_object_native_free_callback_t free_cb);
lit_utf8_byte_t *
ecma_arraybuffer_get_buffer (ecma_object_t *obj_p) __attr_pure___;
ecma_length_t
+4
View File
@@ -446,6 +446,9 @@ void jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, voi
*/
bool jerry_value_is_arraybuffer (const jerry_value_t value);
jerry_value_t jerry_create_arraybuffer (const jerry_length_t size);
jerry_value_t jerry_create_arraybuffer_external (const jerry_length_t size,
uint8_t *buffer_p,
jerry_object_native_free_callback_t free_cb);
jerry_length_t jerry_arraybuffer_write (const jerry_value_t value,
jerry_length_t offset,
const uint8_t *buf_p,
@@ -455,6 +458,7 @@ jerry_length_t jerry_arraybuffer_read (const jerry_value_t value,
uint8_t *buf_p,
jerry_length_t buf_size);
jerry_length_t jerry_get_arraybuffer_byte_length (const jerry_value_t value);
uint8_t *jerry_get_arraybuffer_pointer (const jerry_value_t value);
/**
* @}