Skip to content

Commit d69fe41

Browse files
authored
Improve garbage collection of scripts and modules (#4722)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg [email protected]
1 parent d4178ae commit d69fe41

File tree

2 files changed

+97
-31
lines changed

2 files changed

+97
-31
lines changed

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

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,30 @@ ecma_gc_mark_properties (ecma_object_t *object_p, /**< object */
417417
}
418418
} /* ecma_gc_mark_properties */
419419

420+
/**
421+
* Mark compiled code.
422+
*/
423+
static void
424+
ecma_gc_mark_compiled_code (const ecma_compiled_code_t *compiled_code_p) /**< compiled code */
425+
{
426+
JERRY_ASSERT (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION));
427+
428+
ecma_value_t script_value = ((cbc_uint8_arguments_t *) compiled_code_p)->script_value;
429+
cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value);
430+
431+
if (CBC_SCRIPT_GET_TYPE (script_p) == CBC_SCRIPT_USER_OBJECT)
432+
{
433+
cbc_script_user_t *script_user_p = (cbc_script_user_t *) script_p;
434+
435+
JERRY_ASSERT (ecma_is_value_object (script_user_p->user_value));
436+
ecma_gc_set_object_visited (ecma_get_object_from_value (script_user_p->user_value));
437+
}
438+
439+
#if JERRY_BUILTIN_REALMS
440+
ecma_gc_set_object_visited (script_p->realm_p);
441+
#endif /* JERRY_BUILTIN_REALMS */
442+
} /* ecma_gc_mark_compiled_code */
443+
420444
/**
421445
* Mark objects referenced by bound function object.
422446
*/
@@ -871,6 +895,16 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
871895
ecma_gc_mark_arguments_object (ext_object_p);
872896
break;
873897
}
898+
#if JERRY_PARSER
899+
case ECMA_OBJECT_CLASS_SCRIPT:
900+
{
901+
const ecma_compiled_code_t *compiled_code_p;
902+
compiled_code_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t,
903+
ext_object_p->u.cls.u3.value);
904+
ecma_gc_mark_compiled_code (compiled_code_p);
905+
break;
906+
}
907+
#endif /* JERRY_PARSER */
874908
#if JERRY_BUILTIN_TYPEDARRAY
875909
case ECMA_OBJECT_CLASS_TYPEDARRAY:
876910
{
@@ -903,6 +937,12 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
903937
ecma_gc_set_object_visited (((ecma_module_t *) ext_object_p)->namespace_object_p);
904938
}
905939

940+
if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE)
941+
&& module_p->u.compiled_code_p != NULL)
942+
{
943+
ecma_gc_mark_compiled_code (module_p->u.compiled_code_p);
944+
}
945+
906946
ecma_module_node_t *node_p = module_p->imports_p;
907947

908948
while (node_p != NULL)
@@ -1095,20 +1135,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
10951135
}
10961136
#endif /* JERRY_SNAPSHOT_EXEC */
10971137

1098-
ecma_value_t script_value = ((cbc_uint8_arguments_t *) byte_code_p)->script_value;
1099-
cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value);
1100-
1101-
if (CBC_SCRIPT_GET_TYPE (script_p) == CBC_SCRIPT_USER_OBJECT)
1102-
{
1103-
cbc_script_user_t *script_user_p = (cbc_script_user_t *) script_p;
1104-
1105-
JERRY_ASSERT (ecma_is_value_object (script_user_p->user_value));
1106-
ecma_gc_set_object_visited (ecma_get_object_from_value (script_user_p->user_value));
1107-
}
1108-
1109-
#if JERRY_BUILTIN_REALMS
1110-
ecma_gc_set_object_visited (script_p->realm_p);
1111-
#endif /* JERRY_BUILTIN_REALMS */
1138+
ecma_gc_mark_compiled_code (byte_code_p);
11121139
break;
11131140
}
11141141
#if JERRY_ESNEXT || JERRY_BUILTIN_REALMS

