Add info to external pointer free callback. (#4642)

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
This commit is contained in:
Zoltan Herczeg
2021-04-13 09:51:39 +02:00
committed by GitHub
parent b3ec217b50
commit 053389de80
28 changed files with 304 additions and 123 deletions
+58 -11
View File
@@ -696,11 +696,11 @@ typedef jerry_value_t (*jerry_external_handler_t) (const jerry_call_info_t *call
- [jerry_create_external_function](#jerry_create_external_function) - [jerry_create_external_function](#jerry_create_external_function)
## jerry_object_native_free_callback_t ## jerry_value_free_callback_t
**Summary** **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 generic value types.
*Note*: *Note*:
- Referred values by this method must have at least 1 reference. (Correct API usage satisfies this condition) - Referred values by this method must have at least 1 reference. (Correct API usage satisfies this condition)
@@ -708,17 +708,45 @@ Native free callback of an object. It is used in `jerry_object_native_info_t` an
**Prototype** **Prototype**
```c ```c
typedef void (*jerry_object_native_free_callback_t) (void *native_p); 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. 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)
**Prototype**
```c
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`. *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 2.2*: API calls are once again allowed. (See note)
*Changed in version [[NEXT_RELEASE]]*: `info_p` argument is added
**See also** **See also**
- [jerry_object_native_info_t](#jerry_object_native_info_t) - [jerry_object_native_info_t](#jerry_object_native_info_t)
- [jerry_create_arraybuffer_external](#jerry_create_arraybuffer_external)
## jerry_error_object_created_callback_t ## jerry_error_object_created_callback_t
@@ -5655,7 +5683,7 @@ so the user can release the buffer which was provided.
jerry_value_t jerry_value_t
jerry_create_arraybuffer_external (const jerry_length_t size jerry_create_arraybuffer_external (const jerry_length_t size
uint8_t *buffer_p, 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) - `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*. *New in version 2.0*.
*Changed in version [[NEXT_RELEASE]]*: type of `free_cb` has been changed.
**Example** **Example**
```c ```c
@@ -6473,7 +6503,7 @@ is no longer needed.
```c ```c
jerry_value_t jerry_value_t
jerry_create_external_string (const jerry_char_t *str_p, 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 - `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*. *New in version 2.4*.
*Changed in version [[NEXT_RELEASE]]*: type of `free_cb` has been changed.
**Example** **Example**
```c ```c
@@ -6519,7 +6551,7 @@ is no longer needed.
jerry_value_t jerry_value_t
jerry_create_external_string_sz (const jerry_char_t *str_p, jerry_create_external_string_sz (const jerry_char_t *str_p,
jerry_size_t str_size, 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 - `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*. *New in version 2.4*.
*Changed in version [[NEXT_RELEASE]]*: type of `free_cb` has been changed.
**Example** **Example**
```c ```c
@@ -8416,8 +8450,11 @@ typedef struct
#define SECRET_INFO ((void *) 42) #define SECRET_INFO ((void *) 42)
static void 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; char *data_p = ((buffer_native_object_t*)native_p)->data_p;
if (data_p != NULL) if (data_p != NULL)
@@ -8429,14 +8466,21 @@ buffer_native_freecb (void *native_p)
} }
static void 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); free (native_p);
} }
static void 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"); printf("Note: the object has been freed\n");
} }
@@ -8988,8 +9032,11 @@ typedef struct
int match_foo_value; int match_foo_value;
} find_object_data_t; } 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. */ /* `native_p` was allocated via malloc. */
free (native_p); free (native_p);
} /* native_freecb */ } /* native_freecb */
+6 -8
View File
@@ -2474,7 +2474,7 @@ jerry_create_string_sz (const jerry_char_t *str_p, /**< pointer to string */
*/ */
jerry_value_t jerry_value_t
jerry_create_external_string (const jerry_char_t *str_p, /**< pointer to string */ 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); 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 */ } /* 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_value_t
jerry_create_external_string_sz (const jerry_char_t *str_p, /**< pointer to string */ jerry_create_external_string_sz (const jerry_char_t *str_p, /**< pointer to string */
jerry_size_t str_size, /**< string size */ 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 (); 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); native_pointer_p = ecma_get_native_pointer_value (iter_p, (void *) native_info_p);
if (native_pointer_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; 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) 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; return true;
@@ -5209,7 +5209,7 @@ jerry_create_arraybuffer (const jerry_length_t size) /**< size of the ArrayBuffe
jerry_value_t jerry_value_t
jerry_create_arraybuffer_external (const jerry_length_t size, /**< size of the buffer to used */ 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 */ 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 (); jerry_assert_api_available ();
@@ -5222,9 +5222,7 @@ jerry_create_arraybuffer_external (const jerry_length_t size, /**< size of the b
} }
else else
{ {
arraybuffer = ecma_arraybuffer_new_object_external (size, arraybuffer = ecma_arraybuffer_new_object_external (size, buffer_p, free_cb);
buffer_p,
(ecma_object_native_free_callback_t) free_cb);
} }
return jerry_return (ecma_make_object_value (arraybuffer)); return jerry_return (ecma_make_object_value (arraybuffer));
+30 -13
View File
@@ -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. * Free the native handle/pointer by calling its free callback.
*/ */
static void 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 (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;
}
if (value == JMEM_CP_NULL) if (value == JMEM_CP_NULL)
{ {
return; return;
} }
ecma_native_pointer_t *native_pointer_p; ecma_native_pointer_chain_t *item_p;
item_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_chain_t, value);
native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value);
JERRY_ASSERT (native_pointer_p != NULL);
do 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) 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 */ } /* ecma_gc_free_native_pointer */
/** /**
@@ -1518,7 +1535,7 @@ ecma_gc_free_property (ecma_object_t *object_p, /**< object */
default: default:
{ {
JERRY_ASSERT (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER); JERRY_ASSERT (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
ecma_gc_free_native_pointer (value); ecma_gc_free_native_pointer (property, value);
break; break;
} }
} }
+12 -17
View File
@@ -299,27 +299,22 @@ typedef ecma_value_t (*ecma_native_handler_t) (const struct jerry_call_info_t *c
const uint32_t args_count); const uint32_t args_count);
/** /**
* Native free callback of an object. * Representation of native pointer data.
*/
typedef void (*ecma_object_native_free_callback_t) (void *native_p);
/**
* Type information of a native pointer.
*/ */
typedef struct typedef struct
{ {
ecma_object_native_free_callback_t free_cb; /**< the free callback of the native pointer */ void *native_p; /**< points to the data of the object */
} ecma_object_native_info_t; 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_native_pointer_t data; /**< pointer data */
ecma_object_native_info_t *info_p; /**< native info */ struct ecma_native_pointer_chain_t *next_p; /**< next in the list */
struct ecma_native_pointer_t *next_p; /**< points to the next ecma_native_pointer_t element */ } ecma_native_pointer_chain_t;
} ecma_native_pointer_t;
/** /**
* Option bits for ecma_parse_options_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_CONFIGURABLE = (1u << 0), /**< property is configurable */
ECMA_PROPERTY_FLAG_ENUMERABLE = (1u << 1), /**< property is enumerable */ ECMA_PROPERTY_FLAG_ENUMERABLE = (1u << 1), /**< property is enumerable */
ECMA_PROPERTY_FLAG_WRITABLE = (1u << 2), /**< property is writable */ 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_PROPERTY_FLAG_DELETED = (1u << 3), /**< property is deleted */
ECMA_FAST_ARRAY_FLAG = (1u << 3), /**< array is fast array */ ECMA_FAST_ARRAY_FLAG = (1u << 3), /**< array is fast array */
ECMA_PROPERTY_FLAG_LCACHED = (1u << 4), /**< property is lcached */ ECMA_PROPERTY_FLAG_LCACHED = (1u << 4), /**< property is lcached */
@@ -1849,7 +1844,7 @@ typedef struct
typedef struct typedef struct
{ {
ecma_long_string_t header; 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; } ecma_external_string_t;
/** /**
@@ -2101,7 +2096,7 @@ typedef struct
{ {
ecma_extended_object_t extended_object; /**< extended object part */ ecma_extended_object_t extended_object; /**< extended object part */
void *buffer_p; /**< external buffer pointer */ 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; } ecma_arraybuffer_external_info;
/** /**
@@ -56,8 +56,35 @@ ecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create
ecma_property_value_t *value_p; ecma_property_value_t *value_p;
ECMA_CREATE_INTERNAL_PROPERTY (obj_p, name_p, property_p, 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); 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 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) 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); ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, native_pointer_p);
*property_p |= ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL;
} }
else 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 */ /* There should be at least 2 native pointers in the chain */
JERRY_ASSERT (iter_p != NULL); JERRY_ASSERT (item_p != NULL && item_p->next_p != NULL);
while (true) 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 */ /* The native info already exists -> update the corresponding data */
iter_p->data_p = native_p; item_p->data.native_p = native_p;
return false; 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 */ /* The native info does not exist -> append a new element to the chain */
break; 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)); ecma_native_pointer_chain_t *new_item_p;
iter_p->next_p = native_pointer_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->info_p = info_p;
native_pointer_p->next_p = NULL;
return is_new; return is_new;
} /* ecma_create_native_pointer_property */ } /* 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); ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
if (value_p->value == JMEM_CP_NULL) if (JERRY_LIKELY (*property_p & ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL))
{ {
return NULL; ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t,
} value_p->value);
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);
do
{
if (native_pointer_p->info_p == info_p) if (native_pointer_p->info_p == info_p)
{ {
return native_pointer_p; return native_pointer_p;
} }
native_pointer_p = native_pointer_p->next_p; return NULL;
} }
while (native_pointer_p != NULL);
if (value_p->value == JMEM_CP_NULL)
{
return 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 (item_p->data.info_p == info_p)
{
return &item_p->data;
}
item_p = item_p->next_p;
}
while (item_p != NULL);
return NULL; return NULL;
} /* ecma_get_native_pointer_value */ } /* 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); 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) if (value_p->value == JMEM_CP_NULL)
{ {
return false; return false;
} }
ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, ecma_native_pointer_chain_t *first_p;
value_p->value); first_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_chain_t, value_p->value);
JERRY_ASSERT (native_pointer_p != NULL);
ecma_native_pointer_t *prev_p = NULL; /* There should be at least 2 native pointers in the chain */
JERRY_ASSERT (first_p != NULL && first_p->next_p != NULL);
ecma_native_pointer_chain_t *item_p = first_p;
ecma_native_pointer_chain_t *prev_p = NULL;
do do
{ {
if (native_pointer_p->info_p == info_p) if (item_p->data.info_p == info_p)
{ {
if (prev_p == NULL) if (prev_p == NULL)
{ {
/* The first element is deleted from the chain: change the property value. */ /* 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 else
{ {
/* A non-first element is deleted from the chain: update the previous pointer. */ /* 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; return true;
} }
prev_p = native_pointer_p; prev_p = item_p;
native_pointer_p = native_pointer_p->next_p; item_p = item_p->next_p;
} }
while (native_pointer_p != NULL); while (item_p != NULL);
return false; return false;
} /* ecma_delete_native_pointer_property */ } /* ecma_delete_native_pointer_property */
+1 -1
View File
@@ -455,7 +455,7 @@ ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string
ecma_string_t * ecma_string_t *
ecma_new_ecma_external_string_from_cesu8 (const lit_utf8_byte_t *string_p, /**< cesu-8 string */ 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 */ 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 (string_p != NULL || string_size == 0);
JERRY_ASSERT (lit_is_valid_cesu8_string (string_p, string_size)); JERRY_ASSERT (lit_is_valid_cesu8_string (string_p, string_size));
+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, 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); 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_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); ecma_string_t *ecma_new_ecma_string_from_code_unit (ecma_char_t code_unit);
#if JERRY_ESNEXT #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); ecma_string_t *ecma_new_ecma_string_from_code_units (ecma_char_t first_code_unit, ecma_char_t second_code_unit);
@@ -76,7 +76,7 @@ ecma_arraybuffer_new_object (uint32_t length) /**< length of the arraybuffer */
ecma_object_t * ecma_object_t *
ecma_arraybuffer_new_object_external (uint32_t length, /**< length of the buffer_p to use */ ecma_arraybuffer_new_object_external (uint32_t length, /**< length of the buffer_p to use */
void *buffer_p, /**< pointer for ArrayBuffer's buffer backing */ 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 *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE);
ecma_object_t *object_p = ecma_create_object (prototype_obj_p, ecma_object_t *object_p = ecma_create_object (prototype_obj_p,
@@ -38,7 +38,7 @@ ecma_arraybuffer_new_object (uint32_t lengh);
ecma_object_t * ecma_object_t *
ecma_arraybuffer_new_object_external (uint32_t length, ecma_arraybuffer_new_object_external (uint32_t length,
void *buffer_p, 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 lit_utf8_byte_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
+3 -3
View File
@@ -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 (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_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_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_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_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_bigint (const uint64_t *digits_p, uint32_t size, bool sign);
jerry_value_t jerry_create_undefined (void); 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 (const jerry_length_t size);
jerry_value_t jerry_create_arraybuffer_external (const jerry_length_t size, jerry_value_t jerry_create_arraybuffer_external (const jerry_length_t size,
uint8_t *buffer_p, 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 jerry_arraybuffer_write (const jerry_value_t value,
jerry_length_t offset, jerry_length_t offset,
const uint8_t *buf_p, const uint8_t *buf_p,
+12 -2
View File
@@ -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_value_t args_p[],
const jerry_length_t args_count); 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. * 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 * 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. * 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_free_callback_t free_cb; /**< the free callback of the native pointer */
} jerry_object_native_info_t; } jerry_object_native_info_t;
@@ -22,7 +22,8 @@
* *
* Called if/when the AnalogIn is GC'ed. * 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<AnalogIn*>(void_ptr); delete static_cast<AnalogIn*>(void_ptr);
} }
@@ -22,7 +22,8 @@
* *
* Called if/when the DigitalOut is GC'ed. * 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<DigitalOut*>(void_ptr); delete static_cast<DigitalOut*>(void_ptr);
} }
@@ -23,7 +23,8 @@
* *
* Called if/when the I2C object is GC'ed. * 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<I2C*>(void_ptr); delete static_cast<I2C*>(void_ptr);
} }
@@ -23,7 +23,8 @@
* *
* Called if/when the InterruptIn object is GC'ed. * 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<InterruptIn*>(void_ptr); InterruptIn *native_ptr = static_cast<InterruptIn*>(void_ptr);
native_ptr->rise(0); native_ptr->rise(0);
@@ -22,7 +22,8 @@
* *
* Called if/when the PwmOut is GC'ed. * 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<PwmOut*>(void_ptr); delete static_cast<PwmOut*>(void_ptr);
} }
+6 -2
View File
@@ -106,18 +106,22 @@ handler_throw_test (const jerry_call_info_t *call_info_p, /**< call information
} /* handler_throw_test */ } /* handler_throw_test */
static void 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 ((uintptr_t) native_p == (uintptr_t) 0x0000000000000000ull);
TEST_ASSERT (info_p->free_cb == handler_construct_1_freecb);
printf ("ok object free callback\n"); printf ("ok object free callback\n");
test_api_is_free_callback_was_called = true; test_api_is_free_callback_was_called = true;
} /* handler_construct_1_freecb */ } /* handler_construct_1_freecb */
static void 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 ((uintptr_t) native_p == (uintptr_t) 0x0012345678abcdefull);
TEST_ASSERT (info_p->free_cb == handler_construct_2_freecb);
printf ("ok object free callback\n"); printf ("ok object free callback\n");
test_api_is_free_callback_was_called = true; test_api_is_free_callback_was_called = true;
+3 -1
View File
@@ -22,9 +22,11 @@ static void *global_p = (void *) &global_int;
static int global_counter = 0; static int global_counter = 0;
static void 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; (void) native_p;
TEST_ASSERT (info_p->free_cb == native_free_callback);
global_counter++; global_counter++;
} /* native_free_callback */ } /* native_free_callback */
+4 -2
View File
@@ -132,9 +132,11 @@ test_internal_prop (void)
static int test_data = 1; 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 */ } /* free_test_data */
static const jerry_object_native_info_t test_info = static const jerry_object_native_info_t test_info =
+6 -4
View File
@@ -150,11 +150,13 @@ struct test_data
}; };
static void 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); TEST_ASSERT (native_p != NULL);
struct test_data *native_p = (struct test_data *) user_p; TEST_ASSERT (info_p->free_cb == proxy_native_freecb);
native_p->value = -1; struct test_data *data_p = (struct test_data *) native_p;
data_p->value = -1;
} /* proxy_native_freecb */ } /* proxy_native_freecb */
static const jerry_object_native_info_t proxy_native_info = static const jerry_object_native_info_t proxy_native_info =
+4 -2
View File
@@ -24,10 +24,12 @@
static int native_free_cb_call_count; static int native_free_cb_call_count;
static void 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) native_p;
(void) info_p;
++native_free_cb_call_count;
} /* native_free_cb */ } /* native_free_cb */
static const jerry_object_native_info_t native_info = static const jerry_object_native_info_t native_info =
@@ -24,10 +24,12 @@
static int native_free_cb_call_count; static int native_free_cb_call_count;
static void 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) native_p;
(void) info_p;
++native_free_cb_call_count;
} /* native_free_cb */ } /* native_free_cb */
static const jerry_object_native_info_t native_info = static const jerry_object_native_info_t native_info =
@@ -27,10 +27,12 @@ static size_t native_free_cb_call_count;
static const size_t handle_count = JERRYX_HANDLE_PRELIST_SIZE + 1; static const size_t handle_count = JERRYX_HANDLE_PRELIST_SIZE + 1;
static void 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) native_p;
(void) info_p;
++native_free_cb_call_count;
} /* native_free_cb */ } /* native_free_cb */
static const jerry_object_native_info_t native_info = static const jerry_object_native_info_t native_info =
@@ -27,10 +27,12 @@ static size_t native_free_cb_call_count;
static const size_t handle_count = JERRYX_HANDLE_PRELIST_SIZE * 2; static const size_t handle_count = JERRYX_HANDLE_PRELIST_SIZE * 2;
static void 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) native_p;
(void) info_p;
++native_free_cb_call_count;
} /* native_free_cb */ } /* native_free_cb */
static const jerry_object_native_info_t native_info = static const jerry_object_native_info_t native_info =
@@ -27,10 +27,12 @@
static int native_free_cb_call_count; static int native_free_cb_call_count;
static void 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) native_p;
(void) info_p;
++native_free_cb_call_count;
} /* native_free_cb */ } /* native_free_cb */
static const jerry_object_native_info_t native_info = static const jerry_object_native_info_t native_info =
@@ -24,10 +24,12 @@
static int native_free_cb_call_count; static int native_free_cb_call_count;
static void 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) native_p;
(void) info_p;
++native_free_cb_call_count;
} /* native_free_cb */ } /* native_free_cb */
static const jerry_object_native_info_t native_info = static const jerry_object_native_info_t native_info =
+4 -2
View File
@@ -25,10 +25,12 @@ static int native_free_cb_call_count;
static int reusing_times = 10; static int reusing_times = 10;
static void 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) native_p;
(void) info_p;
++native_free_cb_call_count;
} /* native_free_cb */ } /* native_free_cb */
static const jerry_object_native_info_t native_info = static const jerry_object_native_info_t native_info =
+4 -2
View File
@@ -24,10 +24,12 @@
static int native_free_cb_call_count; static int native_free_cb_call_count;
static void 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) native_p;
(void) info_p;
++native_free_cb_call_count;
} /* native_free_cb */ } /* native_free_cb */
static const jerry_object_native_info_t native_info = static const jerry_object_native_info_t native_info =