Allocate buffers when the buffer pointer is requested (#4812)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
+41
-17
@@ -6072,6 +6072,29 @@ jerry_create_shared_arraybuffer_external (const jerry_length_t size, /**< size o
|
|||||||
#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */
|
#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */
|
||||||
} /* jerry_create_shared_arraybuffer_external */
|
} /* jerry_create_shared_arraybuffer_external */
|
||||||
|
|
||||||
|
#if JERRY_BUILTIN_TYPEDARRAY
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a backing store for an array buffer, ignores allocation fails.
|
||||||
|
*
|
||||||
|
* @return true on success,
|
||||||
|
* false otherwise
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
jerry_arraybuffer_allocate_buffer_no_throw (ecma_object_t *arraybuffer_p) /**< ArrayBuffer object */
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED));
|
||||||
|
|
||||||
|
if (ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_DETACHED)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ecma_arraybuffer_allocate_buffer (arraybuffer_p) != NULL;
|
||||||
|
} /* jerry_arraybuffer_allocate_buffer_no_throw */
|
||||||
|
|
||||||
|
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy bytes into the ArrayBuffer or SharedArrayBuffer from a buffer.
|
* Copy bytes into the ArrayBuffer or SharedArrayBuffer from a buffer.
|
||||||
*
|
*
|
||||||
@@ -6094,15 +6117,15 @@ jerry_arraybuffer_write (const jerry_value_t value, /**< target ArrayBuffer or S
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
|
ecma_object_t *arraybuffer_p = ecma_get_object_from_value (value);
|
||||||
|
|
||||||
if (ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR (buffer_p))
|
if (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)
|
||||||
|
&& !jerry_arraybuffer_allocate_buffer_no_throw (arraybuffer_p))
|
||||||
{
|
{
|
||||||
jerry_release_value (jcontext_take_exception ());
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
jerry_length_t length = ecma_arraybuffer_get_length (buffer_p);
|
jerry_length_t length = ecma_arraybuffer_get_length (arraybuffer_p);
|
||||||
|
|
||||||
if (offset >= length)
|
if (offset >= length)
|
||||||
{
|
{
|
||||||
@@ -6113,9 +6136,9 @@ jerry_arraybuffer_write (const jerry_value_t value, /**< target ArrayBuffer or S
|
|||||||
|
|
||||||
if (copy_count > 0)
|
if (copy_count > 0)
|
||||||
{
|
{
|
||||||
lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
|
lit_utf8_byte_t *buffer_p = ecma_arraybuffer_get_buffer (arraybuffer_p);
|
||||||
|
|
||||||
memcpy ((void *) (mem_buffer_p + offset), (void *) buf_p, copy_count);
|
memcpy ((void *) (buffer_p + offset), (void *) buf_p, copy_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
return copy_count;
|
return copy_count;
|
||||||
@@ -6150,15 +6173,15 @@ jerry_arraybuffer_read (const jerry_value_t value, /**< ArrayBuffer or SharedArr
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
|
ecma_object_t *arraybuffer_p = ecma_get_object_from_value (value);
|
||||||
|
|
||||||
if (ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR (buffer_p))
|
if (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)
|
||||||
|
&& !jerry_arraybuffer_allocate_buffer_no_throw (arraybuffer_p))
|
||||||
{
|
{
|
||||||
jerry_release_value (jcontext_take_exception ());
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
jerry_length_t length = ecma_arraybuffer_get_length (buffer_p);
|
jerry_length_t length = ecma_arraybuffer_get_length (arraybuffer_p);
|
||||||
|
|
||||||
if (offset >= length)
|
if (offset >= length)
|
||||||
{
|
{
|
||||||
@@ -6169,9 +6192,9 @@ jerry_arraybuffer_read (const jerry_value_t value, /**< ArrayBuffer or SharedArr
|
|||||||
|
|
||||||
if (copy_count > 0)
|
if (copy_count > 0)
|
||||||
{
|
{
|
||||||
lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
|
lit_utf8_byte_t *buffer_p = ecma_arraybuffer_get_buffer (arraybuffer_p);
|
||||||
|
|
||||||
memcpy ((void *) buf_p, (void *) (mem_buffer_p + offset), copy_count);
|
memcpy ((void *) buf_p, (void *) (buffer_p + offset), copy_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
return copy_count;
|
return copy_count;
|
||||||
@@ -6200,8 +6223,8 @@ jerry_get_arraybuffer_byte_length (const jerry_value_t value) /**< ArrayBuffer o
|
|||||||
#if JERRY_BUILTIN_TYPEDARRAY
|
#if JERRY_BUILTIN_TYPEDARRAY
|
||||||
if (ecma_is_arraybuffer (value) || ecma_is_shared_arraybuffer (value))
|
if (ecma_is_arraybuffer (value) || ecma_is_shared_arraybuffer (value))
|
||||||
{
|
{
|
||||||
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
|
ecma_object_t *arraybuffer_p = ecma_get_object_from_value (value);
|
||||||
return ecma_arraybuffer_get_length (buffer_p);
|
return ecma_arraybuffer_get_length (arraybuffer_p);
|
||||||
}
|
}
|
||||||
#else /* !JERRY_BUILTIN_TYPEDARRAY */
|
#else /* !JERRY_BUILTIN_TYPEDARRAY */
|
||||||
JERRY_UNUSED (value);
|
JERRY_UNUSED (value);
|
||||||
@@ -6232,14 +6255,15 @@ jerry_get_arraybuffer_pointer (const jerry_value_t array_buffer) /**< Array Buff
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ecma_object_t *buffer_p = ecma_get_object_from_value (array_buffer);
|
ecma_object_t *arraybuffer_p = ecma_get_object_from_value (array_buffer);
|
||||||
|
|
||||||
if (!(ECMA_ARRAYBUFFER_GET_FLAGS (buffer_p) & ECMA_ARRAYBUFFER_ALLOCATED))
|
if (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)
|
||||||
|
&& !jerry_arraybuffer_allocate_buffer_no_throw (arraybuffer_p))
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (uint8_t *) ecma_arraybuffer_get_buffer (buffer_p);
|
return (uint8_t *) ecma_arraybuffer_get_buffer (arraybuffer_p);
|
||||||
#else /* !JERRY_BUILTIN_TYPEDARRAY */
|
#else /* !JERRY_BUILTIN_TYPEDARRAY */
|
||||||
JERRY_UNUSED (array_buffer);
|
JERRY_UNUSED (array_buffer);
|
||||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||||
|
|||||||
@@ -128,26 +128,21 @@ ecma_arraybuffer_new_object (uint32_t length) /**< length of the arraybuffer */
|
|||||||
/**
|
/**
|
||||||
* Allocate a backing store for an array buffer.
|
* Allocate a backing store for an array buffer.
|
||||||
*
|
*
|
||||||
* @return ECMA_VALUE_UNDEFINED on success,
|
* @return buffer pointer on success,
|
||||||
* ECMA_VALUE_ERROR otherwise
|
* NULL otherwise
|
||||||
*/
|
*/
|
||||||
ecma_value_t
|
uint8_t *
|
||||||
ecma_arraybuffer_allocate_buffer (ecma_object_t *object_p) /**< ArrayBuffer object */
|
ecma_arraybuffer_allocate_buffer (ecma_object_t *arraybuffer_p) /**< ArrayBuffer object */
|
||||||
{
|
{
|
||||||
JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_ALLOCATED));
|
JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED));
|
||||||
|
JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_DETACHED));
|
||||||
|
JERRY_ASSERT (ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_HAS_POINTER);
|
||||||
|
|
||||||
if (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_DETACHED)
|
ecma_extended_object_t *extended_object_p = (ecma_extended_object_t *) arraybuffer_p;
|
||||||
{
|
|
||||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
|
||||||
}
|
|
||||||
|
|
||||||
JERRY_ASSERT (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_HAS_POINTER);
|
|
||||||
|
|
||||||
ecma_extended_object_t *extended_object_p = (ecma_extended_object_t *) object_p;
|
|
||||||
uint32_t arraybuffer_length = extended_object_p->u.cls.u3.length;
|
uint32_t arraybuffer_length = extended_object_p->u.cls.u3.length;
|
||||||
ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) object_p;
|
ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) arraybuffer_p;
|
||||||
jerry_arraybuffer_allocate_t arraybuffer_allocate_callback = JERRY_CONTEXT (arraybuffer_allocate_callback);
|
jerry_arraybuffer_allocate_t arraybuffer_allocate_callback = JERRY_CONTEXT (arraybuffer_allocate_callback);
|
||||||
void *buffer_p;
|
uint8_t *buffer_p;
|
||||||
|
|
||||||
if (arraybuffer_allocate_callback != NULL)
|
if (arraybuffer_allocate_callback != NULL)
|
||||||
{
|
{
|
||||||
@@ -167,33 +162,59 @@ ecma_arraybuffer_allocate_buffer (ecma_object_t *object_p) /**< ArrayBuffer obje
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buffer_p = jmem_heap_alloc_block_null_on_error (arraybuffer_length);
|
buffer_p = (uint8_t *) jmem_heap_alloc_block_null_on_error (arraybuffer_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer_p == NULL)
|
if (buffer_p == NULL)
|
||||||
{
|
{
|
||||||
extended_object_p->u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_DETACHED;
|
extended_object_p->u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_DETACHED;
|
||||||
return ecma_raise_range_error (ECMA_ERR_MSG ("Cannot allocate memory for ArrayBuffer"));
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
arraybuffer_pointer_p->buffer_p = buffer_p;
|
arraybuffer_pointer_p->buffer_p = buffer_p;
|
||||||
extended_object_p->u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_ALLOCATED;
|
extended_object_p->u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_ALLOCATED;
|
||||||
|
|
||||||
memset (buffer_p, 0, arraybuffer_length);
|
memset (buffer_p, 0, arraybuffer_length);
|
||||||
return ECMA_VALUE_UNDEFINED;
|
return buffer_p;
|
||||||
} /* ecma_arraybuffer_allocate_buffer */
|
} /* ecma_arraybuffer_allocate_buffer */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a backing store for an array buffer, throws an error if the allocation fails.
|
||||||
|
*
|
||||||
|
* @return ECMA_VALUE_UNDEFINED on success,
|
||||||
|
* ECMA_VALUE_ERROR otherwise
|
||||||
|
*/
|
||||||
|
ecma_value_t
|
||||||
|
ecma_arraybuffer_allocate_buffer_throw (ecma_object_t *arraybuffer_p)
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED));
|
||||||
|
|
||||||
|
if (ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_DETACHED)
|
||||||
|
{
|
||||||
|
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *buffer_p = ecma_arraybuffer_allocate_buffer (arraybuffer_p);
|
||||||
|
|
||||||
|
if (buffer_p == NULL)
|
||||||
|
{
|
||||||
|
return ecma_raise_range_error (ECMA_ERR_MSG ("Cannot allocate memory for ArrayBuffer"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ECMA_VALUE_UNDEFINED;
|
||||||
|
} /* ecma_arraybuffer_allocate_buffer_throw */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Release the backing store allocated by an array buffer.
|
* Release the backing store allocated by an array buffer.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ecma_arraybuffer_release_buffer (ecma_object_t *object_p) /**< ArrayBuffer object */
|
ecma_arraybuffer_release_buffer (ecma_object_t *arraybuffer_p) /**< ArrayBuffer object */
|
||||||
{
|
{
|
||||||
JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)
|
JERRY_ASSERT (ecma_object_class_is (arraybuffer_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)
|
||||||
|| ecma_object_is_shared_arraybuffer (object_p));
|
|| ecma_object_is_shared_arraybuffer (arraybuffer_p));
|
||||||
|
|
||||||
jerry_arraybuffer_free_t free_callback = JERRY_CONTEXT (arraybuffer_free_callback);
|
jerry_arraybuffer_free_t free_callback = JERRY_CONTEXT (arraybuffer_free_callback);
|
||||||
ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) object_p;
|
ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) arraybuffer_p;
|
||||||
uint32_t arraybuffer_length = arraybuffer_pointer_p->extended_object.u.cls.u3.length;
|
uint32_t arraybuffer_length = arraybuffer_pointer_p->extended_object.u.cls.u3.length;
|
||||||
|
|
||||||
if (free_callback == NULL)
|
if (free_callback == NULL)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
*/
|
*/
|
||||||
#define ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR(arraybuffer_p) \
|
#define ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR(arraybuffer_p) \
|
||||||
(JERRY_UNLIKELY (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)) \
|
(JERRY_UNLIKELY (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)) \
|
||||||
&& ecma_arraybuffer_allocate_buffer (arraybuffer_p) == ECMA_VALUE_ERROR)
|
&& ecma_arraybuffer_allocate_buffer_throw (arraybuffer_p) == ECMA_VALUE_ERROR)
|
||||||
|
|
||||||
ecma_value_t
|
ecma_value_t
|
||||||
ecma_op_create_arraybuffer_object (const ecma_value_t *, uint32_t);
|
ecma_op_create_arraybuffer_object (const ecma_value_t *, uint32_t);
|
||||||
@@ -52,10 +52,12 @@ ecma_object_t *
|
|||||||
ecma_arraybuffer_create_object_with_buffer (uint8_t type, uint32_t length);
|
ecma_arraybuffer_create_object_with_buffer (uint8_t type, uint32_t length);
|
||||||
ecma_object_t *
|
ecma_object_t *
|
||||||
ecma_arraybuffer_new_object (uint32_t length);
|
ecma_arraybuffer_new_object (uint32_t length);
|
||||||
|
uint8_t *
|
||||||
|
ecma_arraybuffer_allocate_buffer (ecma_object_t *arraybuffer_p);
|
||||||
ecma_value_t
|
ecma_value_t
|
||||||
ecma_arraybuffer_allocate_buffer (ecma_object_t *object_p);
|
ecma_arraybuffer_allocate_buffer_throw (ecma_object_t *arraybuffer_p);
|
||||||
void
|
void
|
||||||
ecma_arraybuffer_release_buffer (ecma_object_t *object_p);
|
ecma_arraybuffer_release_buffer (ecma_object_t *arraybuffer_p);
|
||||||
uint8_t * JERRY_ATTR_PURE
|
uint8_t * JERRY_ATTR_PURE
|
||||||
ecma_arraybuffer_get_buffer (ecma_object_t *obj_p);
|
ecma_arraybuffer_get_buffer (ecma_object_t *obj_p);
|
||||||
uint32_t JERRY_ATTR_PURE
|
uint32_t JERRY_ATTR_PURE
|
||||||
|
|||||||
@@ -376,6 +376,8 @@ main (void)
|
|||||||
|
|
||||||
uint8_t *const data = jerry_get_arraybuffer_pointer (buffer);
|
uint8_t *const data = jerry_get_arraybuffer_pointer (buffer);
|
||||||
|
|
||||||
|
TEST_ASSERT (data != NULL);
|
||||||
|
|
||||||
/* test memory read */
|
/* test memory read */
|
||||||
for (int i = 0; i < 20; i++)
|
for (int i = 0; i < 20; i++)
|
||||||
{
|
{
|
||||||
@@ -472,6 +474,7 @@ main (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Test ArrayBuffer created in ECMAScript */
|
/* Test ArrayBuffer created in ECMAScript */
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
const jerry_char_t source[] = TEST_STRING_LITERAL ("new ArrayBuffer(64)");
|
const jerry_char_t source[] = TEST_STRING_LITERAL ("new ArrayBuffer(64)");
|
||||||
jerry_value_t arraybuffer = jerry_eval (source, sizeof (source) - 1, JERRY_PARSE_NO_OPTS);
|
jerry_value_t arraybuffer = jerry_eval (source, sizeof (source) - 1, JERRY_PARSE_NO_OPTS);
|
||||||
@@ -479,8 +482,23 @@ main (void)
|
|||||||
TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
|
TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
|
||||||
TEST_ASSERT (!jerry_arraybuffer_has_buffer (arraybuffer));
|
TEST_ASSERT (!jerry_arraybuffer_has_buffer (arraybuffer));
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
uint8_t buf[2] = { 2, 3 };
|
uint8_t buf[2] = { 2, 3 };
|
||||||
TEST_ASSERT (jerry_arraybuffer_write (arraybuffer, 63, buf, 2) == 1);
|
TEST_ASSERT (jerry_arraybuffer_write (arraybuffer, 63, buf, 2) == 1);
|
||||||
|
}
|
||||||
|
else if (i == 1)
|
||||||
|
{
|
||||||
|
uint8_t buf[2] = { 1, 1 };
|
||||||
|
TEST_ASSERT (jerry_arraybuffer_read (arraybuffer, 63, buf, 2) == 1);
|
||||||
|
TEST_ASSERT (buf[0] == 0 && buf[1] == 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint8_t *buffer_p = jerry_get_arraybuffer_pointer (arraybuffer);
|
||||||
|
TEST_ASSERT (buffer_p != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_ASSERT (jerry_arraybuffer_has_buffer (arraybuffer));
|
TEST_ASSERT (jerry_arraybuffer_has_buffer (arraybuffer));
|
||||||
|
|
||||||
jerry_release_value (arraybuffer);
|
jerry_release_value (arraybuffer);
|
||||||
|
|||||||
Reference in New Issue
Block a user