Skip to content

Commit f46d061

Browse files
Daniel Balladbatyai
authored andcommitted
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
1 parent 71d4e12 commit f46d061

7 files changed

Lines changed: 96 additions & 15 deletions

File tree

docs/02.API-REFERENCE.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ typedef jerry_value_t (*jerry_external_handler_t) (const jerry_value_t function_
447447
Native free callback of an object. It is used in `jerry_object_native_info_t` and for external Array buffers.
448448

449449
*Note*:
450-
- This callback method **must not** call any JerryScript API methods.
450+
- Referred values by this method must have at least 1 reference. (Correct API usage satisfies this condition)
451451

452452
**Prototype**
453453

@@ -456,6 +456,7 @@ typedef void (*jerry_object_native_free_callback_t) (void *native_p);
456456
```
457457

458458
*New in version 2.0*: Renamed from `jerry_object_free_callback_t`.
459+
*Changed in version 2.2*: API calls are once again allowed. (See note)
459460

460461
**See also**
461462

@@ -6145,7 +6146,7 @@ You can get them by calling [jerry_get_object_native_pointer](#jerry_get_object_
61456146
it will be called by the garbage collector when the object is freed.
61466147
- If the object is only referenced via the "global" object (or one of it's "child"),
61476148
the free callback will be invoked during the execution of `jerry_cleanup`.
6148-
- The free callback **must not** invoke API functions.
6149+
- The free callback can invoke API functions.
61496150

61506151
*Note*: If possible do not store API values in native pointers, rather check
61516152
[jerry_set_internal_property](#jerry_set_internal_property).

jerry-core/api/jerry.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2956,7 +2956,7 @@ jerry_get_object_native_pointer (const jerry_value_t obj_val, /**< object to get
29562956
* Note:
29572957
* If a non-NULL free callback is specified in the native type info,
29582958
* it will be called by the garbage collector when the object is freed.
2959-
* This callback **must not** invoke API functions.
2959+
* Referred values by this method must have at least 1 reference. (Correct API usage satisfies this condition)
29602960
* The type info always overwrites the previous value, so passing
29612961
* a NULL value deletes the current type info.
29622962
*/

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

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -700,10 +700,6 @@ ecma_gc_free_native_pointer (ecma_property_t *property_p) /**< property */
700700
native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t,
701701
value_p->value);
702702

703-
#ifndef JERRY_NDEBUG
704-
JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_API_AVAILABLE;
705-
#endif /* !JERRY_NDEBUG */
706-
707703
while (native_pointer_p != NULL)
708704
{
709705
if (native_pointer_p->info_p != NULL)
@@ -722,10 +718,6 @@ ecma_gc_free_native_pointer (ecma_property_t *property_p) /**< property */
722718

723719
native_pointer_p = next_p;
724720
}
725-
726-
#ifndef JERRY_NDEBUG
727-
JERRY_CONTEXT (status_flags) |= ECMA_STATUS_API_AVAILABLE;
728-
#endif /* !JERRY_NDEBUG */
729721
} /* ecma_gc_free_native_pointer */
730722

731723
/**
@@ -1405,6 +1397,7 @@ ecma_gc_run (void)
14051397
while (marked_anything_during_current_iteration);
14061398

14071399
black_end_p->gc_next_cp = JMEM_CP_NULL;
1400+
JERRY_CONTEXT (ecma_gc_objects_cp) = black_list_head.gc_next_cp;
14081401

14091402
/* Sweep objects that are currently unmarked. */
14101403
obj_iter_cp = white_gray_list_head.gc_next_cp;
@@ -1420,8 +1413,6 @@ ecma_gc_run (void)
14201413
obj_iter_cp = obj_next_cp;
14211414
}
14221415

1423-
JERRY_CONTEXT (ecma_gc_objects_cp) = black_list_head.gc_next_cp;
1424-
14251416
#if ENABLED (JERRY_BUILTIN_REGEXP)
14261417
/* Free RegExp bytecodes stored in cache */
14271418
re_cache_gc_run ();

jerry-core/ecma/base/ecma-init-finalize.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
* @{
3030
*/
3131

32+
/**
33+
* Maximum number of GC loops on cleanup.
34+
*/
35+
#define JERRY_GC_LOOP_LIMIT 100
36+
3237
/**
3338
* Initialize ECMA components
3439
*/
@@ -73,8 +78,17 @@ ecma_finalize (void)
7378
#endif /* ENABLED (JERRY_ES2015) */
7479

7580
ecma_finalize_global_lex_env ();
76-
ecma_finalize_builtins ();
77-
ecma_gc_run ();
81+
uint8_t runs = 0;
82+
do
83+
{
84+
ecma_finalize_builtins ();
85+
ecma_gc_run ();
86+
if (++runs >= JERRY_GC_LOOP_LIMIT)
87+
{
88+
jerry_fatal (ERR_UNTERMINATED_GC_LOOPS);
89+
}
90+
}
91+
while (JERRY_CONTEXT (ecma_gc_new_objects) != 0);
7892
ecma_finalize_lit_storage ();
7993
} /* ecma_finalize */
8094

jerry-core/include/jerryscript-port.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ typedef enum
5151
ERR_OUT_OF_MEMORY = 10,
5252
ERR_REF_COUNT_LIMIT = 12,
5353
ERR_DISABLED_BYTE_CODE = 13,
54+
ERR_UNTERMINATED_GC_LOOPS = 14,
5455
ERR_FAILED_INTERNAL_ASSERTION = 120
5556
} jerry_fatal_code_t;
5657

jerry-core/jrt/jrt-fatals.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ jerry_fatal (jerry_fatal_code_t code) /**< status code */
4242
JERRY_ERROR_MSG ("Error: ERR_REF_COUNT_LIMIT\n");
4343
break;
4444
}
45+
case ERR_UNTERMINATED_GC_LOOPS:
46+
{
47+
JERRY_ERROR_MSG ("Error: ERR_UNTERMINATED_GC_LOOPS\n");
48+
break;
49+
}
4550
case ERR_DISABLED_BYTE_CODE:
4651
{
4752
JERRY_ERROR_MSG ("Error: ERR_DISABLED_BYTE_CODE\n");
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/* Copyright JS Foundation and other contributors, http://js.foundation
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
17+
#include "jerryscript.h"
18+
#include "jerryscript-port.h"
19+
#include "jerryscript-port-default.h"
20+
#include "test-common.h"
21+
22+
static void native_cb2 (void)
23+
{
24+
jerry_value_t array = jerry_create_array (100);
25+
jerry_release_value (array);
26+
} /* native_cb2 */
27+
28+
static const jerry_object_native_info_t native_info2 =
29+
{
30+
.free_cb = (jerry_object_native_free_callback_t) native_cb2
31+
};
32+
33+
static void native_cb (void)
34+
{
35+
jerry_value_t array = jerry_create_array (100);
36+
37+
jerry_set_object_native_pointer (array, NULL, &native_info2);
38+
39+
jerry_release_value (array);
40+
} /* native_cb */
41+
42+
static const jerry_object_native_info_t native_info =
43+
{
44+
.free_cb = (jerry_object_native_free_callback_t) native_cb
45+
};
46+
47+
static void *
48+
context_alloc_fn (size_t size, void *cb_data)
49+
{
50+
(void) cb_data;
51+
return malloc (size);
52+
} /* context_alloc_fn */
53+
54+
int
55+
main (void)
56+
{
57+
jerry_context_t *ctx_p = jerry_create_context (1024, context_alloc_fn, NULL);
58+
jerry_port_default_set_current_context (ctx_p);
59+
jerry_init (JERRY_INIT_EMPTY);
60+
61+
jerry_value_t obj = jerry_create_object ();
62+
63+
jerry_set_object_native_pointer (obj, NULL, &native_info);
64+
jerry_release_value (obj);
65+
66+
jerry_cleanup ();
67+
free (ctx_p);
68+
return 0;
69+
} /* main */

0 commit comments

Comments
 (0)