Rework external string free operation (#4690)

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2021-08-17 08:31:30 +02:00
committed by GitHub
parent 74e5ccd434
commit e7ffb70ae0
9 changed files with 187 additions and 44 deletions
+108 -11
View File
@@ -769,6 +769,34 @@ typedef void (*jerry_object_native_free_callback_t) (void *native_p, struct jerr
- [jerry_object_native_info_t](#jerry_object_native_info_t)
## jerry_external_string_free_callback_t
**Summary**
Free callback for external strings. See
[jerry_string_set_external_string_free_callback](#jerry_string_set_external_string_free_callback)
for more information.
**Prototype**
```c
typedef void (*jerry_external_string_free_callback_t) (jerry_char_t *string_p,
jerry_size_t string_size,
void *user_p);
```
- `string_p` - extrenal string pointer
- `string_size` - size of external string
- `user_p` - pointer passed when the external string is created
*New in version [[NEXT_RELEASE]]*.
**See also**
- [jerry_string_set_external_string_free_callback](#jerry_string_set_external_string_free_callback)
- [jerry_create_external_string](#jerry_create_external_string)
- [jerry_create_external_string_sz](#jerry_create_external_string_sz)
## jerry_error_object_created_callback_t
**Summary**
@@ -4195,6 +4223,70 @@ jerry_substring_to_utf8_char_buffer (const jerry_value_t value,
- [jerry_is_valid_utf8_string](#jerry_is_valid_utf8_string)
# jerry_string_set_external_string_free_callback
**Summary**
Sets the global callback which is called when the string data of an external
string is no longer used. It is recommended to set this function before the
first external string is created.
*Note*:
- When the callback is NULL, no function is called when an external string is freed.
- In some cases (e.g. when the string is also a magic string registered by
[jerry_register_magic_strings](#jerry_register_magic_strings)), the callback
is called when the string is created, not when it is released.
**Prototype**
```c
void jerry_string_set_external_string_free_callback (jerry_external_string_free_callback_t callback_p);
```
- `callback_p` - callback which is called when an external string is freed.
*New in version [[NEXT_RELEASE]]*.
**Example**
[doctest]: # ()
```c
#include "jerryscript.h"
#include <stdio.h>
static void
external_string_free_callback (jerry_char_t *string_p, /**< string pointer */
jerry_size_t string_size, /**< size of the string */
void *user_p) /**< user pointer */
{
printf ("External string is freed!\n");
}
int
main (void)
{
jerry_init (JERRY_INIT_EMPTY);
jerry_string_set_external_string_free_callback (external_string_free_callback);
const char *string_p = "This is a long external string, should not be duplicated!";
jerry_value_t external_string = jerry_create_external_string ((jerry_char_t *) string_p, NULL);
/* The external_string_free_callback is called. */
jerry_release_value (external_string);
jerry_cleanup ();
return 0;
}
```
**See also**
- [jerry_external_string_free_callback_t](#jerry_external_string_free_callback_t)
- [jerry_create_external_string](#jerry_create_external_string)
- [jerry_create_external_string_sz](#jerry_create_external_string_sz)
# Functions for array object values
## jerry_get_array_length
@@ -7293,24 +7385,25 @@ Create an external string from a valid CESU8 string. The string buffer passed to
should not be modified until the free callback is called. This function can be used to avoid
the duplication of large strings.
*Note*: Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
is no longer needed.
*Note*:
- The free callback can be set by [jerry_string_set_external_string_free_callback](#jerry_string_set_external_string_free_callback)
- 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_external_string (const jerry_char_t *str_p,
jerry_value_free_callback_t free_cb)
jerry_create_external_string (const jerry_char_t *str_p, void *user_p);
```
- `str_p` - non-null pointer to string
- `free_cb` - optional callback which is called right before the string is freed
- `user_p` - user pointer passed to the callback when the string is freed
- return value - value of the created string
*New in version 2.4*.
*Changed in version [[NEXT_RELEASE]]*: type of `free_cb` has been changed.
*Changed in version [[NEXT_RELEASE]]*: `free_cb` is replaced by `user_p`.
**Example**
@@ -7330,6 +7423,7 @@ jerry_create_external_string (const jerry_char_t *str_p,
- [jerry_is_valid_cesu8_string](#jerry_is_valid_cesu8_string)
- [jerry_create_external_string_sz](#jerry_create_external_string_sz)
- [jerry_string_set_external_string_free_callback](#jerry_string_set_external_string_free_callback)
## jerry_create_external_string_sz
@@ -7340,8 +7434,10 @@ Create an external string from a valid CESU8 string. The string buffer passed to
should not be modified until the free callback is called. This function can be used to avoid
the duplication of large strings.
*Note*: Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
is no longer needed.
*Note*:
- The free callback can be set by [jerry_string_set_external_string_free_callback](#jerry_string_set_external_string_free_callback)
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
when it is no longer needed.
**Prototype**
@@ -7349,17 +7445,17 @@ is no longer needed.
jerry_value_t
jerry_create_external_string_sz (const jerry_char_t *str_p,
jerry_size_t str_size,
jerry_value_free_callback_t free_cb)
void *user_p);
```
- `str_p` - non-null pointer to string
- `str_size` - size of the string
- `free_cb` - optional callback which is called right before the string is freed
- `user_p` - user pointer passed to the callback when the string is freed
- return value - value of the created string
*New in version 2.4*.
*Changed in version [[NEXT_RELEASE]]*: type of `free_cb` has been changed.
*Changed in version [[NEXT_RELEASE]]*: `free_cb` is replaced by `user_p`.
**Example**
@@ -7381,6 +7477,7 @@ jerry_create_external_string_sz (const jerry_char_t *str_p,
- [jerry_is_valid_cesu8_string](#jerry_is_valid_cesu8_string)
- [jerry_create_external_string](#jerry_create_external_string)
- [jerry_string_set_external_string_free_callback](#jerry_string_set_external_string_free_callback)
## jerry_create_symbol
+14 -4
View File
@@ -2700,9 +2700,9 @@ jerry_create_string_sz (const jerry_char_t *str_p, /**< pointer to string */
*/
jerry_value_t
jerry_create_external_string (const jerry_char_t *str_p, /**< pointer to string */
jerry_value_free_callback_t free_cb) /**< free callback */
void *user_p) /**< user pointer passed to the callback when the string is freed */
{
return jerry_create_external_string_sz (str_p, lit_zt_utf8_string_size ((lit_utf8_byte_t *) str_p), free_cb);
return jerry_create_external_string_sz (str_p, lit_zt_utf8_string_size ((lit_utf8_byte_t *) str_p), user_p);
} /* jerry_create_external_string */
/**
@@ -2716,13 +2716,13 @@ jerry_create_external_string (const jerry_char_t *str_p, /**< pointer to string
jerry_value_t
jerry_create_external_string_sz (const jerry_char_t *str_p, /**< pointer to string */
jerry_size_t str_size, /**< string size */
jerry_value_free_callback_t free_cb) /**< free callback */
void *user_p) /**< user pointer passed to the callback when the string is freed */
{
jerry_assert_api_available ();
ecma_string_t *ecma_str_p = ecma_new_ecma_external_string_from_cesu8 ((lit_utf8_byte_t *) str_p,
(lit_utf8_size_t) str_size,
free_cb);
user_p);
return ecma_make_string_value (ecma_str_p);
} /* jerry_create_external_string_sz */
@@ -3107,6 +3107,16 @@ jerry_substring_to_utf8_char_buffer (const jerry_value_t value, /**< input strin
buffer_size);
} /* jerry_substring_to_utf8_char_buffer */
/**
* Sets the global callback which is called when an external string is freed.
*/
void
jerry_string_set_external_string_free_callback (jerry_external_string_free_callback_t callback_p) /**< free
* callback */
{
JERRY_CONTEXT (external_string_free_callback_p) = callback_p;
} /* jerry_string_set_external_string_free_callback */
/**
* Checks whether the object or it's prototype objects have the given property.
*
+2 -2
View File
@@ -1804,8 +1804,8 @@ typedef struct
*/
typedef struct
{
ecma_long_string_t header;
jerry_value_free_callback_t free_cb; /**< free callback */
ecma_long_string_t header; /**< long string header */
void *user_p; /**< user pointer passed to the callback when the string is freed */
} ecma_external_string_t;
/**
+15 -6
View File
@@ -19,6 +19,7 @@
#include "ecma-gc.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
#include "jcontext.h"
#include "jrt.h"
#include "jrt-libc-includes.h"
#include "lit-char-helpers.h"
@@ -455,7 +456,8 @@ ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string
ecma_string_t *
ecma_new_ecma_external_string_from_cesu8 (const lit_utf8_byte_t *string_p, /**< cesu-8 string */
lit_utf8_size_t string_size, /**< string size */
jerry_value_free_callback_t free_cb) /**< free callback */
void *user_p) /**< user pointer passed to the callback
* when the string is freed */
{
JERRY_ASSERT (string_p != NULL || string_size == 0);
JERRY_ASSERT (lit_is_valid_cesu8_string (string_p, string_size));
@@ -465,9 +467,11 @@ ecma_new_ecma_external_string_from_cesu8 (const lit_utf8_byte_t *string_p, /**<
/* Normal strings are created for short strings. */
ecma_string_t *string_desc_p = ecma_new_ecma_string_from_utf8 (string_p, string_size);
jerry_external_string_free_callback_t free_cb = JERRY_CONTEXT (external_string_free_callback_p);
if (free_cb != NULL)
{
free_cb ((void *) string_p);
free_cb ((lit_utf8_byte_t *) string_p, string_size, user_p);
}
return string_desc_p;
}
@@ -476,9 +480,11 @@ ecma_new_ecma_external_string_from_cesu8 (const lit_utf8_byte_t *string_p, /**<
if (string_desc_p != NULL)
{
jerry_external_string_free_callback_t free_cb = JERRY_CONTEXT (external_string_free_callback_p);
if (free_cb != NULL)
{
free_cb ((void *) string_p);
free_cb ((lit_utf8_byte_t *) string_p, string_size, user_p);
}
return string_desc_p;
}
@@ -491,7 +497,7 @@ ecma_new_ecma_external_string_from_cesu8 (const lit_utf8_byte_t *string_p, /**<
long_string_p->string_p = string_p;
long_string_p->size = string_size;
long_string_p->length = lit_utf8_string_length (string_p, string_size);
external_string_p->free_cb = free_cb;
external_string_p->user_p = user_p;
return (ecma_string_t *) external_string_p;
} /* ecma_new_ecma_external_string_from_cesu8 */
@@ -961,10 +967,13 @@ ecma_destroy_ecma_string (ecma_string_t *string_p) /**< ecma-string */
}
ecma_external_string_t *external_string_p = (ecma_external_string_t *) string_p;
jerry_external_string_free_callback_t free_cb = JERRY_CONTEXT (external_string_free_callback_p);
if (external_string_p->free_cb != NULL)
if (free_cb != NULL)
{
external_string_p->free_cb ((void *) external_string_p->header.string_p);
free_cb ((lit_utf8_byte_t *) external_string_p->header.string_p,
external_string_p->header.size,
external_string_p->user_p);
}
ecma_dealloc_external_string (external_string_p);
+1 -1
View File
@@ -303,7 +303,7 @@ ecma_string_t *ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *string_p,
ecma_string_t *ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string_p,
lit_utf8_size_t string_size);
ecma_string_t *ecma_new_ecma_external_string_from_cesu8 (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size,
jerry_value_free_callback_t free_cb);
void *user_p);
ecma_string_t *ecma_new_ecma_string_from_code_unit (ecma_char_t code_unit);
#if JERRY_ESNEXT
ecma_string_t *ecma_new_ecma_string_from_code_units (ecma_char_t first_code_unit, ecma_char_t second_code_unit);
+3 -4
View File
@@ -135,6 +135,7 @@ jerry_size_t jerry_substring_to_utf8_char_buffer (const jerry_value_t value,
jerry_length_t end_pos,
jerry_char_t *buffer_p,
jerry_size_t buffer_size);
void jerry_string_set_external_string_free_callback (jerry_external_string_free_callback_t callback_p);
/**
* Functions for array object values.
@@ -188,10 +189,8 @@ jerry_value_t jerry_create_string_from_utf8 (const jerry_char_t *str_p);
jerry_value_t jerry_create_string_sz_from_utf8 (const jerry_char_t *str_p, jerry_size_t str_size);
jerry_value_t jerry_create_string (const jerry_char_t *str_p);
jerry_value_t jerry_create_string_sz (const jerry_char_t *str_p, jerry_size_t str_size);
jerry_value_t jerry_create_external_string (const jerry_char_t *str_p,
jerry_value_free_callback_t free_cb);
jerry_value_t jerry_create_external_string_sz (const jerry_char_t *str_p, jerry_size_t str_size,
jerry_value_free_callback_t free_cb);
jerry_value_t jerry_create_external_string (const jerry_char_t *str_p, void *user_p);
jerry_value_t jerry_create_external_string_sz (const jerry_char_t *str_p, jerry_size_t str_size, void *user_p);
jerry_value_t jerry_create_symbol (const jerry_value_t value);
jerry_value_t jerry_create_bigint (const uint64_t *digits_p, uint32_t size, bool sign);
jerry_value_t jerry_create_undefined (void);
+6
View File
@@ -291,6 +291,12 @@ struct jerry_object_native_info_t;
*/
typedef void (*jerry_object_native_free_callback_t) (void *native_p, struct jerry_object_native_info_t *info_p);
/**
* Free callback for external strings.
*/
typedef void (*jerry_external_string_free_callback_t) (jerry_char_t *string_p, jerry_size_t string_size,
void *user_p);
/**
* Decorator callback for Error objects. The decorator can create
* or update any properties of the newly created Error object.
+1
View File
@@ -158,6 +158,7 @@ struct jerry_context_t
vm_frame_ctx_t *vm_top_context_p; /**< top (current) interpreter context */
jerry_context_data_header_t *context_data_p; /**< linked list of user-provided context-specific pointers */
jerry_external_string_free_callback_t external_string_free_callback_p; /**< free callback for external strings */
void *error_object_created_callback_user_p; /**< user pointer for error_object_update_callback_p */
jerry_error_object_created_callback_t error_object_created_callback_p; /**< decorator callback for Error objects */
size_t ecma_gc_objects_number; /**< number of currently allocated objects */
+37 -16
View File
@@ -25,25 +25,37 @@ static const char *external_3 = "x!?:s";
static const char *external_4 = "Object property external string! Object property external string!";
static void
free_external1 (void *ptr)
external_string_free_callback_1 (jerry_char_t *string_p, /**< string pointer */
jerry_size_t string_size, /**< size of the string */
void *user_p) /**< user pointer */
{
TEST_ASSERT (ptr == external_1);
TEST_ASSERT ((const char *) string_p == external_1);
TEST_ASSERT (string_size == strlen (external_1));
TEST_ASSERT (user_p == NULL);
free_count++;
} /* free_external1 */
} /* external_string_free_callback_1 */
static void
free_external2 (void *ptr)
external_string_free_callback_2 (jerry_char_t *string_p, /**< string pointer */
jerry_size_t string_size, /**< size of the string */
void *user_p) /**< user pointer */
{
TEST_ASSERT (ptr == external_2);
TEST_ASSERT ((const char *) string_p == external_2);
TEST_ASSERT (string_size == strlen (external_2));
TEST_ASSERT (user_p == (void *) &free_count);
free_count++;
} /* free_external2 */
} /* external_string_free_callback_2 */
static void
free_external3 (void *ptr)
external_string_free_callback_3 (jerry_char_t *string_p, /**< string pointer */
jerry_size_t string_size, /**< size of the string */
void *user_p) /**< user pointer */
{
TEST_ASSERT (ptr == external_3);
TEST_ASSERT ((const char *) string_p == external_3);
TEST_ASSERT (string_size == strlen (external_3));
TEST_ASSERT (user_p == (void *) string_p);
free_count++;
} /* free_external3 */
} /* external_string_free_callback_3 */
int
main (void)
@@ -53,38 +65,45 @@ main (void)
jerry_init (JERRY_INIT_EMPTY);
/* Test external callback calls. */
jerry_value_t external_string = jerry_create_external_string ((jerry_char_t *) external_1, free_external1);
jerry_string_set_external_string_free_callback (external_string_free_callback_1);
jerry_value_t external_string = jerry_create_external_string ((jerry_char_t *) external_1, NULL);
TEST_ASSERT (free_count == 0);
jerry_release_value (external_string);
TEST_ASSERT (free_count == 1);
jerry_string_set_external_string_free_callback (NULL);
external_string = jerry_create_external_string ((jerry_char_t *) external_1, NULL);
TEST_ASSERT (free_count == 1);
jerry_release_value (external_string);
TEST_ASSERT (free_count == 1);
external_string = jerry_create_external_string ((jerry_char_t *) external_2, free_external2);
jerry_string_set_external_string_free_callback (external_string_free_callback_2);
external_string = jerry_create_external_string ((jerry_char_t *) external_2, (void *) &free_count);
TEST_ASSERT (free_count == 2);
jerry_release_value (external_string);
TEST_ASSERT (free_count == 2);
external_string = jerry_create_external_string ((jerry_char_t *) external_2, NULL);
jerry_string_set_external_string_free_callback (NULL);
external_string = jerry_create_external_string ((jerry_char_t *) external_2, (void *) &free_count);
TEST_ASSERT (free_count == 2);
jerry_release_value (external_string);
TEST_ASSERT (free_count == 2);
external_string = jerry_create_external_string ((jerry_char_t *) external_3, free_external3);
jerry_string_set_external_string_free_callback (external_string_free_callback_3);
external_string = jerry_create_external_string ((jerry_char_t *) external_3, (void *) external_3);
TEST_ASSERT (free_count == 3);
jerry_release_value (external_string);
TEST_ASSERT (free_count == 3);
external_string = jerry_create_external_string ((jerry_char_t *) external_3, NULL);
jerry_string_set_external_string_free_callback (NULL);
external_string = jerry_create_external_string ((jerry_char_t *) external_3, (void *) external_3);
TEST_ASSERT (free_count == 3);
jerry_release_value (external_string);
TEST_ASSERT (free_count == 3);
/* Test string comparison. */
external_string = jerry_create_external_string ((jerry_char_t *) external_1, free_external1);
jerry_string_set_external_string_free_callback (external_string_free_callback_1);
external_string = jerry_create_external_string ((jerry_char_t *) external_1, NULL);
jerry_value_t other_string = jerry_create_string ((jerry_char_t *) external_1);
jerry_value_t result = jerry_binary_operation (JERRY_BIN_OP_STRICT_EQUAL, external_string, other_string);
@@ -103,7 +122,8 @@ main (void)
jerry_release_value (other_string);
/* Test getting string. */
external_string = jerry_create_external_string ((jerry_char_t *) external_1, free_external1);
jerry_string_set_external_string_free_callback (external_string_free_callback_1);
external_string = jerry_create_external_string ((jerry_char_t *) external_1, NULL);
size_t length = strlen (external_1);
TEST_ASSERT (jerry_value_is_string (external_string));
@@ -119,6 +139,7 @@ main (void)
TEST_ASSERT (free_count == 5);
/* Test property access. */
jerry_string_set_external_string_free_callback (NULL);
external_string = jerry_create_external_string ((jerry_char_t *) external_4, NULL);
other_string = jerry_create_string ((jerry_char_t *) external_4);