From 48cc9b5c9d20f0dd15fe999408a0eeaffae89c17 Mon Sep 17 00:00:00 2001 From: SaeHie Park Date: Tue, 28 Apr 2015 15:10:27 +0900 Subject: [PATCH 1/3] inital code for object free callback, issue #2 JerryScript-DCO-1.0-Signed-off-by: SaeHie Park saehie.park@samsung.com --- jerry-core/ecma/base/ecma-gc.cpp | 24 +++++++++ jerry-core/ecma/base/ecma-globals.h | 1 + .../base/ecma-helpers-external-pointers.cpp | 18 ++++--- jerry-core/ecma/base/ecma-helpers.cpp | 1 + jerry-core/jerry-api.h | 12 +++++ jerry-core/jerry-internal.h | 6 +++ jerry-core/jerry.cpp | 51 +++++++++++++++++++ tests/unit/test_api.cpp | 10 ++++ 8 files changed, 117 insertions(+), 6 deletions(-) diff --git a/jerry-core/ecma/base/ecma-gc.cpp b/jerry-core/ecma/base/ecma-gc.cpp index 30e72526c8..f9d992000e 100644 --- a/jerry-core/ecma/base/ecma-gc.cpp +++ b/jerry-core/ecma/base/ecma-gc.cpp @@ -34,6 +34,10 @@ #include "jrt-libc-includes.h" #include "jrt-bit-fields.h" +#define JERRY_INTERNAL +#include "jerry-internal.h" + + /** * An object's GC color * @@ -320,6 +324,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ case ECMA_INTERNAL_PROPERTY_CODE: /* an integer */ case ECMA_INTERNAL_PROPERTY_NATIVE_CODE: /* an external pointer */ case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */ + case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an object free callback */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_EXTENSION_ID: /* an integer */ @@ -360,6 +365,25 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */ if (!ecma_is_lexical_environment (object_p) || ecma_get_lex_env_type (object_p) != ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND) { + /* call object free callback with given handle */ + { + ecma_external_pointer_t freecb_p; + ecma_external_pointer_t native_p; + + bool is_retrieved = + ecma_get_external_pointer_value (object_p, + ECMA_INTERNAL_PROPERTY_FREE_CALLBACK, + &freecb_p); + if (is_retrieved && freecb_p) + is_retrieved = + ecma_get_external_pointer_value (object_p, + ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE, + &native_p); + + if (is_retrieved && native_p) + jerry_dispatch_object_free_callback (object_p, freecb_p, native_p); + } + for (ecma_property_t *property = ecma_get_property_list (object_p), *next_property_p; property != NULL; property = next_property_p) diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index b8cd218138..1aee268b7e 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -206,6 +206,7 @@ typedef enum ECMA_INTERNAL_PROPERTY_CODE, /**< [[Code]] */ ECMA_INTERNAL_PROPERTY_NATIVE_CODE, /**< native handler location descriptor */ ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE, /**< native handle associated with an object */ + ECMA_INTERNAL_PROPERTY_FREE_CALLBACK, /**< native free callback associated with an object */ ECMA_INTERNAL_PROPERTY_FORMAL_PARAMETERS, /**< [[FormalParameters]] */ ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE, /**< [[Primitive value]] for String objects */ ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE, /**< [[Primitive value]] for Number objects */ diff --git a/jerry-core/ecma/base/ecma-helpers-external-pointers.cpp b/jerry-core/ecma/base/ecma-helpers-external-pointers.cpp index 779ff8bf34..91ddbc9114 100644 --- a/jerry-core/ecma/base/ecma-helpers-external-pointers.cpp +++ b/jerry-core/ecma/base/ecma-helpers-external-pointers.cpp @@ -30,7 +30,8 @@ * Note: * property identifier should be one of the following: * - ECMA_INTERNAL_PROPERTY_NATIVE_CODE; - * - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE. + * - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE; + * - ECMA_INTERNAL_PROPERTY_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. @@ -42,7 +43,8 @@ ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to crea ecma_external_pointer_t ptr_value) /**< value to store in the property */ { JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_CODE - || id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE); + || id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE + || id == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK); bool ret_val; ecma_property_t *prop_p = ecma_find_internal_property (obj_p, id); @@ -81,7 +83,8 @@ ecma_create_external_pointer_property (ecma_object_t *obj_p, /**< object to crea * Note: * property identifier should be one of the following: * - ECMA_INTERNAL_PROPERTY_NATIVE_CODE; - * - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE. + * - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE; + * - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK. * * @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). @@ -93,7 +96,8 @@ ecma_get_external_pointer_value (ecma_object_t *obj_p, /**< object to get proper ecma_external_pointer_t *out_pointer_p) /**< out: value of the external pointer */ { JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_CODE - || id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE); + || id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE + || id == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK); ecma_property_t* prop_p = ecma_find_internal_property (obj_p, id); @@ -126,13 +130,15 @@ ecma_get_external_pointer_value (ecma_object_t *obj_p, /**< object to get proper * Note: * property identifier should be one of the following: * - ECMA_INTERNAL_PROPERTY_NATIVE_CODE; - * - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE. + * - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE; + * - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK. */ void ecma_free_external_pointer_in_property (ecma_property_t *prop_p) /**< internal property */ { JERRY_ASSERT (prop_p->u.internal_property.type == ECMA_INTERNAL_PROPERTY_NATIVE_CODE - || prop_p->u.internal_property.type == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE); + || prop_p->u.internal_property.type == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE + || prop_p->u.internal_property.type == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK); if (sizeof (ecma_external_pointer_t) == sizeof (uint32_t)) { diff --git a/jerry-core/ecma/base/ecma-helpers.cpp b/jerry-core/ecma/base/ecma-helpers.cpp index 454a8e2e9a..114f33f4ce 100644 --- a/jerry-core/ecma/base/ecma-helpers.cpp +++ b/jerry-core/ecma/base/ecma-helpers.cpp @@ -780,6 +780,7 @@ ecma_free_internal_property (ecma_property_t *property_p) /**< the property */ case ECMA_INTERNAL_PROPERTY_NATIVE_CODE: /* an external pointer */ case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */ + case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an external pointer */ { ecma_free_external_pointer_in_property (property_p); diff --git a/jerry-core/jerry-api.h b/jerry-core/jerry-api.h index ec0c11d20a..264acd3d52 100644 --- a/jerry-core/jerry-api.h +++ b/jerry-core/jerry-api.h @@ -100,6 +100,10 @@ typedef bool (*jerry_external_handler_t) (const jerry_api_object_t *function_obj const jerry_api_value_t args_p [], const uint16_t args_count); +typedef void (*jerry_object_free_callback_t) (const jerry_api_object_t *object_p, + const uintptr_t native_p); + + extern EXTERN_C ssize_t jerry_api_string_to_char_buffer (const jerry_api_string_t *string_p, char *buffer_p, @@ -152,6 +156,14 @@ bool jerry_api_get_object_native_handle (jerry_api_object_t *object_p, uintptr_t extern EXTERN_C void jerry_api_set_object_native_handle (jerry_api_object_t *object_p, uintptr_t handle); +extern EXTERN_C +bool jerry_api_get_object_free_callback (jerry_api_object_t *object_p, + jerry_object_free_callback_t* out_freecb_p); + +extern EXTERN_C +void jerry_api_set_object_free_callback (jerry_api_object_t *object_p, + jerry_object_free_callback_t freecb_p); + extern EXTERN_C bool jerry_api_call_function (jerry_api_object_t *function_object_p, jerry_api_object_t *this_arg_p, diff --git a/jerry-core/jerry-internal.h b/jerry-core/jerry-internal.h index 9b0ce67a1f..008e55dd37 100644 --- a/jerry-core/jerry-internal.h +++ b/jerry-core/jerry-internal.h @@ -30,4 +30,10 @@ jerry_dispatch_external_function (ecma_object_t *function_object_p, const ecma_value_t args_p [], ecma_length_t args_count); +extern void +jerry_dispatch_object_free_callback (ecma_object_t *object_p, + ecma_external_pointer_t freecb_p, + ecma_external_pointer_t native_p); + + #endif /* !JERRY_INTERNAL_H */ diff --git a/jerry-core/jerry.cpp b/jerry-core/jerry.cpp index 4220bf1c7c..fe729b860c 100644 --- a/jerry-core/jerry.cpp +++ b/jerry-core/jerry.cpp @@ -424,6 +424,21 @@ jerry_dispatch_external_function (ecma_object_t *function_object_p, /**< externa return completion_value; } /* jerry_dispatch_external_function */ +/** + * Dispatch call to object free callback function + * + * Note: + * it's critical GC phase so should not re-enter jerry apis + */ +void +jerry_dispatch_object_free_callback (ecma_object_t *object_p, /**< object that is garbage colleted*/ + ecma_external_pointer_t freecb_p, /**< pointer to free callback handler */ + ecma_external_pointer_t native_p) /**< pointer to the function's native handler */ +{ + /* Todo: prevent call inside jerry again */ + ((jerry_object_free_callback_t) freecb_p) (object_p, (uintptr_t)native_p); +} + /** * Check if the specified object is a function object. * @@ -652,6 +667,42 @@ jerry_api_set_object_native_handle (jerry_api_object_t *object_p, /**< object to handle); } /* jerry_api_set_object_native_handle */ +/** + * Get object free callbaack handle, associated with specified object + * + * @return true - if there is associated handle (handle is returned through out_handle_p), + * false - otherwise. + */ +bool +jerry_api_get_object_free_callback (jerry_api_object_t *object_p, /**< object to get handle from */ + jerry_object_free_callback_t* out_freecb_p) /**< out: handle value */ +{ + uintptr_t handle_value; + + bool does_exist = ecma_get_external_pointer_value (object_p, + ECMA_INTERNAL_PROPERTY_FREE_CALLBACK, + &handle_value); + + if (does_exist) + { + *out_freecb_p = (jerry_object_free_callback_t)handle_value; + } + + return does_exist; +} /* jerry_api_get_object_native_handle */ + +/** + * Set object free callback native handle for the specified object + */ +void +jerry_api_set_object_free_callback (jerry_api_object_t *object_p, /**< object to set handle in */ + jerry_object_free_callback_t freecb_p) /**< free callback function */ +{ + ecma_create_external_pointer_property (object_p, + ECMA_INTERNAL_PROPERTY_FREE_CALLBACK, + (uintptr_t)freecb_p); +} /* jerry_api_set_object_freecb_handle */ + /** * Invoke function specified by a function object * diff --git a/tests/unit/test_api.cpp b/tests/unit/test_api.cpp index 869edc9f8b..385d789868 100644 --- a/tests/unit/test_api.cpp +++ b/tests/unit/test_api.cpp @@ -115,6 +115,14 @@ handler (const jerry_api_object_t *function_obj_p, return true; } /* handler */ +static void +handler_construct_freecb (const jerry_api_object_t *object_p, uintptr_t native_p) +{ + (void)object_p; + assert (native_p == (uintptr_t) 0x0012345678abcdefull); + printf("ok object free callback\n"); +} + static bool handler_construct (const jerry_api_object_t *function_obj_p, const jerry_api_value_t *this_p, @@ -135,6 +143,8 @@ handler_construct (const jerry_api_object_t *function_obj_p, jerry_api_set_object_native_handle (this_p->v_object, (uintptr_t) 0x0012345678abcdefull); + jerry_api_set_object_free_callback (this_p->v_object, handler_construct_freecb); + return true; } /* handler_construct */ From 130e627c7c57b7aea0b8af0d30036fe431134a59 Mon Sep 17 00:00:00 2001 From: SaeHie Park Date: Tue, 28 Apr 2015 17:48:12 +0900 Subject: [PATCH 2/3] object free callback fix, issue #2 - remove jerry_api_get_object_free_callback(), currenly no usage - remove object_p parameter with free_callback(), object can mislead users to call APIs which is dangerous this time. JerryScript-DCO-1.0-Signed-off-by: SaeHie Park saehie.park@samsung.com --- jerry-core/ecma/base/ecma-gc.cpp | 2 +- jerry-core/jerry-api.h | 7 +------ jerry-core/jerry-internal.h | 3 +-- jerry-core/jerry.cpp | 29 ++--------------------------- tests/unit/test_api.cpp | 3 +-- 5 files changed, 6 insertions(+), 38 deletions(-) diff --git a/jerry-core/ecma/base/ecma-gc.cpp b/jerry-core/ecma/base/ecma-gc.cpp index f9d992000e..192cc8acc5 100644 --- a/jerry-core/ecma/base/ecma-gc.cpp +++ b/jerry-core/ecma/base/ecma-gc.cpp @@ -381,7 +381,7 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */ &native_p); if (is_retrieved && native_p) - jerry_dispatch_object_free_callback (object_p, freecb_p, native_p); + jerry_dispatch_object_free_callback (freecb_p, native_p); } for (ecma_property_t *property = ecma_get_property_list (object_p), *next_property_p; diff --git a/jerry-core/jerry-api.h b/jerry-core/jerry-api.h index 264acd3d52..f9f035423f 100644 --- a/jerry-core/jerry-api.h +++ b/jerry-core/jerry-api.h @@ -100,8 +100,7 @@ typedef bool (*jerry_external_handler_t) (const jerry_api_object_t *function_obj const jerry_api_value_t args_p [], const uint16_t args_count); -typedef void (*jerry_object_free_callback_t) (const jerry_api_object_t *object_p, - const uintptr_t native_p); +typedef void (*jerry_object_free_callback_t) (const uintptr_t native_p); extern EXTERN_C ssize_t @@ -156,10 +155,6 @@ bool jerry_api_get_object_native_handle (jerry_api_object_t *object_p, uintptr_t extern EXTERN_C void jerry_api_set_object_native_handle (jerry_api_object_t *object_p, uintptr_t handle); -extern EXTERN_C -bool jerry_api_get_object_free_callback (jerry_api_object_t *object_p, - jerry_object_free_callback_t* out_freecb_p); - extern EXTERN_C void jerry_api_set_object_free_callback (jerry_api_object_t *object_p, jerry_object_free_callback_t freecb_p); diff --git a/jerry-core/jerry-internal.h b/jerry-core/jerry-internal.h index 008e55dd37..926d87a6a2 100644 --- a/jerry-core/jerry-internal.h +++ b/jerry-core/jerry-internal.h @@ -31,8 +31,7 @@ jerry_dispatch_external_function (ecma_object_t *function_object_p, ecma_length_t args_count); extern void -jerry_dispatch_object_free_callback (ecma_object_t *object_p, - ecma_external_pointer_t freecb_p, +jerry_dispatch_object_free_callback (ecma_external_pointer_t freecb_p, ecma_external_pointer_t native_p); diff --git a/jerry-core/jerry.cpp b/jerry-core/jerry.cpp index fe729b860c..d42edb27f7 100644 --- a/jerry-core/jerry.cpp +++ b/jerry-core/jerry.cpp @@ -431,12 +431,11 @@ jerry_dispatch_external_function (ecma_object_t *function_object_p, /**< externa * it's critical GC phase so should not re-enter jerry apis */ void -jerry_dispatch_object_free_callback (ecma_object_t *object_p, /**< object that is garbage colleted*/ - ecma_external_pointer_t freecb_p, /**< pointer to free callback handler */ +jerry_dispatch_object_free_callback (ecma_external_pointer_t freecb_p, /**< pointer to free callback handler */ ecma_external_pointer_t native_p) /**< pointer to the function's native handler */ { /* Todo: prevent call inside jerry again */ - ((jerry_object_free_callback_t) freecb_p) (object_p, (uintptr_t)native_p); + ((jerry_object_free_callback_t) freecb_p) ((uintptr_t)native_p); } /** @@ -667,30 +666,6 @@ jerry_api_set_object_native_handle (jerry_api_object_t *object_p, /**< object to handle); } /* jerry_api_set_object_native_handle */ -/** - * Get object free callbaack handle, associated with specified object - * - * @return true - if there is associated handle (handle is returned through out_handle_p), - * false - otherwise. - */ -bool -jerry_api_get_object_free_callback (jerry_api_object_t *object_p, /**< object to get handle from */ - jerry_object_free_callback_t* out_freecb_p) /**< out: handle value */ -{ - uintptr_t handle_value; - - bool does_exist = ecma_get_external_pointer_value (object_p, - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK, - &handle_value); - - if (does_exist) - { - *out_freecb_p = (jerry_object_free_callback_t)handle_value; - } - - return does_exist; -} /* jerry_api_get_object_native_handle */ - /** * Set object free callback native handle for the specified object */ diff --git a/tests/unit/test_api.cpp b/tests/unit/test_api.cpp index 385d789868..8c70536516 100644 --- a/tests/unit/test_api.cpp +++ b/tests/unit/test_api.cpp @@ -116,9 +116,8 @@ handler (const jerry_api_object_t *function_obj_p, } /* handler */ static void -handler_construct_freecb (const jerry_api_object_t *object_p, uintptr_t native_p) +handler_construct_freecb (uintptr_t native_p) { - (void)object_p; assert (native_p == (uintptr_t) 0x0012345678abcdefull); printf("ok object free callback\n"); } From dc370f1f0f0da3834946c65707d2a5946bc673a7 Mon Sep 17 00:00:00 2001 From: SaeHie Park Date: Tue, 28 Apr 2015 19:10:03 +0900 Subject: [PATCH 3/3] fix call object free callback when object is not lexical_environment JerryScript-DCO-1.0-Signed-off-by: SaeHie Park saehie.park@samsung.com --- jerry-core/ecma/base/ecma-gc.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/jerry-core/ecma/base/ecma-gc.cpp b/jerry-core/ecma/base/ecma-gc.cpp index 192cc8acc5..8889cc8b0c 100644 --- a/jerry-core/ecma/base/ecma-gc.cpp +++ b/jerry-core/ecma/base/ecma-gc.cpp @@ -366,6 +366,7 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */ ecma_get_lex_env_type (object_p) != ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND) { /* call object free callback with given handle */ + if (!ecma_is_lexical_environment (object_p)) { ecma_external_pointer_t freecb_p; ecma_external_pointer_t native_p;