Skip to content

Commit 5ec3e2f

Browse files
committed
Native callback in embedding jerry when object is to be freed.
JerryScript-DCO-1.0-Signed-off-by: SaeHie Park [email protected]
1 parent 17036c8 commit 5ec3e2f

File tree

8 files changed

+111
-7
lines changed

8 files changed

+111
-7
lines changed

jerry-core/ecma/base/ecma-gc.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
#include "jrt-libc-includes.h"
3535
#include "jrt-bit-fields.h"
3636

37+
#define JERRY_INTERNAL
38+
#include "jerry-internal.h"
39+
3740
/**
3841
* An object's GC color
3942
*
@@ -320,6 +323,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
320323
case ECMA_INTERNAL_PROPERTY_CODE: /* an integer */
321324
case ECMA_INTERNAL_PROPERTY_NATIVE_CODE: /* an external pointer */
322325
case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */
326+
case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an object's native free callback */
323327
case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */
324328
case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID: /* an integer */
325329
case ECMA_INTERNAL_PROPERTY_EXTENSION_ID: /* an integer */
@@ -357,6 +361,27 @@ ecma_gc_sweep (ecma_object_t *object_p) /**< object to free */
357361
&& !ecma_gc_is_object_visited (object_p)
358362
&& ecma_gc_get_object_refs (object_p) == 0);
359363

364+
if (!ecma_is_lexical_environment (object_p))
365+
{
366+
/* if the object provides free callback, invoke it with handle stored in the object */
367+
368+
ecma_external_pointer_t freecb_p;
369+
ecma_external_pointer_t native_p;
370+
371+
bool is_retrieved = ecma_get_external_pointer_value (object_p,
372+
ECMA_INTERNAL_PROPERTY_FREE_CALLBACK,
373+
&freecb_p);
374+
if (is_retrieved)
375+
{
376+
is_retrieved = ecma_get_external_pointer_value (object_p,
377+
ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE,
378+
&native_p);
379+
JERRY_ASSERT (is_retrieved);
380+
381+
jerry_dispatch_object_free_callback (freecb_p, native_p);
382+
}
383+
}
384+
360385
if (!ecma_is_lexical_environment (object_p) ||
361386
ecma_get_lex_env_type (object_p) != ECMA_LEXICAL_ENVIRONMENT_OBJECTBOUND)
362387
{

jerry-core/ecma/base/ecma-globals.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ typedef enum
206206
ECMA_INTERNAL_PROPERTY_CODE, /**< [[Code]] */
207207
ECMA_INTERNAL_PROPERTY_NATIVE_CODE, /**< native handler location descriptor */
208208
ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE, /**< native handle associated with an object */
209+
ECMA_INTERNAL_PROPERTY_FREE_CALLBACK, /**< object's native free callback */
209210
ECMA_INTERNAL_PROPERTY_FORMAL_PARAMETERS, /**< [[FormalParameters]] */
210211
ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE, /**< [[Primitive value]] for String objects */
211212
ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE, /**< [[Primitive value]] for Number objects */

jerry-core/ecma/base/ecma-helpers-external-pointers.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
* Note:
3131
* property identifier should be one of the following:
3232
* - ECMA_INTERNAL_PROPERTY_NATIVE_CODE;
33-
* - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE.
33+
* - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE;
34+
* - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK.
3435
*
3536
* @return true - if property was just created with specified value,
3637
* 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
4243
ecma_external_pointer_t ptr_value) /**< value to store in the property */
4344
{
4445
JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_CODE
45-
|| id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE);
46+
|| id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE
47+
|| id == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK);
4648

4749
bool ret_val;
4850
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
8183
* Note:
8284
* property identifier should be one of the following:
8385
* - ECMA_INTERNAL_PROPERTY_NATIVE_CODE;
84-
* - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE.
86+
* - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE;
87+
* - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK.
8588
*
8689
* @return true - if property exists and it's value is returned through out_pointer_p,
8790
* 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
9396
ecma_external_pointer_t *out_pointer_p) /**< out: value of the external pointer */
9497
{
9598
JERRY_ASSERT (id == ECMA_INTERNAL_PROPERTY_NATIVE_CODE
96-
|| id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE);
99+
|| id == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE
100+
|| id == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK);
97101

98102
ecma_property_t* prop_p = ecma_find_internal_property (obj_p, id);
99103

