Allow the JS objects to have more than one native pointer data (#2814)

Currently JS objects can only have one native pointer data which could be a limitation in special cases.
This patch allows to register multiple native infos, which can be accessed/associated with the corresponding `jerry_object_native_info_t`.

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
Robert Fancsik
2019-04-16 07:50:49 +02:00
committed by László Langó
parent c818930cdc
commit b3f4aa6816
14 changed files with 436 additions and 180 deletions
+35 -13
View File
@@ -2591,9 +2591,8 @@ jerry_objects_foreach_by_native_info (const jerry_object_native_info_t *native_i
{
if (!ecma_is_lexical_environment (iter_p))
{
native_pointer_p = ecma_get_native_pointer_value (iter_p);
native_pointer_p = ecma_get_native_pointer_value (iter_p, (void *) native_info_p);
if (native_pointer_p
&& ((const jerry_object_native_info_t *) native_pointer_p->info_p) == native_info_p
&& !foreach_p (ecma_make_object_value (iter_p), native_pointer_p->data_p, user_data_p))
{
return true;
@@ -2605,11 +2604,10 @@ jerry_objects_foreach_by_native_info (const jerry_object_native_info_t *native_i
} /* jerry_objects_foreach_by_native_info */
/**
* Get native pointer and its type information, associated with specified object.
* Get native pointer and its type information, associated with the given native type info.
*
* Note:
* If native pointer is present, its type information is returned
* in out_native_pointer_p and out_native_info_p.
* If native pointer is present, its type information is returned in out_native_pointer_p
*
* @return true - if there is an associated pointer,
* false - otherwise
@@ -2617,8 +2615,8 @@ jerry_objects_foreach_by_native_info (const jerry_object_native_info_t *native_i
bool
jerry_get_object_native_pointer (const jerry_value_t obj_val, /**< object to get native pointer from */
void **out_native_pointer_p, /**< [out] native pointer */
const jerry_object_native_info_t **out_native_info_p) /**< [out] the type info
* of the native pointer */
const jerry_object_native_info_t *native_info_p) /**< the type info
* of the native pointer */
{
jerry_assert_api_available ();
@@ -2628,7 +2626,7 @@ jerry_get_object_native_pointer (const jerry_value_t obj_val, /**< object to get
}
ecma_native_pointer_t *native_pointer_p;
native_pointer_p = ecma_get_native_pointer_value (ecma_get_object_from_value (obj_val));
native_pointer_p = ecma_get_native_pointer_value (ecma_get_object_from_value (obj_val), (void *) native_info_p);
if (native_pointer_p == NULL)
{
@@ -2640,11 +2638,6 @@ jerry_get_object_native_pointer (const jerry_value_t obj_val, /**< object to get
*out_native_pointer_p = native_pointer_p->data_p;
}
if (out_native_info_p != NULL)
{
*out_native_info_p = (const jerry_object_native_info_t *) native_pointer_p->info_p;
}
return true;
} /* jerry_get_object_native_pointer */
@@ -2676,6 +2669,35 @@ jerry_set_object_native_pointer (const jerry_value_t obj_val, /**< object to set
}
} /* jerry_set_object_native_pointer */
/**
* Delete the previously set native pointer by the native type info from the specified object.
*
* Note:
* If the specified object has no matching native pointer for the given native type info
* the function has no effect.
*
* Note:
* This operation cannot throw an exception.
*
* @return true - if the native pointer has been deleted succesfully
* false - otherwise
*/
bool
jerry_delete_object_native_pointer (const jerry_value_t obj_val, /**< object to delete native pointer from */
const jerry_object_native_info_t *native_info_p) /**< object's native type info */
{
jerry_assert_api_available ();
if (ecma_is_value_object (obj_val))
{
ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
return ecma_delete_native_pointer_property (object_p, (void *) native_info_p);
}
return false;
} /* jerry_delete_object_native_pointer */
/**
* Applies the given function to the every property in the object.
*
+15 -8
View File
@@ -501,17 +501,24 @@ ecma_gc_free_native_pointer (ecma_property_t *property_p) /**< property */
native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t,
value_p->value);
if (native_pointer_p->info_p != NULL)
while (native_pointer_p != NULL)
{
ecma_object_native_free_callback_t free_cb = native_pointer_p->info_p->free_cb;
if (free_cb != NULL)
if (native_pointer_p->info_p != NULL)
{
free_cb (native_pointer_p->data_p);
}
}
ecma_object_native_free_callback_t free_cb = native_pointer_p->info_p->free_cb;
jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t));
if (free_cb != NULL)
{
free_cb (native_pointer_p->data_p);
}
}
ecma_native_pointer_t *next_p = native_pointer_p->next_p;
jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t));
native_pointer_p = next_p;
}
} /* ecma_gc_free_native_pointer */
/**
+2 -1
View File
@@ -294,10 +294,11 @@ typedef struct
/**
* Representation for native pointer data.
*/
typedef struct
typedef struct ecma_native_pointer_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;
/**
@@ -15,6 +15,7 @@
#include "ecma-alloc.h"
#include "ecma-globals.h"
#include "ecma-objects.h"
#include "ecma-helpers.h"
/** \addtogroup ecma ECMA
@@ -42,10 +43,10 @@ ecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create
ecma_native_pointer_t *native_pointer_p;
if (is_new)
if (property_p == NULL)
{
ecma_property_value_t *value_p;
value_p = ecma_create_named_data_property (obj_p, name_p, ECMA_PROPERTY_FLAG_WRITABLE, &property_p);
value_p = ecma_create_named_data_property (obj_p, name_p, ECMA_PROPERTY_CONFIGURABLE_WRITABLE, &property_p);
ECMA_CONVERT_DATA_PROPERTY_TO_INTERNAL_PROPERTY (property_p);
@@ -57,11 +58,37 @@ ecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create
{
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);
ecma_native_pointer_t *iter_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value_p->value);
/* There should be at least 1 native pointer in the chain */
JERRY_ASSERT (iter_p != NULL);
while (true)
{
if (iter_p->info_p == info_p)
{
/* The native info already exists -> update the corresponding data */
iter_p->data_p = native_p;
return false;
}
if (iter_p->next_p == NULL)
{
/* The native info does not exist -> append a new element to the chain */
break;
}
iter_p = iter_p->next_p;
}
native_pointer_p = jmem_heap_alloc_block (sizeof (ecma_native_pointer_t));
iter_p->next_p = native_pointer_p;
}
native_pointer_p->data_p = native_p;
native_pointer_p->info_p = info_p;
native_pointer_p->next_p = NULL;
return is_new;
} /* ecma_create_native_pointer_property */
@@ -77,7 +104,8 @@ ecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create
* NULL otherwise
*/
ecma_native_pointer_t *
ecma_get_native_pointer_value (ecma_object_t *obj_p) /**< object to get property value from */
ecma_get_native_pointer_value (ecma_object_t *obj_p, /**< object to get property value from */
void *info_p) /**< native pointer's type info */
{
ecma_string_t *name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p);
@@ -89,9 +117,94 @@ 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);
return 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);
while (native_pointer_p != NULL)
{
if (native_pointer_p->info_p == info_p)
{
return native_pointer_p;
}
native_pointer_p = native_pointer_p->next_p;
}
return NULL;
} /* ecma_get_native_pointer_value */
/**
* Delete the previously set native pointer by the native type info from the specified object.
*
* Note:
* If the specified object has no matching native pointer for the given native type info
* the function has no effect.
*
* @return true - if the native pointer has been deleted succesfully
* false - otherwise
*/
bool
ecma_delete_native_pointer_property (ecma_object_t *obj_p, /**< object to delete property from */
void *info_p) /**< native pointer's type info */
{
ecma_string_t *name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p);
if (property_p == NULL)
{
return false;
}
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
ecma_native_pointer_t *native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t,
value_p->value);
ecma_native_pointer_t *prev_p = NULL;
JERRY_ASSERT (native_pointer_p != NULL);
while (native_pointer_p != NULL)
{
if (native_pointer_p->info_p == info_p)
{
if (prev_p == NULL)
{
if (native_pointer_p->next_p == NULL)
{
/* Only one native pointer property exists, so the property can be deleted as well. */
ecma_op_object_delete (obj_p, name_p, false);
jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t));
return true;
}
else
{
/* There are at least two native pointers and the first one should be deleted.
In this case the second element's data is copied to the head of the chain, and freed as well. */
ecma_native_pointer_t *next_p = native_pointer_p->next_p;
memcpy (native_pointer_p, next_p, sizeof (ecma_native_pointer_t));
jmem_heap_free_block (next_p, sizeof (ecma_native_pointer_t));
return true;
}
}
else
{
/* There are at least two native pointers and not the first element should be deleted.
In this case the current element's next element reference is copied to the previous element. */
prev_p->next_p = native_pointer_p->next_p;
jmem_heap_free_block (native_pointer_p, sizeof (ecma_native_pointer_t));
return true;
}
}
prev_p = native_pointer_p;
native_pointer_p = native_pointer_p->next_p;
}
return false;
} /* ecma_delete_native_pointer_property */
/**
* @}
* @}
+2 -1
View File
@@ -389,7 +389,8 @@ void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p);
/* ecma-helpers-external-pointers.c */
bool ecma_create_native_pointer_property (ecma_object_t *obj_p, void *native_p, void *info_p);
ecma_native_pointer_t *ecma_get_native_pointer_value (ecma_object_t *obj_p);
ecma_native_pointer_t *ecma_get_native_pointer_value (ecma_object_t *obj_p, void *info_p);
bool ecma_delete_native_pointer_property (ecma_object_t *obj_p, void *info_p);
/* ecma-helpers-conversion.c */
ecma_number_t ecma_utf8_string_to_number (const lit_utf8_byte_t *str_p, lit_utf8_size_t str_size);
+3 -1
View File
@@ -527,10 +527,12 @@ jerry_value_t jerry_set_prototype (const jerry_value_t obj_val, const jerry_valu
bool jerry_get_object_native_pointer (const jerry_value_t obj_val,
void **out_native_pointer_p,
const jerry_object_native_info_t **out_pointer_info_p);
const jerry_object_native_info_t *native_pointer_info_p);
void jerry_set_object_native_pointer (const jerry_value_t obj_val,
void *native_pointer_p,
const jerry_object_native_info_t *native_info_p);
bool jerry_delete_object_native_pointer (const jerry_value_t obj_val,
const jerry_object_native_info_t *native_info_p);
bool jerry_objects_foreach (jerry_objects_foreach_t foreach_p,
void *user_data);