Skip to content

Object free callback #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions jerry-core/ecma/base/ecma-gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -360,6 +365,26 @@ 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 */
if (!ecma_is_lexical_environment (object_p))
{
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 (freecb_p, native_p);
}

for (ecma_property_t *property = ecma_get_property_list (object_p), *next_property_p;
property != NULL;
property = next_property_p)
Expand Down
1 change: 1 addition & 0 deletions jerry-core/ecma/base/ecma-globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
18 changes: 12 additions & 6 deletions jerry-core/ecma/base/ecma-helpers-external-pointers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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);
Expand Down Expand Up @@ -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).
Expand All @@ -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);

Expand Down Expand Up @@ -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))
{
Expand Down
1 change: 1 addition & 0 deletions jerry-core/ecma/base/ecma-helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
7 changes: 7 additions & 0 deletions jerry-core/jerry-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ 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 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,
Expand Down Expand Up @@ -152,6 +155,10 @@ 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
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,
Expand Down
5 changes: 5 additions & 0 deletions jerry-core/jerry-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,9 @@ 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_external_pointer_t freecb_p,
ecma_external_pointer_t native_p);


#endif /* !JERRY_INTERNAL_H */
26 changes: 26 additions & 0 deletions jerry-core/jerry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,20 @@ 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_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) ((uintptr_t)native_p);
}

/**
* Check if the specified object is a function object.
*
Expand Down Expand Up @@ -652,6 +666,18 @@ jerry_api_set_object_native_handle (jerry_api_object_t *object_p, /**< object to
handle);
} /* jerry_api_set_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
*
Expand Down
9 changes: 9 additions & 0 deletions tests/unit/test_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ handler (const jerry_api_object_t *function_obj_p,
return true;
} /* handler */

static void
handler_construct_freecb (uintptr_t native_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,
Expand All @@ -135,6 +142,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 */

Expand Down