Skip to content

Commit 6649940

Browse files
authored
Implement function.toString operation (#4752)
May increase the memory consumtpion heavily. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
1 parent 1c6b18e commit 6649940

37 files changed

+1002
-192
lines changed

docs/02.API-REFERENCE.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ Possible compile time enabled feature types:
175175
- JERRY_FEATURE_GLOBAL_THIS - GlobalThisValue support
176176
- JERRY_FEATURE_PROMISE_CALLBACK - Promise callback support
177177
- JERRY_FEATURE_MODULE - Module support
178+
- JERRY_FEATURE_WEAKREF - WeakRef support
179+
- JERRY_FEATURE_FUNCTION_TO_STRING - function toString support
178180

179181
*New in version 2.0*.
180182

@@ -183,7 +185,8 @@ Possible compile time enabled feature types:
183185
*Changed in version 2.4*: Added `JERRY_FEATURE_BIGINT`, `JERRY_FEATURE_REALM` values.
184186

185187
*Changed in version [[NEXT_RELEASE]]*: Added `JERRY_FEATURE_VM_THROW`, `JERRY_FEATURE_GLOBAL_THIS`,
186-
`JERRY_FEATURE_PROMISE_CALLBACK`, and `JERRY_FEATURE_MODULE` values.
188+
`JERRY_FEATURE_PROMISE_CALLBACK`, and `JERRY_FEATURE_MODULE`,
189+
`JERRY_FEATURE_WEAKREF`, and `JERRY_FEATURE_FUNCTION_TO_STRING` values.
187190

188191
## jerry_container_type_t
189192

jerry-core/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ set(JERRY_DEBUGGER OFF CACHE BOOL "Enable JerryScrip
2424
set(JERRY_ERROR_MESSAGES OFF CACHE BOOL "Enable error messages?")
2525
set(JERRY_EXTERNAL_CONTEXT OFF CACHE BOOL "Enable external context?")
2626
set(JERRY_PARSER ON CACHE BOOL "Enable javascript-parser?")
27+
set(JERRY_FUNCTION_TO_STRING OFF CACHE BOOL "Enable function toString operation?")
2728
set(JERRY_LINE_INFO OFF CACHE BOOL "Enable line info?")
2829
set(JERRY_LOGGING OFF CACHE BOOL "Enable logging?")
2930
set(JERRY_MEM_STATS OFF CACHE BOOL "Enable memory statistics?")
@@ -83,6 +84,7 @@ message(STATUS "JERRY_DEBUGGER " ${JERRY_DEBUGGER})
8384
message(STATUS "JERRY_ERROR_MESSAGES " ${JERRY_ERROR_MESSAGES})
8485
message(STATUS "JERRY_EXTERNAL_CONTEXT " ${JERRY_EXTERNAL_CONTEXT})
8586
message(STATUS "JERRY_PARSER " ${JERRY_PARSER})
87+
message(STATUS "JERRY_FUNCTION_TO_STRING " ${JERRY_FUNCTION_TO_STRING})
8688
message(STATUS "JERRY_LINE_INFO " ${JERRY_LINE_INFO})
8789
message(STATUS "JERRY_LOGGING " ${JERRY_LOGGING} ${JERRY_LOGGING_MESSAGE})
8890
message(STATUS "JERRY_MEM_STATS " ${JERRY_MEM_STATS})
@@ -135,6 +137,7 @@ set(SOURCE_CORE_FILES
135137
ecma/base/ecma-alloc.c
136138
ecma/base/ecma-gc.c
137139
ecma/base/ecma-errors.c
140+
ecma/base/ecma-extended-info.c
138141
ecma/base/ecma-helpers-collection.c
139142
ecma/base/ecma-helpers-conversion.c
140143
ecma/base/ecma-helpers-errol.c
@@ -559,6 +562,9 @@ jerry_add_define01(JERRY_EXTERNAL_CONTEXT)
559562
# JS-Parser
560563
jerry_add_define01(JERRY_PARSER)
561564

565+
# JS function toString
566+
jerry_add_define01(JERRY_FUNCTION_TO_STRING)
567+
562568
# JS line info
563569
jerry_add_define01(JERRY_LINE_INFO)
564570

jerry-core/api/jerry-snapshot.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -979,8 +979,13 @@ jerry_exec_snapshot (const uint32_t *snapshot_p, /**< snapshot */
979979
user_value = option_values_p->user_value;
980980
}
981981

982-
uint32_t script_size = (user_value != ECMA_VALUE_EMPTY ? sizeof (cbc_script_user_t)
983-
: sizeof (cbc_script_t));
982+
size_t script_size = sizeof (cbc_script_t);
983+
984+
if (user_value != ECMA_VALUE_EMPTY)
985+
{
986+
script_size += sizeof (ecma_value_t);
987+
}
988+
984989
cbc_script_t *script_p = jmem_heap_alloc_block (script_size);
985990

986991
CBC_SCRIPT_SET_TYPE (script_p, user_value, CBC_SCRIPT_REF_ONE);
@@ -1003,6 +1008,10 @@ jerry_exec_snapshot (const uint32_t *snapshot_p, /**< snapshot */
10031008
script_p->resource_name = resource_name;
10041009
#endif /* JERRY_RESOURCE_NAME */
10051010

1011+
#if JERRY_FUNCTION_TO_STRING
1012+
script_p->source_code = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY);
1013+
#endif /* JERRY_FUNCTION_TO_STRING */
1014+
10061015
const uint8_t *literal_base_p = snapshot_data_p + header_p->lit_table_offset;
10071016

10081017
bytecode_p = snapshot_load_compiled_code ((const uint8_t *) bytecode_p,
@@ -1021,7 +1030,7 @@ jerry_exec_snapshot (const uint32_t *snapshot_p, /**< snapshot */
10211030

10221031
if (user_value != ECMA_VALUE_EMPTY)
10231032
{
1024-
((cbc_script_user_t *) script_p)->user_value = ecma_copy_value_if_not_object (user_value);
1033+
CBC_SCRIPT_GET_USER_VALUE (script_p) = ecma_copy_value_if_not_object (user_value);
10251034
}
10261035
}
10271036

jerry-core/api/jerry.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,6 +1841,9 @@ jerry_is_feature_enabled (const jerry_feature_t feature) /**< feature to check *
18411841
#if JERRY_MODULE_SYSTEM
18421842
|| feature == JERRY_FEATURE_MODULE
18431843
#endif /* JERRY_MODULE_SYSTEM */
1844+
#if JERRY_FUNCTION_TO_STRING
1845+
|| feature == JERRY_FEATURE_FUNCTION_TO_STRING
1846+
#endif /* JERRY_FUNCTION_TO_STRING */
18441847
);
18451848
} /* jerry_is_feature_enabled */
18461849

@@ -2801,7 +2804,7 @@ jerry_create_regexp_sz (const jerry_char_t *pattern_p, /**< zero-terminated UTF-
28012804
jerry_assert_api_available ();
28022805

28032806
#if JERRY_BUILTIN_REGEXP
2804-
if (!lit_is_valid_utf8_string (pattern_p, pattern_size))
2807+
if (!lit_is_valid_utf8_string (pattern_p, pattern_size, true))
28052808
{
28062809
return jerry_throw (ecma_raise_common_error (ECMA_ERR_MSG ("Input must be a valid utf8 string")));
28072810
}
@@ -5130,7 +5133,8 @@ jerry_is_valid_utf8_string (const jerry_char_t *utf8_buf_p, /**< UTF-8 string */
51305133
jerry_size_t buf_size) /**< string size */
51315134
{
51325135
return lit_is_valid_utf8_string ((lit_utf8_byte_t *) utf8_buf_p,
5133-
(lit_utf8_size_t) buf_size);
5136+
(lit_utf8_size_t) buf_size,
5137+
true);
51345138
} /* jerry_is_valid_utf8_string */
51355139

51365140
/**
@@ -5490,7 +5494,7 @@ jerry_get_user_value (const jerry_value_t value) /**< jerry api value */
54905494
return ECMA_VALUE_UNDEFINED;
54915495
}
54925496

