From 85dd50ce355ed8a46802039694e5996f1f38f43c Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Tue, 30 Mar 2021 12:05:08 +0000 Subject: [PATCH] Add info to external pointer free callback. Furthermore reduce memory consumption when only one external pointer is assigned to an object. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- docs/02.API-REFERENCE.md | 67 ++++++-- jerry-core/api/jerry.c | 14 +- jerry-core/ecma/base/ecma-gc.c | 43 ++++-- jerry-core/ecma/base/ecma-globals.h | 29 ++-- .../base/ecma-helpers-external-pointers.c | 145 ++++++++++++++---- jerry-core/ecma/base/ecma-helpers-string.c | 2 +- jerry-core/ecma/base/ecma-helpers.h | 2 +- .../ecma/operations/ecma-arraybuffer-object.c | 2 +- .../ecma/operations/ecma-arraybuffer-object.h | 2 +- jerry-core/include/jerryscript-core.h | 6 +- jerry-core/include/jerryscript-types.h | 14 +- .../source/AnalogIn-js.cpp | 3 +- .../source/DigitalOut-js.cpp | 3 +- .../source/I2C-js.cpp | 3 +- .../source/InterruptIn-js.cpp | 3 +- .../source/PwmOut-js.cpp | 3 +- tests/unit-core/test-api.c | 8 +- tests/unit-core/test-native-pointer.c | 4 +- tests/unit-core/test-objects-foreach.c | 6 +- tests/unit-core/test-proxy.c | 10 +- tests/unit-ext/test-ext-autorelease.c | 6 +- tests/unit-ext/test-ext-handle-scope-escape.c | 6 +- ...t-ext-handle-scope-handle-prelist-escape.c | 6 +- .../test-ext-handle-scope-handle-prelist.c | 6 +- tests/unit-ext/test-ext-handle-scope-nested.c | 6 +- tests/unit-ext/test-ext-handle-scope-remove.c | 6 +- tests/unit-ext/test-ext-handle-scope-root.c | 6 +- tests/unit-ext/test-ext-handle-scope.c | 6 +- 28 files changed, 299 insertions(+), 118 deletions(-) diff --git a/docs/02.API-REFERENCE.md b/docs/02.API-REFERENCE.md index ad0f9470a1..b567814e74 100644 --- a/docs/02.API-REFERENCE.md +++ b/docs/02.API-REFERENCE.md @@ -696,11 +696,35 @@ typedef jerry_value_t (*jerry_external_handler_t) (const jerry_call_info_t *call - [jerry_create_external_function](#jerry_create_external_function) +## jerry_value_free_callback_t + +**Summary** + +Native free callback of generic value types. + +*Note*: + - Referred values by this method must have at least 1 reference. (Correct API usage satisfies this condition) + +**Prototype** + +```c +typedef void (*jerry_value_free_callback_t) (void *native_p); +``` + +*New in version [[NEXT_RELEASE]]*. + +**See also** + +- [jerry_create_external_string](#jerry_create_external_string) +- [jerry_create_external_string_sz](#jerry_create_external_string_sz) +- [jerry_create_arraybuffer_external](#jerry_create_arraybuffer_external) + ## jerry_object_native_free_callback_t **Summary** -Native free callback of an object. It is used in `jerry_object_native_info_t` and for external Array buffers. +Native free callback of an object. The callback receives both the memory pointer and the type +information passed to [jerry_set_object_native_pointer](#jerry_set_object_native_pointer). *Note*: - Referred values by this method must have at least 1 reference. (Correct API usage satisfies this condition) @@ -708,17 +732,21 @@ Native free callback of an object. It is used in `jerry_object_native_info_t` an **Prototype** ```c -typedef void (*jerry_object_native_free_callback_t) (void *native_p); +typedef void (*jerry_object_native_free_callback_t) (void *native_p, struct jerry_object_native_info_t *info_p); ``` +- `native_p` - native pointer passed to [jerry_set_object_native_pointer](#jerry_set_object_native_pointer). +- `info_p` - native type info passed to [jerry_set_object_native_pointer](#jerry_set_object_native_pointer). + *New in version 2.0*: Renamed from `jerry_object_free_callback_t`. *Changed in version 2.2*: API calls are once again allowed. (See note) +*Changed in version [[NEXT_RELEASE]]*: `info_p` argument is added + **See also** - [jerry_object_native_info_t](#jerry_object_native_info_t) -- [jerry_create_arraybuffer_external](#jerry_create_arraybuffer_external) ## jerry_error_object_created_callback_t @@ -5655,7 +5683,7 @@ so the user can release the buffer which was provided. 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_value_free_callback_t free_cb); ``` - `size` - size of the buffer to use **in bytes** (should not be 0) @@ -5667,6 +5695,8 @@ jerry_create_arraybuffer_external (const jerry_length_t size *New in version 2.0*. +*Changed in version [[NEXT_RELEASE]]*: type of `free_cb` has been changed. + **Example** ```c @@ -6473,7 +6503,7 @@ is no longer needed. ```c jerry_value_t jerry_create_external_string (const jerry_char_t *str_p, - jerry_object_native_free_callback_t free_cb) + jerry_value_free_callback_t free_cb) ``` - `str_p` - non-null pointer to string @@ -6482,6 +6512,8 @@ jerry_create_external_string (const jerry_char_t *str_p, *New in version 2.4*. +*Changed in version [[NEXT_RELEASE]]*: type of `free_cb` has been changed. + **Example** ```c @@ -6519,7 +6551,7 @@ is no longer needed. jerry_value_t jerry_create_external_string_sz (const jerry_char_t *str_p, jerry_size_t str_size, - jerry_object_native_free_callback_t free_cb) + jerry_value_free_callback_t free_cb) ``` - `str_p` - non-null pointer to string @@ -6529,6 +6561,8 @@ jerry_create_external_string_sz (const jerry_char_t *str_p, *New in version 2.4*. +*Changed in version [[NEXT_RELEASE]]*: type of `free_cb` has been changed. + **Example** ```c @@ -8416,8 +8450,11 @@ typedef struct #define SECRET_INFO ((void *) 42) static void -buffer_native_freecb (void *native_p) +buffer_native_freecb (void *native_p, + jerry_object_native_info_t *info_p) { + (void) info_p; + char *data_p = ((buffer_native_object_t*)native_p)->data_p; if (data_p != NULL) @@ -8429,14 +8466,21 @@ buffer_native_freecb (void *native_p) } static void -shape_native_freecb (void *native_p) +shape_native_freecb (void *native_p, + jerry_object_native_info_t *info_p) { + (void) info_p; + free (native_p); } static void -destructor_freecb (void *native_p) +destructor_freecb (void *native_p, + jerry_object_native_info_t *info_p) { + (void) native_p; + (void) info_p; + printf("Note: the object has been freed\n"); } @@ -8988,8 +9032,11 @@ typedef struct int match_foo_value; } find_object_data_t; -static void native_freecb (void *native_p) +static void native_freecb (void *native_p, + jerry_object_native_info_t *info_p) { + (void) info_p; + /* `native_p` was allocated via malloc. */ free (native_p); } /* native_freecb */ diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index f07735d274..717fc1f60e 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -2474,7 +2474,7 @@ 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_object_native_free_callback_t free_cb) /**< free callback */ + jerry_value_free_callback_t free_cb) /**< free callback */ { return jerry_create_external_string_sz (str_p, lit_zt_utf8_string_size ((lit_utf8_byte_t *) str_p), free_cb); } /* jerry_create_external_string */ @@ -2490,7 +2490,7 @@ 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_object_native_free_callback_t free_cb) /**< free callback */ + jerry_value_free_callback_t free_cb) /**< free callback */ { jerry_assert_api_available (); @@ -4022,7 +4022,7 @@ jerry_objects_foreach_by_native_info (const jerry_object_native_info_t *native_i { native_pointer_p = ecma_get_native_pointer_value (iter_p, (void *) native_info_p); if (native_pointer_p - && !foreach_p (ecma_make_object_value (iter_p), native_pointer_p->data_p, user_data_p)) + && !foreach_p (ecma_make_object_value (iter_p), native_pointer_p->native_p, user_data_p)) { return true; } @@ -4066,7 +4066,7 @@ jerry_get_object_native_pointer (const jerry_value_t obj_val, /**< object to get if (out_native_pointer_p != NULL) { - *out_native_pointer_p = native_pointer_p->data_p; + *out_native_pointer_p = native_pointer_p->native_p; } return true; @@ -5209,7 +5209,7 @@ jerry_create_arraybuffer (const jerry_length_t size) /**< size of the ArrayBuffe 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_value_free_callback_t free_cb) /**< buffer free callback */ { jerry_assert_api_available (); @@ -5222,9 +5222,7 @@ jerry_create_arraybuffer_external (const jerry_length_t size, /**< size of the b } else { - arraybuffer = ecma_arraybuffer_new_object_external (size, - buffer_p, - (ecma_object_native_free_callback_t) free_cb); + arraybuffer = ecma_arraybuffer_new_object_external (size, buffer_p, free_cb); } return jerry_return (ecma_make_object_value (arraybuffer)); diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index fb1422e790..93f2333f48 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -1175,37 +1175,54 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ * Free the native handle/pointer by calling its free callback. */ static void -ecma_gc_free_native_pointer (ecma_value_t value) /**< property value */ +ecma_gc_free_native_pointer (ecma_property_t property, /**< property descriptor */ + ecma_value_t value) /**< property value */ { - if (value == JMEM_CP_NULL) + if (JERRY_LIKELY (property & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL)) { + JERRY_ASSERT (value != JMEM_CP_NULL); + + ecma_native_pointer_t *native_pointer_p; + native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value); + + jerry_object_native_free_callback_t free_cb = native_pointer_p->info_p->free_cb; + + if (free_cb != NULL) + { + free_cb (native_pointer_p->native_p, native_pointer_p->info_p); + } + + jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t)); return; } - ecma_native_pointer_t *native_pointer_p; + if (value == JMEM_CP_NULL) + { + return; + } - native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value); - JERRY_ASSERT (native_pointer_p != NULL); + ecma_native_pointer_chain_t *item_p; + item_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_chain_t, value); do { - if (native_pointer_p->info_p != NULL) + if (item_p->data.info_p != NULL) { - ecma_object_native_free_callback_t free_cb = native_pointer_p->info_p->free_cb; + jerry_object_native_free_callback_t free_cb = item_p->data.info_p->free_cb; if (free_cb != NULL) { - free_cb (native_pointer_p->data_p); + free_cb (item_p->data.native_p, item_p->data.info_p); } } - ecma_native_pointer_t *next_p = native_pointer_p->next_p; + ecma_native_pointer_chain_t *next_p = item_p->next_p; - jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t)); + jmem_heap_free_block (item_p, sizeof (ecma_native_pointer_chain_t)); - native_pointer_p = next_p; + item_p = next_p; } - while (native_pointer_p != NULL); + while (item_p != NULL); } /* ecma_gc_free_native_pointer */ /** @@ -1518,7 +1535,7 @@ ecma_gc_free_property (ecma_object_t *object_p, /**< object */ default: { JERRY_ASSERT (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER); - ecma_gc_free_native_pointer (value); + ecma_gc_free_native_pointer (property, value); break; } } diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 72073d3c0a..625a321cd8 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -299,27 +299,22 @@ typedef ecma_value_t (*ecma_native_handler_t) (const struct jerry_call_info_t *c const uint32_t args_count); /** - * Native free callback of an object. - */ -typedef void (*ecma_object_native_free_callback_t) (void *native_p); - -/** - * Type information of a native pointer. + * Representation of native pointer data. */ typedef struct { - ecma_object_native_free_callback_t free_cb; /**< the free callback of the native pointer */ -} ecma_object_native_info_t; + void *native_p; /**< points to the data of the object */ + jerry_object_native_info_t *info_p; /**< native info */ +} ecma_native_pointer_t; /** - * Representation for native pointer data. + * Representation of native pointer data chain. */ -typedef struct ecma_native_pointer_t +typedef struct ecma_native_pointer_chain_t { - void *data_p; /**< points to the data of the object */ - ecma_object_native_info_t *info_p; /**< native info */ - struct ecma_native_pointer_t *next_p; /**< points to the next ecma_native_pointer_t element */ -} ecma_native_pointer_t; + ecma_native_pointer_t data; /**< pointer data */ + struct ecma_native_pointer_chain_t *next_p; /**< next in the list */ +} ecma_native_pointer_chain_t; /** * Option bits for ecma_parse_options_t. @@ -415,7 +410,7 @@ typedef enum ECMA_PROPERTY_FLAG_CONFIGURABLE = (1u << 0), /**< property is configurable */ ECMA_PROPERTY_FLAG_ENUMERABLE = (1u << 1), /**< property is enumerable */ ECMA_PROPERTY_FLAG_WRITABLE = (1u << 2), /**< property is writable */ - + ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL = (1u << 2), /**< only one external pointer is assigned to this object */ ECMA_PROPERTY_FLAG_DELETED = (1u << 3), /**< property is deleted */ ECMA_FAST_ARRAY_FLAG = (1u << 3), /**< array is fast array */ ECMA_PROPERTY_FLAG_LCACHED = (1u << 4), /**< property is lcached */ @@ -1849,7 +1844,7 @@ typedef struct typedef struct { ecma_long_string_t header; - ecma_object_native_free_callback_t free_cb; /**< free callback */ + jerry_value_free_callback_t free_cb; /**< free callback */ } ecma_external_string_t; /** @@ -2101,7 +2096,7 @@ 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 */ + jerry_value_free_callback_t free_cb; /**< the free callback for the above buffer pointer */ } ecma_arraybuffer_external_info; /** diff --git a/jerry-core/ecma/base/ecma-helpers-external-pointers.c b/jerry-core/ecma/base/ecma-helpers-external-pointers.c index f3e8fd8f8d..c105f875fa 100644 --- a/jerry-core/ecma/base/ecma-helpers-external-pointers.c +++ b/jerry-core/ecma/base/ecma-helpers-external-pointers.c @@ -56,8 +56,35 @@ ecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create ecma_property_value_t *value_p; ECMA_CREATE_INTERNAL_PROPERTY (obj_p, name_p, property_p, value_p); - native_pointer_p = jmem_heap_alloc_block (sizeof (ecma_native_pointer_t)); + native_pointer_p = (ecma_native_pointer_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_t)); ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, native_pointer_p); + + *property_p |= ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL; + } + else if (*property_p & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL) + { + ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value_p->value); + + if (native_pointer_p->info_p == info_p) + { + native_pointer_p->native_p = native_p; + return false; + } + + ecma_native_pointer_chain_t *item_p; + item_p = (ecma_native_pointer_chain_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_chain_t)); + item_p->data = *native_pointer_p; + + jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t)); + + item_p->next_p = (ecma_native_pointer_chain_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_chain_t)); + item_p->next_p->next_p = NULL; + + native_pointer_p = &item_p->next_p->data; + *property_p &= (ecma_property_t) ~ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL; + ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, item_p); } else { @@ -65,42 +92,48 @@ ecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create if (value_p->value == JMEM_CP_NULL) { - native_pointer_p = jmem_heap_alloc_block (sizeof (ecma_native_pointer_t)); + native_pointer_p = (ecma_native_pointer_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_t)); ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, native_pointer_p); + + *property_p |= ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL; } else { - ecma_native_pointer_t *iter_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value_p->value); + ecma_native_pointer_chain_t *item_p; + item_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_chain_t, value_p->value); - /* There should be at least 1 native pointer in the chain */ - JERRY_ASSERT (iter_p != NULL); + /* There should be at least 2 native pointers in the chain */ + JERRY_ASSERT (item_p != NULL && item_p->next_p != NULL); while (true) { - if (iter_p->info_p == info_p) + if (item_p->data.info_p == info_p) { /* The native info already exists -> update the corresponding data */ - iter_p->data_p = native_p; + item_p->data.native_p = native_p; return false; } - if (iter_p->next_p == NULL) + if (item_p->next_p == NULL) { /* The native info does not exist -> append a new element to the chain */ break; } - iter_p = iter_p->next_p; + item_p = item_p->next_p; } - native_pointer_p = jmem_heap_alloc_block (sizeof (ecma_native_pointer_t)); - iter_p->next_p = native_pointer_p; + ecma_native_pointer_chain_t *new_item_p; + + new_item_p = (ecma_native_pointer_chain_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_chain_t)); + item_p->next_p = new_item_p; + + native_pointer_p = &new_item_p->data; } } - native_pointer_p->data_p = native_p; + native_pointer_p->native_p = native_p; native_pointer_p->info_p = info_p; - native_pointer_p->next_p = NULL; return is_new; } /* ecma_create_native_pointer_property */ @@ -135,25 +168,40 @@ ecma_get_native_pointer_value (ecma_object_t *obj_p, /**< object to get property ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + if (JERRY_LIKELY (*property_p & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL)) + { + ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, + value_p->value); + + if (native_pointer_p->info_p == info_p) + { + return native_pointer_p; + } + + return NULL; + } + if (value_p->value == JMEM_CP_NULL) { return NULL; } - ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, - value_p->value); - JERRY_ASSERT (native_pointer_p != NULL); + ecma_native_pointer_chain_t *item_p; + item_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_chain_t, value_p->value); + + /* There should be at least 2 native pointers in the chain */ + JERRY_ASSERT (item_p != NULL && item_p->next_p != NULL); do { - if (native_pointer_p->info_p == info_p) + if (item_p->data.info_p == info_p) { - return native_pointer_p; + return &item_p->data; } - native_pointer_p = native_pointer_p->next_p; + item_p = item_p->next_p; } - while (native_pointer_p != NULL); + while (item_p != NULL); return NULL; } /* ecma_get_native_pointer_value */ @@ -188,40 +236,75 @@ ecma_delete_native_pointer_property (ecma_object_t *obj_p, /**< object to delete ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + if (JERRY_LIKELY (*property_p & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL)) + { + ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, + value_p->value); + + if (native_pointer_p->info_p != info_p) + { + return false; + } + + value_p->value = JMEM_CP_NULL; + *property_p &= (ecma_property_t) ~ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL; + jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t)); + return true; + } + if (value_p->value == JMEM_CP_NULL) { return false; } - ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, - value_p->value); - JERRY_ASSERT (native_pointer_p != NULL); + ecma_native_pointer_chain_t *first_p; + first_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_chain_t, value_p->value); + + /* There should be at least 2 native pointers in the chain */ + JERRY_ASSERT (first_p != NULL && first_p->next_p != NULL); - ecma_native_pointer_t *prev_p = NULL; + ecma_native_pointer_chain_t *item_p = first_p; + ecma_native_pointer_chain_t *prev_p = NULL; do { - if (native_pointer_p->info_p == info_p) + if (item_p->data.info_p == info_p) { if (prev_p == NULL) { /* The first element is deleted from the chain: change the property value. */ - ECMA_SET_INTERNAL_VALUE_ANY_POINTER (value_p->value, native_pointer_p->next_p); + first_p = item_p->next_p; + ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, first_p); } else { /* A non-first element is deleted from the chain: update the previous pointer. */ - prev_p->next_p = native_pointer_p->next_p; + prev_p->next_p = item_p->next_p; } - jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t)); + jmem_heap_free_block (item_p, sizeof (ecma_native_pointer_chain_t)); + + if (first_p->next_p != NULL) + { + return true; + } + + /* Only one item remained. */ + ecma_native_pointer_t *native_pointer_p; + native_pointer_p = (ecma_native_pointer_t *) jmem_heap_alloc_block (sizeof (ecma_native_pointer_t)); + *native_pointer_p = first_p->data; + + jmem_heap_free_block (first_p, sizeof (ecma_native_pointer_chain_t)); + + ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, native_pointer_p); + *property_p |= ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL; return true; } - prev_p = native_pointer_p; - native_pointer_p = native_pointer_p->next_p; + prev_p = item_p; + item_p = item_p->next_p; } - while (native_pointer_p != NULL); + while (item_p != NULL); return false; } /* ecma_delete_native_pointer_property */ diff --git a/jerry-core/ecma/base/ecma-helpers-string.c b/jerry-core/ecma/base/ecma-helpers-string.c index 0e3a35a4a4..94cada2942 100644 --- a/jerry-core/ecma/base/ecma-helpers-string.c +++ b/jerry-core/ecma/base/ecma-helpers-string.c @@ -455,7 +455,7 @@ 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 */ - ecma_object_native_free_callback_t free_cb) /**< free callback */ + jerry_value_free_callback_t free_cb) /**< free callback */ { JERRY_ASSERT (string_p != NULL || string_size == 0); JERRY_ASSERT (lit_is_valid_cesu8_string (string_p, string_size)); diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 211ca1d214..9a02a3a100 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -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, - ecma_object_native_free_callback_t free_cb); + jerry_value_free_callback_t free_cb); 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); diff --git a/jerry-core/ecma/operations/ecma-arraybuffer-object.c b/jerry-core/ecma/operations/ecma-arraybuffer-object.c index 0815a01f59..c846963456 100644 --- a/jerry-core/ecma/operations/ecma-arraybuffer-object.c +++ b/jerry-core/ecma/operations/ecma-arraybuffer-object.c @@ -76,7 +76,7 @@ ecma_arraybuffer_new_object (uint32_t length) /**< length of the arraybuffer */ ecma_object_t * ecma_arraybuffer_new_object_external (uint32_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 */ + jerry_value_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, diff --git a/jerry-core/ecma/operations/ecma-arraybuffer-object.h b/jerry-core/ecma/operations/ecma-arraybuffer-object.h index ada0cfc3a7..ca7e8cd63f 100644 --- a/jerry-core/ecma/operations/ecma-arraybuffer-object.h +++ b/jerry-core/ecma/operations/ecma-arraybuffer-object.h @@ -38,7 +38,7 @@ ecma_arraybuffer_new_object (uint32_t lengh); ecma_object_t * ecma_arraybuffer_new_object_external (uint32_t length, void *buffer_p, - ecma_object_native_free_callback_t free_cb); + jerry_value_free_callback_t free_cb); lit_utf8_byte_t * JERRY_ATTR_PURE ecma_arraybuffer_get_buffer (ecma_object_t *obj_p); uint32_t JERRY_ATTR_PURE diff --git a/jerry-core/include/jerryscript-core.h b/jerry-core/include/jerryscript-core.h index 494e0c2126..e70f12084e 100644 --- a/jerry-core/include/jerryscript-core.h +++ b/jerry-core/include/jerryscript-core.h @@ -190,9 +190,9 @@ jerry_value_t jerry_create_string_sz_from_utf8 (const jerry_char_t *str_p, jerry 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_object_native_free_callback_t free_cb); + 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_object_native_free_callback_t free_cb); + jerry_value_free_callback_t free_cb); 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); @@ -351,7 +351,7 @@ 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_value_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, diff --git a/jerry-core/include/jerryscript-types.h b/jerry-core/include/jerryscript-types.h index 2fbb4e1b8a..4a12ec3ef2 100644 --- a/jerry-core/include/jerryscript-types.h +++ b/jerry-core/include/jerryscript-types.h @@ -277,10 +277,20 @@ typedef jerry_value_t (*jerry_external_handler_t) (const jerry_call_info_t *call const jerry_value_t args_p[], const jerry_length_t args_count); +/** + * Native free callback of generic value types. + */ +typedef void (*jerry_value_free_callback_t) (void *native_p); + +/** + * Forward definition of jerry_object_native_info_t. + */ +struct jerry_object_native_info_t; + /** * Native free callback of an object. */ -typedef void (*jerry_object_native_free_callback_t) (void *native_p); +typedef void (*jerry_object_native_free_callback_t) (void *native_p, struct jerry_object_native_info_t *info_p); /** * Decorator callback for Error objects. The decorator can create @@ -374,7 +384,7 @@ typedef void *(*jerry_context_alloc_t) (size_t size, void *cb_data_p); /** * Type information of a native pointer. */ -typedef struct +typedef struct jerry_object_native_info_t { jerry_object_native_free_callback_t free_cb; /**< the free callback of the native pointer */ } jerry_object_native_info_t; diff --git a/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/AnalogIn-js.cpp b/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/AnalogIn-js.cpp index 82f97a8c74..d05c19ce05 100644 --- a/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/AnalogIn-js.cpp +++ b/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/AnalogIn-js.cpp @@ -22,7 +22,8 @@ * * Called if/when the AnalogIn is GC'ed. */ -void NAME_FOR_CLASS_NATIVE_DESTRUCTOR(AnalogIn)(void* void_ptr) { +void NAME_FOR_CLASS_NATIVE_DESTRUCTOR(AnalogIn)(void* void_ptr, jerry_object_native_info_t *info_p) { + (void) info_p; delete static_cast(void_ptr); } diff --git a/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/DigitalOut-js.cpp b/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/DigitalOut-js.cpp index ce6c2a061d..a521f00e6d 100644 --- a/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/DigitalOut-js.cpp +++ b/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/DigitalOut-js.cpp @@ -22,7 +22,8 @@ * * Called if/when the DigitalOut is GC'ed. */ -void NAME_FOR_CLASS_NATIVE_DESTRUCTOR(DigitalOut)(void* void_ptr) { +void NAME_FOR_CLASS_NATIVE_DESTRUCTOR(DigitalOut)(void* void_ptr, jerry_object_native_info_t *info_p) { + (void) info_p; delete static_cast(void_ptr); } diff --git a/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/I2C-js.cpp b/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/I2C-js.cpp index 078fc98fbc..98172de434 100644 --- a/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/I2C-js.cpp +++ b/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/I2C-js.cpp @@ -23,7 +23,8 @@ * * Called if/when the I2C object is GC'ed. */ -void NAME_FOR_CLASS_NATIVE_DESTRUCTOR(I2C) (void *void_ptr) { +void NAME_FOR_CLASS_NATIVE_DESTRUCTOR(I2C) (void *void_ptr, jerry_object_native_info_t *info_p) { + (void) info_p; delete static_cast(void_ptr); } diff --git a/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/InterruptIn-js.cpp b/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/InterruptIn-js.cpp index c86701fcb4..a1961dfed4 100644 --- a/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/InterruptIn-js.cpp +++ b/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/InterruptIn-js.cpp @@ -23,7 +23,8 @@ * * Called if/when the InterruptIn object is GC'ed. */ -void NAME_FOR_CLASS_NATIVE_DESTRUCTOR(InterruptIn) (void *void_ptr) { +void NAME_FOR_CLASS_NATIVE_DESTRUCTOR(InterruptIn) (void *void_ptr, jerry_object_native_info_t *info_p) { + (void) info_p; InterruptIn *native_ptr = static_cast(void_ptr); native_ptr->rise(0); diff --git a/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/PwmOut-js.cpp b/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/PwmOut-js.cpp index e3d43cae14..fab24157f5 100644 --- a/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/PwmOut-js.cpp +++ b/targets/mbedos5/jerryscript-mbed/jerryscript-mbed-drivers/source/PwmOut-js.cpp @@ -22,7 +22,8 @@ * * Called if/when the PwmOut is GC'ed. */ -void NAME_FOR_CLASS_NATIVE_DESTRUCTOR(PwmOut)(void* void_ptr) { +void NAME_FOR_CLASS_NATIVE_DESTRUCTOR(PwmOut)(void* void_ptr, jerry_object_native_info_t *info_p) { + (void) info_p; delete static_cast(void_ptr); } diff --git a/tests/unit-core/test-api.c b/tests/unit-core/test-api.c index 948c0cd0c2..ca4df1fb2e 100644 --- a/tests/unit-core/test-api.c +++ b/tests/unit-core/test-api.c @@ -106,18 +106,22 @@ handler_throw_test (const jerry_call_info_t *call_info_p, /**< call information } /* handler_throw_test */ static void -handler_construct_1_freecb (void *native_p) +handler_construct_1_freecb (void *native_p, /**< native pointer */ + jerry_object_native_info_t *info_p) /**< native info */ { TEST_ASSERT ((uintptr_t) native_p == (uintptr_t) 0x0000000000000000ull); + TEST_ASSERT (info_p->free_cb == handler_construct_1_freecb); printf ("ok object free callback\n"); test_api_is_free_callback_was_called = true; } /* handler_construct_1_freecb */ static void -handler_construct_2_freecb (void *native_p) +handler_construct_2_freecb (void *native_p, /**< native pointer */ + jerry_object_native_info_t *info_p) /**< native info */ { TEST_ASSERT ((uintptr_t) native_p == (uintptr_t) 0x0012345678abcdefull); + TEST_ASSERT (info_p->free_cb == handler_construct_2_freecb); printf ("ok object free callback\n"); test_api_is_free_callback_was_called = true; diff --git a/tests/unit-core/test-native-pointer.c b/tests/unit-core/test-native-pointer.c index 3a341712e0..54e3899e73 100644 --- a/tests/unit-core/test-native-pointer.c +++ b/tests/unit-core/test-native-pointer.c @@ -22,9 +22,11 @@ static void *global_p = (void *) &global_int; static int global_counter = 0; static void -native_free_callback (void *native_p) /**< native pointer */ +native_free_callback (void *native_p, /**< native pointer */ + jerry_object_native_info_t *info_p) /**< native info */ { (void) native_p; + TEST_ASSERT (info_p->free_cb == native_free_callback); global_counter++; } /* native_free_callback */ diff --git a/tests/unit-core/test-objects-foreach.c b/tests/unit-core/test-objects-foreach.c index edbeab6869..2fb9433302 100644 --- a/tests/unit-core/test-objects-foreach.c +++ b/tests/unit-core/test-objects-foreach.c @@ -132,9 +132,11 @@ test_internal_prop (void) static int test_data = 1; -static void free_test_data (void *data_p) +static void free_test_data (void *native_p, /**< native pointer */ + jerry_object_native_info_t *info_p) /**< native info */ { - TEST_ASSERT ((int *) data_p == &test_data); + TEST_ASSERT ((int *) native_p == &test_data); + TEST_ASSERT (info_p->free_cb == free_test_data); } /* free_test_data */ static const jerry_object_native_info_t test_info = diff --git a/tests/unit-core/test-proxy.c b/tests/unit-core/test-proxy.c index e3d95c0b07..491aa317f5 100644 --- a/tests/unit-core/test-proxy.c +++ b/tests/unit-core/test-proxy.c @@ -150,11 +150,13 @@ struct test_data }; static void -proxy_native_freecb (void *user_p) +proxy_native_freecb (void *native_p, /**< native pointer */ + jerry_object_native_info_t *info_p) /**< native info */ { - TEST_ASSERT (user_p != NULL); - struct test_data *native_p = (struct test_data *) user_p; - native_p->value = -1; + TEST_ASSERT (native_p != NULL); + TEST_ASSERT (info_p->free_cb == proxy_native_freecb); + struct test_data *data_p = (struct test_data *) native_p; + data_p->value = -1; } /* proxy_native_freecb */ static const jerry_object_native_info_t proxy_native_info = diff --git a/tests/unit-ext/test-ext-autorelease.c b/tests/unit-ext/test-ext-autorelease.c index 36df3db255..8734ea59b7 100644 --- a/tests/unit-ext/test-ext-autorelease.c +++ b/tests/unit-ext/test-ext-autorelease.c @@ -24,10 +24,12 @@ static int native_free_cb_call_count; static void -native_free_cb (void *native_p) +native_free_cb (void *native_p, /**< native pointer */ + jerry_object_native_info_t *info_p) /**< native info */ { - ++native_free_cb_call_count; (void) native_p; + (void) info_p; + ++native_free_cb_call_count; } /* native_free_cb */ static const jerry_object_native_info_t native_info = diff --git a/tests/unit-ext/test-ext-handle-scope-escape.c b/tests/unit-ext/test-ext-handle-scope-escape.c index 24c93c670a..c78b6980bc 100644 --- a/tests/unit-ext/test-ext-handle-scope-escape.c +++ b/tests/unit-ext/test-ext-handle-scope-escape.c @@ -24,10 +24,12 @@ static int native_free_cb_call_count; static void -native_free_cb (void *native_p) +native_free_cb (void *native_p, /**< native pointer */ + jerry_object_native_info_t *info_p) /**< native info */ { - ++native_free_cb_call_count; (void) native_p; + (void) info_p; + ++native_free_cb_call_count; } /* native_free_cb */ static const jerry_object_native_info_t native_info = diff --git a/tests/unit-ext/test-ext-handle-scope-handle-prelist-escape.c b/tests/unit-ext/test-ext-handle-scope-handle-prelist-escape.c index 4eec761baf..36cb75b59e 100644 --- a/tests/unit-ext/test-ext-handle-scope-handle-prelist-escape.c +++ b/tests/unit-ext/test-ext-handle-scope-handle-prelist-escape.c @@ -27,10 +27,12 @@ static size_t native_free_cb_call_count; static const size_t handle_count = JERRYX_HANDLE_PRELIST_SIZE + 1; static void -native_free_cb (void *native_p) +native_free_cb (void *native_p, /**< native pointer */ + jerry_object_native_info_t *info_p) /**< native info */ { - ++native_free_cb_call_count; (void) native_p; + (void) info_p; + ++native_free_cb_call_count; } /* native_free_cb */ static const jerry_object_native_info_t native_info = diff --git a/tests/unit-ext/test-ext-handle-scope-handle-prelist.c b/tests/unit-ext/test-ext-handle-scope-handle-prelist.c index d8b6707ccf..4ef011aa18 100644 --- a/tests/unit-ext/test-ext-handle-scope-handle-prelist.c +++ b/tests/unit-ext/test-ext-handle-scope-handle-prelist.c @@ -27,10 +27,12 @@ static size_t native_free_cb_call_count; static const size_t handle_count = JERRYX_HANDLE_PRELIST_SIZE * 2; static void -native_free_cb (void *native_p) +native_free_cb (void *native_p, /**< native pointer */ + jerry_object_native_info_t *info_p) /**< native info */ { - ++native_free_cb_call_count; (void) native_p; + (void) info_p; + ++native_free_cb_call_count; } /* native_free_cb */ static const jerry_object_native_info_t native_info = diff --git a/tests/unit-ext/test-ext-handle-scope-nested.c b/tests/unit-ext/test-ext-handle-scope-nested.c index c5a0520b12..ce8e3c0a76 100644 --- a/tests/unit-ext/test-ext-handle-scope-nested.c +++ b/tests/unit-ext/test-ext-handle-scope-nested.c @@ -27,10 +27,12 @@ static int native_free_cb_call_count; static void -native_free_cb (void *native_p) +native_free_cb (void *native_p, /**< native pointer */ + jerry_object_native_info_t *info_p) /**< native info */ { - ++native_free_cb_call_count; (void) native_p; + (void) info_p; + ++native_free_cb_call_count; } /* native_free_cb */ static const jerry_object_native_info_t native_info = diff --git a/tests/unit-ext/test-ext-handle-scope-remove.c b/tests/unit-ext/test-ext-handle-scope-remove.c index 7f8d592b75..90ef47cdc2 100644 --- a/tests/unit-ext/test-ext-handle-scope-remove.c +++ b/tests/unit-ext/test-ext-handle-scope-remove.c @@ -24,10 +24,12 @@ static int native_free_cb_call_count; static void -native_free_cb (void *native_p) +native_free_cb (void *native_p, /**< native pointer */ + jerry_object_native_info_t *info_p) /**< native info */ { - ++native_free_cb_call_count; (void) native_p; + (void) info_p; + ++native_free_cb_call_count; } /* native_free_cb */ static const jerry_object_native_info_t native_info = diff --git a/tests/unit-ext/test-ext-handle-scope-root.c b/tests/unit-ext/test-ext-handle-scope-root.c index a3c2a3da5f..b018f726cd 100644 --- a/tests/unit-ext/test-ext-handle-scope-root.c +++ b/tests/unit-ext/test-ext-handle-scope-root.c @@ -25,10 +25,12 @@ static int native_free_cb_call_count; static int reusing_times = 10; static void -native_free_cb (void *native_p) +native_free_cb (void *native_p, /**< native pointer */ + jerry_object_native_info_t *info_p) /**< native info */ { - ++native_free_cb_call_count; (void) native_p; + (void) info_p; + ++native_free_cb_call_count; } /* native_free_cb */ static const jerry_object_native_info_t native_info = diff --git a/tests/unit-ext/test-ext-handle-scope.c b/tests/unit-ext/test-ext-handle-scope.c index 9ed96842cf..5cfe92112c 100644 --- a/tests/unit-ext/test-ext-handle-scope.c +++ b/tests/unit-ext/test-ext-handle-scope.c @@ -24,10 +24,12 @@ static int native_free_cb_call_count; static void -native_free_cb (void *native_p) +native_free_cb (void *native_p, /**< native pointer */ + jerry_object_native_info_t *info_p) /**< native info */ { - ++native_free_cb_call_count; (void) native_p; + (void) info_p; + ++native_free_cb_call_count; } /* native_free_cb */ static const jerry_object_native_info_t native_info =