Add 'type' argument to set/get native handle API (#1711)

Ecma-object have native handle type inside, and binding code could use
type info to validate native handle's type.

Related issue #1681

JerryScript-DCO-1.0-Signed-off-by: Zidong Jiang zidong.jiang@intel.com
This commit is contained in:
Zidong Jiang
2017-04-10 16:51:37 +08:00
committed by GitHub
parent 574dff512e
commit e522e740a7
12 changed files with 486 additions and 141 deletions
-1
View File
@@ -86,7 +86,6 @@ DECLARE_ROUTINES_FOR (collection_header)
DECLARE_ROUTINES_FOR (collection_chunk)
DECLARE_ROUTINES_FOR (string)
DECLARE_ROUTINES_FOR (getter_setter_pointers)
DECLARE_ROUTINES_FOR (external_pointer)
/**
* Allocate memory for extended object
-12
View File
@@ -97,18 +97,6 @@ ecma_getter_setter_pointers_t *ecma_alloc_getter_setter_pointers (void);
*/
void ecma_dealloc_getter_setter_pointers (ecma_getter_setter_pointers_t *getter_setter_pointers_p);
/**
* Allocate memory for external pointer
*
* @return pointer to allocated memory
*/
ecma_external_pointer_t *ecma_alloc_external_pointer (void);
/**
* Dealloc memory from external pointer
*/
void ecma_dealloc_external_pointer (ecma_external_pointer_t *external_pointer_p);
/*
* Allocate memory for extended object
*
+53 -23
View File
@@ -353,6 +353,47 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
}
} /* ecma_gc_mark */
/**
* Free the native handle/pointer by calling its free callback
*/
static void
ecma_gc_free_native_pointer (ecma_property_t *property_p, /**< property */
lit_magic_string_id_t id) /**< identifier of internal property */
{
JERRY_ASSERT (property_p != NULL);
JERRY_ASSERT (id == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
|| id == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
ecma_external_pointer_t native_p;
ecma_external_pointer_t free_cb;
void *package_p;
package_p = ECMA_GET_INTERNAL_VALUE_POINTER (void, value_p->value);
if (id == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE)
{
native_p = ((ecma_native_handle_package_t *) package_p)->handle_p;
free_cb = ((ecma_native_handle_package_t *) package_p)->free_cb;
if ((jerry_object_free_callback_t) free_cb != NULL)
{
((jerry_object_free_callback_t) free_cb) ((uintptr_t) native_p);
}
}
else
{
native_p = ((ecma_native_pointer_package_t *) package_p)->native_p;
free_cb = *(ecma_external_pointer_t *) (((ecma_native_pointer_package_t *) package_p)->info_p);
if ((jerry_object_native_free_callback_t) free_cb != NULL)
{
((jerry_object_native_free_callback_t) free_cb) ((void *) native_p);
}
}
} /* ecma_gc_free_native_pointer */
/**
* Free specified object
*/
@@ -365,28 +406,6 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
bool obj_is_not_lex_env = !ecma_is_lexical_environment (object_p);
if (obj_is_not_lex_env)
{
/* if the object provides free callback, invoke it with handle stored in the object */
ecma_external_pointer_t freecb_p;
ecma_external_pointer_t native_p;
bool is_retrieved = ecma_get_external_pointer_value (object_p,
LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK,
&freecb_p);
if (is_retrieved && ((jerry_object_free_callback_t) freecb_p) != NULL)
{
is_retrieved = ecma_get_external_pointer_value (object_p,
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE,
&native_p);
JERRY_ASSERT (is_retrieved);
jerry_dispatch_object_free_callback (freecb_p, native_p);
}
}
if (obj_is_not_lex_env
|| ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
{
@@ -410,9 +429,20 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
{
ecma_property_t *property_p = (ecma_property_t *) (prop_iter_p->types + i);
jmem_cpointer_t name_cp = prop_pair_p->names_cp[i];
/* Call the native's free callback. */
if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_STRING_CONTAINER_MAGIC_STRING
&& (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
|| name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER))
{
ecma_gc_free_native_pointer (property_p, (lit_magic_string_id_t) name_cp);
}
if (prop_iter_p->types[i] != ECMA_PROPERTY_TYPE_DELETED)
{
ecma_free_property (object_p, prop_pair_p->names_cp[i], prop_iter_p->types + i);
ecma_free_property (object_p, name_cp, property_p);
}
}
+22
View File
@@ -195,6 +195,28 @@ typedef int32_t ecma_integer_value_t;
*/
typedef uintptr_t ecma_external_pointer_t;
/**
* Representation for native handle package.
*
* Note: It is for the deprecated api:
* jerry_get_object_native_handle and jerry_set_object_native_handle
*/
typedef struct
{
ecma_external_pointer_t handle_p; /**< points to the external native object */
ecma_external_pointer_t free_cb; /**< free callback of the native handle */
} ecma_native_handle_package_t;
/**
* Representation of the native pointer package.
*/
typedef struct
{
ecma_external_pointer_t native_p; /**< points to the external native object */
ecma_external_pointer_t info_p; /**< type info of the native pointer */
} ecma_native_pointer_package_t;
/**
* Special property identifiers.
*/
@@ -25,24 +25,24 @@
*/
/**
* Create internal property with specified identifier and store external pointer in the property.
* Create internal property with specified identifier and store native handle/pointer of the object.
*
* Note:
* property identifier should be one of the following:
* - LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
* - LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK
* - LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER
*
* @return true - if property was just created with specified value,
* false - otherwise, if property existed before the call, it's value was updated
*/
bool
ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to create property in */
lit_magic_string_id_t id, /**< identifier of internal
* property to create */
ecma_external_pointer_t ptr_value) /**< value to store in the property */
static bool
ecma_create_native_property (ecma_object_t *obj_p, /**< object to create property in */
lit_magic_string_id_t id, /**< identifier of internal
* property to create */
void *package_p) /**< value to store in the property */
{
JERRY_ASSERT (id == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
|| id == LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK);
|| id == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
ecma_string_t name;
ecma_init_ecma_magic_string (&name, id);
@@ -58,6 +58,7 @@ ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to crea
else
{
value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
ecma_free_native_package_property (property_p, id);
}
JERRY_ASSERT (ECMA_STRING_IS_REF_EQUALS_TO_ONE (&name));
@@ -65,51 +66,72 @@ ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to crea
JERRY_STATIC_ASSERT (sizeof (uint32_t) <= sizeof (value_p->value),
size_of_internal_property_value_must_be_greater_than_or_equal_to_4_bytes);
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
value_p->value = (ecma_value_t) ptr_value;
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
ecma_external_pointer_t *handler_p;
if (is_new)
{
handler_p = ecma_alloc_external_pointer ();
ECMA_SET_NON_NULL_POINTER (value_p->value, handler_p);
}
else
{
handler_p = ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t, value_p->value);
}
*handler_p = ptr_value;
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
ECMA_SET_INTERNAL_VALUE_POINTER (value_p->value, package_p);
return is_new;
} /* ecma_create_external_pointer_property */
} /* ecma_create_native_property */
/**
* Get value of external pointer stored in the object's property with specified identifier
* Create a native handle property to store the native handle and its free callback.
*
* @return true - if property was just created with specified value,
* false - otherwise, if property existed before the call, it's value was updated
*/
bool
ecma_create_native_handle_property (ecma_object_t *obj_p, /**< object to create property in */
ecma_external_pointer_t handle_p, /**< native handle */
ecma_external_pointer_t free_cb) /**< native handle's free callback*/
{
ecma_native_handle_package_t *package_p;
package_p = jmem_heap_alloc_block (sizeof (ecma_native_handle_package_t));
package_p->handle_p = handle_p;
package_p->free_cb = free_cb;
return ecma_create_native_property (obj_p,
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE,
package_p);
} /* ecma_create_native_handle_property */
/**
* Create a native pointer property to store the native pointer and its type info.
*
* @return true - if property was just created with specified value,
* false - otherwise, if property existed before the call, it's value was updated
*/
bool
ecma_create_native_pointer_property (ecma_object_t *obj_p, /**< object to create property in */
ecma_external_pointer_t native_p, /**< native pointer */
ecma_external_pointer_t info_p) /**< native pointer's type info */
{
ecma_native_pointer_package_t *package_p;
package_p = jmem_heap_alloc_block (sizeof (ecma_native_pointer_package_t));
package_p->native_p = native_p;
package_p->info_p = info_p;
return ecma_create_native_property (obj_p,
LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER,
package_p);
} /* ecma_create_native_pointer_property */
/**
* Get value of native package stored in the object's property with specified identifier
*
* Note:
* property identifier should be one of the following:
* - LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
* - LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK
* - LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER
*
* @return true - if property exists and it's value is returned through out_pointer_p,
* false - otherwise (value returned through out_pointer_p is NULL)
*/
bool
ecma_get_external_pointer_value (ecma_object_t *obj_p, /**< object to get property value from */
lit_magic_string_id_t id, /**< identifier of internal property
* to get value from */
ecma_external_pointer_t *out_pointer_p) /**< [out] value of the external pointer */
ecma_get_native_package_value (ecma_object_t *obj_p, /**< object to get property value from */
lit_magic_string_id_t id, /**< identifier of internal property
* to get value from */
void **out_pointer_p) /**< [out] value of the native package */
{
JERRY_ASSERT (id == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
|| id == LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK);
|| id == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
ecma_string_t name;
ecma_init_ecma_magic_string (&name, id);
@@ -120,51 +142,46 @@ ecma_get_external_pointer_value (ecma_object_t *obj_p, /**< object to get proper
if (property_p == NULL)
{
*out_pointer_p = (ecma_external_pointer_t) NULL;
*out_pointer_p = NULL;
return false;
}
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
*out_pointer_p = value_p->value;
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
*out_pointer_p = *ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t, value_p->value);
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
*out_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (void, value_p->value);
return true;
} /* ecma_get_external_pointer_value */
} /* ecma_get_native_package_value */
/**
* Free memory associated with external pointer stored in the property
* Free the allocated native package struct.
*
* Note:
* property identifier should be one of the following:
* - LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
* - LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK
* - LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER
*/
void
ecma_free_external_pointer_in_property (ecma_property_t *prop_p) /**< internal property */
ecma_free_native_package_property (ecma_property_t *prop_p, /**< native property */
lit_magic_string_id_t id) /**< identifier of internal */
{
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
JERRY_ASSERT (id == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
|| id == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
/* no additional memory was allocated for the pointer storage */
JERRY_UNUSED (prop_p);
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (prop_p);
void *package_p;
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
package_p = ECMA_GET_INTERNAL_VALUE_POINTER (void, value_p->value);
ecma_external_pointer_t *handler_p = ECMA_GET_NON_NULL_POINTER (ecma_external_pointer_t,
ECMA_PROPERTY_VALUE_PTR (prop_p)->value);
if (id == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE)
{
jmem_heap_free_block (package_p, sizeof (ecma_native_handle_package_t));
return;
}
ecma_dealloc_external_pointer (handler_p);
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
} /* ecma_free_external_pointer_in_property */
jmem_heap_free_block (package_p, sizeof (ecma_native_pointer_package_t));
} /* ecma_free_native_package_property */
/**
* @}
+2 -2
View File
@@ -731,9 +731,9 @@ ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to
if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_STRING_CONTAINER_MAGIC_STRING)
{
if (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE
|| name_cp == LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK)
|| name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER)
{
ecma_free_external_pointer_in_property (property_p);
ecma_free_native_package_property (property_p, (lit_magic_string_id_t) name_cp);
break;
}
}
+11 -5
View File
@@ -341,11 +341,17 @@ void ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p);
void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p);
/* ecma-helpers-external-pointers.c */
bool ecma_create_external_pointer_property (ecma_object_t *obj_p, lit_magic_string_id_t id,
ecma_external_pointer_t ptr_value);
bool ecma_get_external_pointer_value (ecma_object_t *obj_p, lit_magic_string_id_t id,
ecma_external_pointer_t *out_pointer_p);
void ecma_free_external_pointer_in_property (ecma_property_t *prop_p);
bool ecma_create_native_handle_property (ecma_object_t *obj_p,
ecma_external_pointer_t handle_p,
ecma_external_pointer_t free_cb);
bool ecma_create_native_pointer_property (ecma_object_t *obj_p,
ecma_external_pointer_t native_p,
ecma_external_pointer_t info_p);
bool ecma_get_native_package_value (ecma_object_t *obj_p,
lit_magic_string_id_t id,
void **out_pointer_p);
void ecma_free_native_package_property (ecma_property_t *prop_p,
lit_magic_string_id_t id);
/* 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);
+72 -14
View File
@@ -1902,7 +1902,9 @@ jerry_set_prototype (const jerry_value_t obj_val, /**< object value */
} /* jerry_set_prototype */
/**
* Get native handle, associated with specified object
* Get native handle, associated with specified object.
*
* Note: This API is deprecated, please use jerry_get_object_native_pointer instaed.
*
* @return true - if there is an associated handle (handle is returned through out_handle_p),
* false - otherwise
@@ -1913,22 +1915,53 @@ jerry_get_object_native_handle (const jerry_value_t obj_val, /**< object to get
{
jerry_assert_api_available ();
uintptr_t handle_value;
ecma_native_handle_package_t *package_p;
bool does_exist = ecma_get_external_pointer_value (ecma_get_object_from_value (obj_val),
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE,
&handle_value);
bool does_exist = ecma_get_native_package_value (ecma_get_object_from_value (obj_val),
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE,
(void **) &package_p);
if (does_exist)
{
*out_handle_p = handle_value;
*out_handle_p = package_p->handle_p;
}
return does_exist;
} /* jerry_get_object_native_handle */
/**
* Set native handle and an optional free callback for the specified object
* Get native pointer and its type information, associated with specified object.
*
* @return true - if there is an associated pointer (pointer is returned through out_handle_p),
* false - otherwise
*/
bool
jerry_get_object_native_pointer (const jerry_value_t obj_val, /**< object to get native pointer from */
void **out_native_p, /**< [out] native pointer */
const jerry_object_native_info_t **out_info_p) /**< [out] the type info
* of the native pointer */
{
jerry_assert_api_available ();
ecma_native_pointer_package_t *package_p;
bool does_exist = ecma_get_native_package_value (ecma_get_object_from_value (obj_val),
LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER,
(void **) &package_p);
if (does_exist)
{
*out_native_p = (void *) package_p->native_p;
*out_info_p = (const jerry_object_native_info_t *) package_p->info_p;
}
return does_exist;
} /* jerry_get_object_native_pointer */
/**
* Set native handle and an optional free callback for the specified object.
*
* Note: This API is deprecated, please use jerry_set_object_native_pointer instaed.
*
* Note:
* If native handle was already set for the object, its value is updated.
@@ -1948,15 +1981,40 @@ jerry_set_object_native_handle (const jerry_value_t obj_val, /**< object to set
ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
ecma_create_external_pointer_property (object_p,
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE,
handle_p);
ecma_create_external_pointer_property (object_p,
LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK,
(uintptr_t) freecb_p);
ecma_create_native_handle_property (object_p,
handle_p,
(ecma_external_pointer_t) freecb_p);
} /* jerry_set_object_native_handle */
/**
* Set native pointer and an optional type info for the specified object.
*
*
* Note:
* If native pointer was already set for the object, its value is updated.
*
* Note:
* If a non-NULL free callback is specified in the native type info,
* it will be called by the garbage collector when the object is freed.
* The type info is always overwrites the previous value, so passing
* a NULL value deletes the current type info.
*/
void
jerry_set_object_native_pointer (const jerry_value_t obj_val, /**< object to set native pointer in */
void *native_p, /**< native pointer */
const jerry_object_native_info_t *info_p) /**< object's native type info */
{
jerry_assert_api_available ();
ecma_object_t *object_p = ecma_get_object_from_value (obj_val);
ecma_create_native_pointer_property (object_p,
(ecma_external_pointer_t) native_p,
(ecma_external_pointer_t) info_p);
} /* jerry_set_object_native_pointer */
/**
* Applies the given function to the every property in the object.
*
+29 -1
View File
@@ -25,6 +25,12 @@ extern "C"
{
#endif /* __cplusplus */
#ifdef __GNUC__
#define JERRY_DEPRECATED_API __attribute__((deprecated))
#else /* !__GNUC__ */
/* TODO: for other compilers */
#define JERRY_DEPRECATED_API
#endif /* __GNUC__ */
/** \addtogroup jerry Jerry engine interface
* @{
*/
@@ -156,16 +162,28 @@ typedef jerry_value_t (*jerry_external_handler_t) (const jerry_value_t function_
const jerry_length_t args_count);
/**
* Native free callback of an object
* Native free callback of an object (deprecated)
*/
typedef void (*jerry_object_free_callback_t) (const uintptr_t native_p);
/**
* Native free callback of an object
*/
typedef void (*jerry_object_native_free_callback_t) (void *native_p);
/**
* Function type applied for each data property of an object
*/
typedef bool (*jerry_object_property_foreach_t) (const jerry_value_t property_name,
const jerry_value_t property_value,
void *user_data_p);
/**
* Type information of a native pointer.
*/
typedef struct
{
jerry_object_native_free_callback_t free_cb; /**< the free callback of the native pointer */
} jerry_object_native_info_t;
/**
* General engine functions
@@ -322,9 +340,19 @@ jerry_value_t jerry_get_object_keys (const jerry_value_t obj_val);
jerry_value_t jerry_get_prototype (const jerry_value_t obj_val);
jerry_value_t jerry_set_prototype (const jerry_value_t obj_val, const jerry_value_t proto_obj_val);
JERRY_DEPRECATED_API
bool jerry_get_object_native_handle (const jerry_value_t obj_val, uintptr_t *out_handle_p);
JERRY_DEPRECATED_API
void jerry_set_object_native_handle (const jerry_value_t obj_val, uintptr_t handle_p,
jerry_object_free_callback_t freecb_p);
bool jerry_get_object_native_pointer (const jerry_value_t obj_val,
void **out_native_p,
const jerry_object_native_info_t **out_info_p);
void jerry_set_object_native_pointer (const jerry_value_t obj_val,
void *native_p,
const jerry_object_native_info_t *info_p);
bool jerry_foreach_object_property (const jerry_value_t obj_val, jerry_object_property_foreach_t foreach_p,
void *user_data_p);
+3 -4
View File
@@ -36,10 +36,9 @@ typedef enum
#undef LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE
LIT_NON_INTERNAL_MAGIC_STRING__COUNT, /**< number of non-internal magic strings */
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE = LIT_NON_INTERNAL_MAGIC_STRING__COUNT, /**< native handle associated
* with an object */
LIT_INTERNAL_MAGIC_STRING_FREE_CALLBACK, /**< object's native free callback */
LIT_INTERNAL_MAGIC_STRING_NATIVE_HANDLE = LIT_NON_INTERNAL_MAGIC_STRING__COUNT, /**< native handle package
* associated with an object */
LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER, /**< native pointer package associated with an object */
LIT_MAGIC_STRING__COUNT /**< number of magic strings */
} lit_magic_string_id_t;