5493-
return ecma_copy_value (((cbc_script_user_t *) script_p)->user_value);
5497+
return ecma_copy_value (CBC_SCRIPT_GET_USER_VALUE (script_p));
54945498
} /* jerry_get_user_value */
54955499

54965500
/**

jerry-core/config.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,19 @@
231231
# define JERRY_LCACHE 1
232232
#endif /* !defined (JERRY_LCACHE) */
233233

234+
/**
235+
* Enable/Disable function toString operation.
236+
*
237+
* Allowed values:
238+
* 0: Disable function toString operation.
239+
* 1: Enable function toString operation.
240+
*
241+
* Default value: 0
242+
*/
243+
#ifndef JERRY_FUNCTION_TO_STRING
244+
# define JERRY_FUNCTION_TO_STRING 0
245+
#endif /* !defined (JERRY_FUNCTION_TO_STRING) */
246+
234247
/**
235248
* Enable/Disable line-info management inside the engine.
236249
*
@@ -634,6 +647,10 @@
634647
|| ((JERRY_LCACHE != 0) && (JERRY_LCACHE != 1))
635648
# error "Invalid value for 'JERRY_LCACHE' macro."
636649
#endif
650+
#if !defined (JERRY_FUNCTION_TO_STRING) \
651+
|| ((JERRY_FUNCTION_TO_STRING != 0) && (JERRY_FUNCTION_TO_STRING != 1))
652+
# error "Invalid value for 'JERRY_FUNCTION_TO_STRING' macro."
653+
#endif
637654
#if !defined (JERRY_LINE_INFO) \
638655
|| ((JERRY_LINE_INFO != 0) && (JERRY_LINE_INFO != 1))
639656
# error "Invalid value for 'JERRY_LINE_INFO' macro."
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
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+
#include "byte-code.h"
17+
#include "ecma-helpers.h"
18+
#include "ecma-extended-info.h"
19+
20+
#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
21+
22+
/** \addtogroup ecma ECMA
23+
* @{
24+
*
25+
* \addtogroup ecmaextendedinfo Extended info
26+
* @{
27+
*/
28+
29+
/**
30+
* Decodes an uint32_t number, and updates the buffer position.
31+
*
32+
* @return the decoded value
33+
*/
34+
uint32_t
35+
ecma_extended_info_decode_vlq (uint8_t **buffer_p) /**< [in/out] target buffer */
36+
{
37+
uint8_t *source_p = *buffer_p;
38+
uint32_t value = 0;
39+
40+
do
41+
{
42+
source_p--;
43+
value = (value << ECMA_EXTENDED_INFO_VLQ_SHIFT) | (*source_p & ECMA_EXTENDED_INFO_VLQ_MASK);
44+
}
45+
while (*source_p & ECMA_EXTENDED_INFO_VLQ_CONTINUE);
46+
47+
*buffer_p = source_p;
48+
return value;
49+
} /* ecma_extended_info_decode_vlq */
50+
51+
/**
52+
* Encodes an uint32_t number into a buffer.
53+
*/
54+
void
55+
ecma_extended_info_encode_vlq (uint8_t **buffer_p, /**< target buffer */
56+
uint32_t value) /**< encoded value */
57+
{
58+
uint8_t *destination_p = *buffer_p - 1;
59+
60+
if (value <= ECMA_EXTENDED_INFO_VLQ_MASK)
61+
{
62+
*destination_p = (uint8_t) value;
63+
*buffer_p = destination_p;
64+
return;
65+
}
66+
67+
uint32_t length = 0;
68+
uint32_t current_value = value >> ECMA_EXTENDED_INFO_VLQ_SHIFT;
69+
70+
do
71+
{
72+
current_value >>= ECMA_EXTENDED_INFO_VLQ_SHIFT;
73+
length++;
74+
}
75+
while (current_value > 0);
76+
77+
destination_p -= length;
78+
*buffer_p = destination_p;
79+
80+
do
81+
{
82+
*destination_p++ = (uint8_t) (value | ECMA_EXTENDED_INFO_VLQ_CONTINUE);
83+
value >>= ECMA_EXTENDED_INFO_VLQ_SHIFT;
84+
}
85+
while (value > 0);
86+
87+
**buffer_p &= ECMA_EXTENDED_INFO_VLQ_MASK;
88+
} /* ecma_extended_info_encode_vlq */
89+
90+
/**
91+
* Gets the encoded length of a number.
92+
*
93+
* @return encoded length
94+
*/
95+
uint32_t
96+
ecma_extended_info_get_encoded_length (uint32_t value) /**< encoded value */
97+
{
98+
uint32_t length = 0;
99+
100+
do
101+
{
102+
value >>= ECMA_EXTENDED_INFO_VLQ_SHIFT;
103+
length++;
104+
}
105+
while (value > 0);
106+
107+
return length;
108+
} /* ecma_extended_info_get_encoded_length */
109+
110+
/**
111+
* Get the extended info from a byte code
112+
*
113+
* @return pointer to the extended info
114+
*/
115+
uint8_t *
116+
ecma_compiled_code_resolve_extended_info (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */
117+
{
118+
JERRY_ASSERT (bytecode_header_p != NULL);
119+
JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO);
120+
121+
ecma_value_t *base_p = ecma_compiled_code_resolve_arguments_start (bytecode_header_p);
122+
123+
#if JERRY_ESNEXT
124+
if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) != CBC_FUNCTION_CONSTRUCTOR)
125+
{
126+
base_p--;
127+
}
128+
129+
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS)
130+
{
131+
base_p--;
132+
}
133+
#endif /* JERRY_ESNEXT */
134+
135+
#if JERRY_LINE_INFO
136+
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_LINE_INFO)
137+
{
138+
base_p--;
139+
}
140+
#endif /* JERRY_LINE_INFO */
141+
142+
JERRY_ASSERT (((uint8_t *) base_p)[-1] != 0);
143+
144+
return ((uint8_t *) base_p) - 1;
145+
} /* ecma_compiled_code_resolve_extended_info */
146+
147+
#endif /* JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING */
148+
149+
/**
150+
* @}
151+
* @}
152+
*/
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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+
#ifndef ECMA_EXTENDED_INFO_H
17+
#define ECMA_EXTENDED_INFO_H
18+
19+
/** \addtogroup ecma ECMA
20+
* @{
21+
*
22+
* \addtogroup ecmaextendedinfo Extended info
23+
* @{
24+
*/
25+
26+
#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
27+
28+
#include "ecma-globals.h"
29+
30+
/**
31+
* Vlq encoding: flag which is set for all bytes except the last one.
32+
*/
33+
#define ECMA_EXTENDED_INFO_VLQ_CONTINUE 0x80
34+
35+
/**
36+
* Vlq encoding: mask to decode the number fragment.
37+
*/
38+
#define ECMA_EXTENDED_INFO_VLQ_MASK 0x7f
39+
40+
/**
41+
* Vlq encoding: number of bits stored in a byte.
42+
*/
43+
#define ECMA_EXTENDED_INFO_VLQ_SHIFT 7
44+
45+
uint32_t ecma_extended_info_decode_vlq (uint8_t **buffer_p);
46+
void ecma_extended_info_encode_vlq (uint8_t **buffer_p, uint32_t value);
47+
uint32_t ecma_extended_info_get_encoded_length (uint32_t value);
48+
49+
uint8_t *ecma_compiled_code_resolve_extended_info (const ecma_compiled_code_t *bytecode_header_p);
50+
51+
#endif /* JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING */
52+
53+
/**
54+
* @}
55+
* @}
56+
*/
57+
58+
#endif /* !ECMA_EXTENDED_INFO_H */

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -430,10 +430,10 @@ ecma_gc_mark_compiled_code (const ecma_compiled_code_t *compiled_code_p) /**< co
430430

431431
if (CBC_SCRIPT_GET_TYPE (script_p) == CBC_SCRIPT_USER_OBJECT)
432432
{
433-
cbc_script_user_t *script_user_p = (cbc_script_user_t *) script_p;
433+
ecma_value_t user_value = CBC_SCRIPT_GET_USER_VALUE (script_p);
434434

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));
435+
JERRY_ASSERT (ecma_is_value_object (user_value));
436+
ecma_gc_set_object_visited (ecma_get_object_from_value (user_value));
437437
}
438438

439439
#if JERRY_BUILTIN_REALMS

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ typedef enum
130130
#if JERRY_ESNEXT
131131
ECMA_PARSE_INTERNAL_PRE_SCANNING = (1u << 16), /**< the parser is in pre-scanning mode */
132132
#endif /* JERRY_ESNEXT */
133+
#if JERRY_FUNCTION_TO_STRING
134+
ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER = (1u << 17), /**< source has 4 byte marker */
135+
#endif /* JERRY_FUNCTION_TO_STRING */
133136
#ifndef JERRY_NDEBUG
134137
/**
135138
* This flag represents an error in for in/of statements, which cannot be set

0 commit comments

Comments
 (0)