Skip to content

Native callback in embedding jerry when object is to be freed. #14

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

Merged
merged 1 commit into from
May 5, 2015
Merged
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,9 @@
#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 +323,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's native 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 @@ -357,6 +361,27 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
&& !ecma_gc_is_object_visited (object_p)
&& ecma_gc_get_object_refs (object_p) == 0);

if (!ecma_is_lexical_environment (object_p))
{
/* 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,
ECMA_INTERNAL_PROPERTY_FREE_CALLBACK,
&freecb_p);
if (is_retrieved)
{
is_retrieved = ecma_get_external_pointer_value (object_p,
ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE,
&native_p);
JERRY_ASSERT (is_retrieved);

jerry_dispatch_object_free_callback (freecb_p, native_p);
}
}

if (!ecma_is_lexical_environment (object_p) ||
ecma_get_lex_env_type (object_p) != ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND)
{
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, /**< object's native free callback */
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
9 changes: 9 additions & 0 deletions jerry-core/jerry-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ 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);

/**
* An object's native free callback
*/
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 +157,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
bool 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
4 changes: 4 additions & 0 deletions jerry-core/jerry-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,8 @@ 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 */
46 changes: 45 additions & 1 deletion jerry-core/jerry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,25 @@ jerry_dispatch_external_function (ecma_object_t *function_object_p, /**< externa
return completion_value;
} /* jerry_dispatch_external_function */

/**
* Dispatch call to object's native free callback function
*
* Note:
* the callback is called during critical GC phase,
* so, should not perform any requests to engine
*/
void
jerry_dispatch_object_free_callback (ecma_external_pointer_t freecb_p, /**< pointer to free callback handler */
ecma_external_pointer_t native_p) /**< native handle, associated
* with freed object */
{
jerry_make_api_unavailable ();

((jerry_object_free_callback_t) freecb_p) ((uintptr_t) native_p);

jerry_make_api_available ();
} /* jerry_dispatch_object_free_callback */

/**
* Check if the specified object is a function object.
*
Expand Down Expand Up @@ -743,6 +762,32 @@ 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 for the specified object
*
* @return true - if callback was set successfully,
* false - otherwise (there is no native handle, associated with the object).
*/
bool
jerry_api_set_object_free_callback (jerry_api_object_t *object_p, /**< object to set callback for */
jerry_object_free_callback_t freecb_p) /**< object free callback */
{
uintptr_t handle_value;
bool is_native_handle_associated = jerry_api_get_object_native_handle (object_p,
&handle_value);

if (!is_native_handle_associated)
{
return false;
}

ecma_create_external_pointer_property (object_p,
ECMA_INTERNAL_PROPERTY_FREE_CALLBACK,
(uintptr_t) freecb_p);

return true;
} /* jerry_api_set_object_free_callback */

/**
* Invoke function specified by a function object
*
Expand Down Expand Up @@ -1019,7 +1064,6 @@ jerry_init (jerry_flag_t flags) /**< combination of Jerry flags */

jerry_flags = flags;

jerry_make_api_unavailable (); /* TODO remove this line when it's called somewhere else */
jerry_make_api_available ();

mem_init ();
Expand Down
14 changes: 14 additions & 0 deletions tests/unit/test_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ const char *test_source = (
"}"
);

bool test_api_is_free_callback_was_called = false;

/**
* Initialize Jerry API value with specified boolean value
*/
Expand Down Expand Up @@ -115,6 +117,15 @@ 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");

test_api_is_free_callback_was_called = true;
} /* handler_construct_freecb */

static bool
handler_construct (const jerry_api_object_t *function_obj_p,
const jerry_api_value_t *this_p,
Expand All @@ -135,6 +146,9 @@ handler_construct (const jerry_api_object_t *function_obj_p,

jerry_api_set_object_native_handle (this_p->v_object, (uintptr_t) 0x0012345678abcdefull);

bool is_set = jerry_api_set_object_free_callback (this_p->v_object, handler_construct_freecb);
assert (is_set);

return true;
} /* handler_construct */

Expand Down