@@ -126,13 +130,15 @@ ecma_get_external_pointer_value (ecma_object_t *obj_p, /**< object to get proper
126130
* Note:
127131
* property identifier should be one of the following:
128132
* - ECMA_INTERNAL_PROPERTY_NATIVE_CODE;
129-
* - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE.
133+
* - ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE;
134+
* - ECMA_INTERNAL_PROPERTY_FREE_CALLBACK.
130135
*/
131136
void
132137
ecma_free_external_pointer_in_property (ecma_property_t *prop_p) /**< internal property */
133138
{
134139
JERRY_ASSERT (prop_p->u.internal_property.type == ECMA_INTERNAL_PROPERTY_NATIVE_CODE
135-
|| prop_p->u.internal_property.type == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE);
140+
|| prop_p->u.internal_property.type == ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE
141+
|| prop_p->u.internal_property.type == ECMA_INTERNAL_PROPERTY_FREE_CALLBACK);
136142

137143
if (sizeof (ecma_external_pointer_t) == sizeof (uint32_t))
138144
{

jerry-core/ecma/base/ecma-helpers.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,7 @@ ecma_free_internal_property (ecma_property_t *property_p) /**< the property */
780780

781781
case ECMA_INTERNAL_PROPERTY_NATIVE_CODE: /* an external pointer */
782782
case ECMA_INTERNAL_PROPERTY_NATIVE_HANDLE: /* an external pointer */
783+
case ECMA_INTERNAL_PROPERTY_FREE_CALLBACK: /* an external pointer */
783784
{
784785
ecma_free_external_pointer_in_property (property_p);
785786

jerry-core/jerry-api.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ typedef bool (*jerry_external_handler_t) (const jerry_api_object_t *function_obj
100100
const jerry_api_value_t args_p [],
101101
const uint16_t args_count);
102102

103+
/**
104+
* An object's native free callback
105+
*/
106+
typedef void (*jerry_object_free_callback_t) (const uintptr_t native_p);
107+
103108
extern EXTERN_C ssize_t
104109
jerry_api_string_to_char_buffer (const jerry_api_string_t *string_p,
105110
char *buffer_p,
@@ -152,6 +157,10 @@ bool jerry_api_get_object_native_handle (jerry_api_object_t *object_p, uintptr_t
152157
extern EXTERN_C
153158
void jerry_api_set_object_native_handle (jerry_api_object_t *object_p, uintptr_t handle);
154159

160+
extern EXTERN_C
161+
bool jerry_api_set_object_free_callback (jerry_api_object_t *object_p,
162+
jerry_object_free_callback_t freecb_p);
163+
155164
extern EXTERN_C
156165
bool jerry_api_call_function (jerry_api_object_t *function_object_p,
157166
jerry_api_object_t *this_arg_p,

jerry-core/jerry-internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,8 @@ jerry_dispatch_external_function (ecma_object_t *function_object_p,
3030
const ecma_value_t args_p [],
3131
ecma_length_t args_count);
3232

33+
extern void
34+
jerry_dispatch_object_free_callback (ecma_external_pointer_t freecb_p,
35+
ecma_external_pointer_t native_p);
36+
3337
#endif /* !JERRY_INTERNAL_H */

jerry-core/jerry.cpp

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,25 @@ jerry_dispatch_external_function (ecma_object_t *function_object_p, /**< externa
499499
return completion_value;
500500
} /* jerry_dispatch_external_function */
501501

502+
/**
503+
* Dispatch call to object's native free callback function
504+
*
505+
* Note:
506+
* the callback is called during critical GC phase,
507+
* so, should not perform any requests to engine
508+
*/
509+
void
510+
jerry_dispatch_object_free_callback (ecma_external_pointer_t freecb_p, /**< pointer to free callback handler */
511+
ecma_external_pointer_t native_p) /**< native handle, associated
512+
* with freed object */
513+
{
514+
jerry_make_api_unavailable ();
515+
516+
((jerry_object_free_callback_t) freecb_p) ((uintptr_t) native_p);
517+
518+
jerry_make_api_available ();
519+
} /* jerry_dispatch_object_free_callback */
520+
502521
/**
503522
* Check if the specified object is a function object.
504523
*
@@ -743,6 +762,32 @@ jerry_api_set_object_native_handle (jerry_api_object_t *object_p, /**< object to
743762
handle);
744763
} /* jerry_api_set_object_native_handle */
745764

765+
/**
766+
* Set object free callback for the specified object
767+
*
768+
* @return true - if callback was set successfully,
769+
* false - otherwise (there is no native handle, associated with the object).
770+
*/
771+
bool
772+
jerry_api_set_object_free_callback (jerry_api_object_t *object_p, /**< object to set callback for */
773+
jerry_object_free_callback_t freecb_p) /**< object free callback */
774+
{
775+
uintptr_t handle_value;
776+
bool is_native_handle_associated = jerry_api_get_object_native_handle (object_p,
777+
&handle_value);
778+
779+
if (!is_native_handle_associated)
780+
{
781+
return false;
782+
}
783+
784+
ecma_create_external_pointer_property (object_p,
785+
ECMA_INTERNAL_PROPERTY_FREE_CALLBACK,
786+
(uintptr_t) freecb_p);
787+
788+
return true;
789+
} /* jerry_api_set_object_free_callback */
790+
746791
/**
747792
* Invoke function specified by a function object
748793
*
@@ -1019,7 +1064,6 @@ jerry_init (jerry_flag_t flags) /**< combination of Jerry flags */
10191064

10201065
jerry_flags = flags;
10211066

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

10251069
mem_init ();

tests/unit/test_api.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ const char *test_source = (
4040
"}"
4141
);
4242

43+
bool test_api_is_free_callback_was_called = false;
44+
4345
/**
4446
* Initialize Jerry API value with specified boolean value
4547
*/
@@ -115,6 +117,15 @@ handler (const jerry_api_object_t *function_obj_p,
115117
return true;
116118
} /* handler */
117119

120+
static void
121+
handler_construct_freecb (uintptr_t native_p)
122+
{
123+
assert (native_p == (uintptr_t) 0x0012345678abcdefull);
124+
printf ("ok object free callback\n");
125+
126+
test_api_is_free_callback_was_called = true;
127+
} /* handler_construct_freecb */
128+
118129
static bool
119130
handler_construct (const jerry_api_object_t *function_obj_p,
120131
const jerry_api_value_t *this_p,
@@ -135,6 +146,9 @@ handler_construct (const jerry_api_object_t *function_obj_p,
135146

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

149+
bool is_set = jerry_api_set_object_free_callback (this_p->v_object, handler_construct_freecb);
150+
assert (is_set);
151+
138152
return true;
139153
} /* handler_construct */
140154

0 commit comments

Comments
 (0)