tests/unit-core/test-module-dynamic.c

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,15 @@ module_import_callback (const jerry_value_t specifier, /* string value */
7777
{
7878
TEST_ASSERT (user_p == (void *) &mode);
7979

80-
jerry_value_t compare_value = jerry_binary_operation (JERRY_BIN_OP_STRICT_EQUAL,
81-
user_value,
82-
global_user_value);
80+
if (mode != 3)
81+
{
82+
jerry_value_t compare_value = jerry_binary_operation (JERRY_BIN_OP_STRICT_EQUAL,
83+
user_value,
84+
global_user_value);
8385

84-
TEST_ASSERT (jerry_value_is_true (compare_value));
85-
jerry_release_value (compare_value);
86+
TEST_ASSERT (jerry_value_is_true (compare_value));
87+
jerry_release_value (compare_value);
88+
}
8689

8790
switch (mode)
8891
{
@@ -107,9 +110,21 @@ module_import_callback (const jerry_value_t specifier, /* string value */
107110
jerry_release_value (object_value);
108111
return promise_value;
109112
}
113+
case 3:
114+
{
115+
compare_specifier (specifier, 28);
116+
117+
TEST_ASSERT (jerry_value_is_object (user_value));
118+
jerry_value_t property_name = jerry_create_string ((const jerry_char_t *) "MyProp1");
119+
jerry_value_t result = jerry_get_property (user_value, property_name);
120+
TEST_ASSERT (jerry_value_is_number (result) && jerry_get_number_value (result) == 3.5);
121+
jerry_release_value (result);
122+
jerry_release_value (property_name);
123+
return jerry_create_undefined ();
124+
}
110125
}
111126

112-
TEST_ASSERT (mode == 3 || mode == 4);
127+
TEST_ASSERT (mode == 4 || mode == 5);
113128

114129
jerry_parse_options_t parse_options;
115130
parse_options.options = JERRY_PARSE_MODULE;
@@ -121,7 +136,7 @@ module_import_callback (const jerry_value_t specifier, /* string value */
121136
TEST_ASSERT (!jerry_value_is_error (result_value));
122137
jerry_release_value (result_value);
123138

124-
if (mode == 3)
139+
if (mode == 4)
125140
{
126141
result_value = jerry_module_evaluate (parse_result_value);
127142
TEST_ASSERT (!jerry_value_is_error (result_value));
@@ -133,13 +148,20 @@ module_import_callback (const jerry_value_t specifier, /* string value */
133148

134149
static void
135150
run_script (const char *source_p, /* source code */
136-
jerry_parse_options_t *parse_options_p) /* parse options */
151+
jerry_parse_options_t *parse_options_p, /* parse options */
152+
bool release_user_value) /* release user value */
137153
{
138154
jerry_value_t parse_result_value;
139155

140156
parse_result_value = jerry_parse ((const jerry_char_t *) source_p, strlen (source_p), parse_options_p);
141157
TEST_ASSERT (!jerry_value_is_error (parse_result_value));
142158

159+
if (release_user_value)
160+
{
161+
jerry_release_value (parse_options_p->user_value);
162+
jerry_gc (JERRY_GC_PRESSURE_HIGH);
163+
}
164+
143165
jerry_value_t result_value;
144166
if (parse_options_p->options & JERRY_PARSE_MODULE)
145167
{
@@ -184,11 +206,11 @@ main (void)
184206

185207
if (jerry_is_feature_enabled (JERRY_FEATURE_ERROR_MESSAGES))
186208
{
187-
run_script ("var expected_message = 'Module cannot be instantiated'", &parse_options);
209+
run_script ("var expected_message = 'Module cannot be instantiated'", &parse_options, false);
188210
}
189211
else
190212
{
191-
run_script ("var expected_message = ''", &parse_options);
213+
run_script ("var expected_message = ''", &parse_options, false);
192214
}
193215

194216
global_user_value = jerry_create_object ();
@@ -203,7 +225,7 @@ main (void)
203225
mode = 0;
204226
parse_options.options = JERRY_PARSE_HAS_USER_VALUE;
205227
parse_options.user_value = global_user_value;
206-
run_script (source_p, &parse_options);
228+
run_script (source_p, &parse_options, false);
207229
jerry_release_value (global_user_value);
208230

209231
global_user_value = jerry_create_null ();
@@ -219,7 +241,7 @@ main (void)
219241
mode = 1;
220242
parse_options.options = JERRY_PARSE_HAS_USER_VALUE;
221243
parse_options.user_value = global_user_value;
222-
run_script (source_p, &parse_options);
244+
run_script (source_p, &parse_options, false);
223245
jerry_release_value (global_user_value);
224246

225247
global_user_value = jerry_create_number (5.6);
@@ -236,7 +258,7 @@ main (void)
236258
mode = 2;
237259
parse_options.options = JERRY_PARSE_HAS_USER_VALUE | JERRY_PARSE_MODULE;
238260
parse_options.user_value = global_user_value;
239-
run_script (source_p, &parse_options);
261+
run_script (source_p, &parse_options, false);
240262
jerry_release_value (global_user_value);
241263

242264
global_user_value = jerry_create_string ((const jerry_char_t *) "Any string...");
@@ -249,10 +271,27 @@ main (void)
249271
"}\n"
250272
"f()\n");
251273

252-
mode = 3;
274+
for (int i = 0; i < 2; i++)
275+
{
276+
mode = 3;
277+
parse_options.options = JERRY_PARSE_HAS_USER_VALUE | (i == 1 ? JERRY_PARSE_MODULE : 0);
278+
parse_options.user_value = jerry_create_object ();
279+
jerry_value_t property_name = jerry_create_string ((const jerry_char_t *) "MyProp1");
280+
jerry_value_t property_value = jerry_create_number (3.5);
281+
jerry_value_t result = jerry_set_property (parse_options.user_value, property_name, property_value);
282+
TEST_ASSERT (jerry_value_is_true (result));
283+
jerry_release_value (result);
284+
jerry_release_value (property_value);
285+
jerry_release_value (property_name);
286+
287+
source_p = TEST_STRING_LITERAL ("import('28_module.mjs')");
288+
run_script (source_p, &parse_options, true);
289+
}
290+
291+
mode = 4;
253292
parse_options.options = JERRY_PARSE_HAS_USER_VALUE;
254293
parse_options.user_value = global_user_value;
255-
run_script (source_p, &parse_options);
294+
run_script (source_p, &parse_options, false);
256295
jerry_release_value (global_user_value);
257296

258297
global_user_value = jerry_create_external_function (global_assert);
@@ -268,10 +307,10 @@ main (void)
268307
"}\n"
269308
"f()\n");
270309

271-
mode = 4;
310+
mode = 5;
272311
parse_options.options = JERRY_PARSE_HAS_USER_VALUE | JERRY_PARSE_MODULE;
273312
parse_options.user_value = global_user_value;
274-
run_script (source_p, &parse_options);
313+
run_script (source_p, &parse_options, false);
275314
jerry_release_value (global_user_value);
276315

277316
jerry_cleanup ();

0 commit comments

Comments
 (0)