Allow API usage in native_free_callbacks (#3515)
This patch allows the use of API functions in native_free_callbacks for native pointers once again. JerryScript-DCO-1.0-Signed-off-by: Daniel Balla dballa@inf.u-szeged.hu
This commit is contained in:
committed by
Dániel Bátyai
parent
71d4e12105
commit
f46d061d19
@@ -447,7 +447,7 @@ typedef jerry_value_t (*jerry_external_handler_t) (const jerry_value_t function_
|
|||||||
Native free callback of an object. It is used in `jerry_object_native_info_t` and for external Array buffers.
|
Native free callback of an object. It is used in `jerry_object_native_info_t` and for external Array buffers.
|
||||||
|
|
||||||
*Note*:
|
*Note*:
|
||||||
- This callback method **must not** call any JerryScript API methods.
|
- Referred values by this method must have at least 1 reference. (Correct API usage satisfies this condition)
|
||||||
|
|
||||||
**Prototype**
|
**Prototype**
|
||||||
|
|
||||||
@@ -456,6 +456,7 @@ typedef void (*jerry_object_native_free_callback_t) (void *native_p);
|
|||||||
```
|
```
|
||||||
|
|
||||||
*New in version 2.0*: Renamed from `jerry_object_free_callback_t`.
|
*New in version 2.0*: Renamed from `jerry_object_free_callback_t`.
|
||||||
|
*Changed in version 2.2*: API calls are once again allowed. (See note)
|
||||||
|
|
||||||
**See also**
|
**See also**
|
||||||
|
|
||||||
@@ -6145,7 +6146,7 @@ You can get them by calling [jerry_get_object_native_pointer](#jerry_get_object_
|
|||||||
it will be called by the garbage collector when the object is freed.
|
it will be called by the garbage collector when the object is freed.
|
||||||
- If the object is only referenced via the "global" object (or one of it's "child"),
|
- If the object is only referenced via the "global" object (or one of it's "child"),
|
||||||
the free callback will be invoked during the execution of `jerry_cleanup`.
|
the free callback will be invoked during the execution of `jerry_cleanup`.
|
||||||
- The free callback **must not** invoke API functions.
|
- The free callback can invoke API functions.
|
||||||
|
|
||||||
*Note*: If possible do not store API values in native pointers, rather check
|
*Note*: If possible do not store API values in native pointers, rather check
|
||||||
[jerry_set_internal_property](#jerry_set_internal_property).
|
[jerry_set_internal_property](#jerry_set_internal_property).
|
||||||
|
|||||||
@@ -2956,7 +2956,7 @@ jerry_get_object_native_pointer (const jerry_value_t obj_val, /**< object to get
|
|||||||
* Note:
|
* Note:
|
||||||
* If a non-NULL free callback is specified in the native type info,
|
* 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.
|
* it will be called by the garbage collector when the object is freed.
|
||||||
* This callback **must not** invoke API functions.
|
* Referred values by this method must have at least 1 reference. (Correct API usage satisfies this condition)
|
||||||
* The type info always overwrites the previous value, so passing
|
* The type info always overwrites the previous value, so passing
|
||||||
* a NULL value deletes the current type info.
|
* a NULL value deletes the current type info.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -700,10 +700,6 @@ ecma_gc_free_native_pointer (ecma_property_t *property_p) /**< property */
|
|||||||
native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t,
|
native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t,
|
||||||
value_p->value);
|
value_p->value);
|
||||||
|
|
||||||
#ifndef JERRY_NDEBUG
|
|
||||||
JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_API_AVAILABLE;
|
|
||||||
#endif /* !JERRY_NDEBUG */
|
|
||||||
|
|
||||||
while (native_pointer_p != NULL)
|
while (native_pointer_p != NULL)
|
||||||
{
|
{
|
||||||
if (native_pointer_p->info_p != NULL)
|
if (native_pointer_p->info_p != NULL)
|
||||||
@@ -722,10 +718,6 @@ ecma_gc_free_native_pointer (ecma_property_t *property_p) /**< property */
|
|||||||
|
|
||||||
native_pointer_p = next_p;
|
native_pointer_p = next_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef JERRY_NDEBUG
|
|
||||||
JERRY_CONTEXT (status_flags) |= ECMA_STATUS_API_AVAILABLE;
|
|
||||||
#endif /* !JERRY_NDEBUG */
|
|
||||||
} /* ecma_gc_free_native_pointer */
|
} /* ecma_gc_free_native_pointer */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1405,6 +1397,7 @@ ecma_gc_run (void)
|
|||||||
while (marked_anything_during_current_iteration);
|
while (marked_anything_during_current_iteration);
|
||||||
|
|
||||||
black_end_p->gc_next_cp = JMEM_CP_NULL;
|
black_end_p->gc_next_cp = JMEM_CP_NULL;
|
||||||
|
JERRY_CONTEXT (ecma_gc_objects_cp) = black_list_head.gc_next_cp;
|
||||||
|
|
||||||
/* Sweep objects that are currently unmarked. */
|
/* Sweep objects that are currently unmarked. */
|
||||||
obj_iter_cp = white_gray_list_head.gc_next_cp;
|
obj_iter_cp = white_gray_list_head.gc_next_cp;
|
||||||
@@ -1420,8 +1413,6 @@ ecma_gc_run (void)
|
|||||||
obj_iter_cp = obj_next_cp;
|
obj_iter_cp = obj_next_cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
JERRY_CONTEXT (ecma_gc_objects_cp) = black_list_head.gc_next_cp;
|
|
||||||
|
|
||||||
#if ENABLED (JERRY_BUILTIN_REGEXP)
|
#if ENABLED (JERRY_BUILTIN_REGEXP)
|
||||||
/* Free RegExp bytecodes stored in cache */
|
/* Free RegExp bytecodes stored in cache */
|
||||||
re_cache_gc_run ();
|
re_cache_gc_run ();
|
||||||
|
|||||||
@@ -29,6 +29,11 @@
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of GC loops on cleanup.
|
||||||
|
*/
|
||||||
|
#define JERRY_GC_LOOP_LIMIT 100
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize ECMA components
|
* Initialize ECMA components
|
||||||
*/
|
*/
|
||||||
@@ -73,8 +78,17 @@ ecma_finalize (void)
|
|||||||
#endif /* ENABLED (JERRY_ES2015) */
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
|
|
||||||
ecma_finalize_global_lex_env ();
|
ecma_finalize_global_lex_env ();
|
||||||
|
uint8_t runs = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
ecma_finalize_builtins ();
|
ecma_finalize_builtins ();
|
||||||
ecma_gc_run ();
|
ecma_gc_run ();
|
||||||
|
if (++runs >= JERRY_GC_LOOP_LIMIT)
|
||||||
|
{
|
||||||
|
jerry_fatal (ERR_UNTERMINATED_GC_LOOPS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (JERRY_CONTEXT (ecma_gc_new_objects) != 0);
|
||||||
ecma_finalize_lit_storage ();
|
ecma_finalize_lit_storage ();
|
||||||
} /* ecma_finalize */
|
} /* ecma_finalize */
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ typedef enum
|
|||||||
ERR_OUT_OF_MEMORY = 10,
|
ERR_OUT_OF_MEMORY = 10,
|
||||||
ERR_REF_COUNT_LIMIT = 12,
|
ERR_REF_COUNT_LIMIT = 12,
|
||||||
ERR_DISABLED_BYTE_CODE = 13,
|
ERR_DISABLED_BYTE_CODE = 13,
|
||||||
|
ERR_UNTERMINATED_GC_LOOPS = 14,
|
||||||
ERR_FAILED_INTERNAL_ASSERTION = 120
|
ERR_FAILED_INTERNAL_ASSERTION = 120
|
||||||
} jerry_fatal_code_t;
|
} jerry_fatal_code_t;
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,11 @@ jerry_fatal (jerry_fatal_code_t code) /**< status code */
|
|||||||
JERRY_ERROR_MSG ("Error: ERR_REF_COUNT_LIMIT\n");
|
JERRY_ERROR_MSG ("Error: ERR_REF_COUNT_LIMIT\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ERR_UNTERMINATED_GC_LOOPS:
|
||||||
|
{
|
||||||
|
JERRY_ERROR_MSG ("Error: ERR_UNTERMINATED_GC_LOOPS\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ERR_DISABLED_BYTE_CODE:
|
case ERR_DISABLED_BYTE_CODE:
|
||||||
{
|
{
|
||||||
JERRY_ERROR_MSG ("Error: ERR_DISABLED_BYTE_CODE\n");
|
JERRY_ERROR_MSG ("Error: ERR_DISABLED_BYTE_CODE\n");
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "jerryscript.h"
|
||||||
|
#include "jerryscript-port.h"
|
||||||
|
#include "jerryscript-port-default.h"
|
||||||
|
#include "test-common.h"
|
||||||
|
|
||||||
|
static void native_cb2 (void)
|
||||||
|
{
|
||||||
|
jerry_value_t array = jerry_create_array (100);
|
||||||
|
jerry_release_value (array);
|
||||||
|
} /* native_cb2 */
|
||||||
|
|
||||||
|
static const jerry_object_native_info_t native_info2 =
|
||||||
|
{
|
||||||
|
.free_cb = (jerry_object_native_free_callback_t) native_cb2
|
||||||
|
};
|
||||||
|
|
||||||
|
static void native_cb (void)
|
||||||
|
{
|
||||||
|
jerry_value_t array = jerry_create_array (100);
|
||||||
|
|
||||||
|
jerry_set_object_native_pointer (array, NULL, &native_info2);
|
||||||
|
|
||||||
|
jerry_release_value (array);
|
||||||
|
} /* native_cb */
|
||||||
|
|
||||||
|
static const jerry_object_native_info_t native_info =
|
||||||
|
{
|
||||||
|
.free_cb = (jerry_object_native_free_callback_t) native_cb
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *
|
||||||
|
context_alloc_fn (size_t size, void *cb_data)
|
||||||
|
{
|
||||||
|
(void) cb_data;
|
||||||
|
return malloc (size);
|
||||||
|
} /* context_alloc_fn */
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
jerry_context_t *ctx_p = jerry_create_context (1024, context_alloc_fn, NULL);
|
||||||
|
jerry_port_default_set_current_context (ctx_p);
|
||||||
|
jerry_init (JERRY_INIT_EMPTY);
|
||||||
|
|
||||||
|
jerry_value_t obj = jerry_create_object ();
|
||||||
|
|
||||||
|
jerry_set_object_native_pointer (obj, NULL, &native_info);
|
||||||
|
jerry_release_value (obj);
|
||||||
|
|
||||||
|
jerry_cleanup ();
|
||||||
|
free (ctx_p);
|
||||||
|
return 0;
|
||||||
|
} /* main */
|
||||||
Reference in New Issue
Block a user