1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation 2425bb815Sopenharmony_ci * 3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License. 5425bb815Sopenharmony_ci * You may obtain a copy of the License at 6425bb815Sopenharmony_ci * 7425bb815Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8425bb815Sopenharmony_ci * 9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS 11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and 13425bb815Sopenharmony_ci * limitations under the License. 14425bb815Sopenharmony_ci */ 15425bb815Sopenharmony_ci 16425bb815Sopenharmony_ci#include "ecma-conversion.h" 17425bb815Sopenharmony_ci#include "ecma-exceptions.h" 18425bb815Sopenharmony_ci#include "ecma-function-object.h" 19425bb815Sopenharmony_ci#include "ecma-helpers.h" 20425bb815Sopenharmony_ci#include "ecma-lex-env.h" 21425bb815Sopenharmony_ci#include "ecma-literal-storage.h" 22425bb815Sopenharmony_ci#include "jcontext.h" 23425bb815Sopenharmony_ci#include "jerryscript.h" 24425bb815Sopenharmony_ci#include "jerry-snapshot.h" 25425bb815Sopenharmony_ci#include "js-parser.h" 26425bb815Sopenharmony_ci#include "lit-char-helpers.h" 27425bb815Sopenharmony_ci#include "re-compiler.h" 28425bb815Sopenharmony_ci 29425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_SAVE) || ENABLED (JERRY_SNAPSHOT_EXEC) 30425bb815Sopenharmony_ci 31425bb815Sopenharmony_ci/** 32425bb815Sopenharmony_ci * Get snapshot configuration flags. 33425bb815Sopenharmony_ci * 34425bb815Sopenharmony_ci * @return configuration flags 35425bb815Sopenharmony_ci */ 36425bb815Sopenharmony_cistatic inline uint32_t JERRY_ATTR_ALWAYS_INLINE 37425bb815Sopenharmony_cisnapshot_get_global_flags (bool has_regex, /**< regex literal is present */ 38425bb815Sopenharmony_ci bool has_class) /**< class literal is present */ 39425bb815Sopenharmony_ci{ 40425bb815Sopenharmony_ci JERRY_UNUSED (has_regex); 41425bb815Sopenharmony_ci JERRY_UNUSED (has_class); 42425bb815Sopenharmony_ci 43425bb815Sopenharmony_ci uint32_t flags = 0; 44425bb815Sopenharmony_ci 45425bb815Sopenharmony_ci#if ENABLED (JERRY_BUILTIN_REGEXP) 46425bb815Sopenharmony_ci flags |= (has_regex ? JERRY_SNAPSHOT_HAS_REGEX_LITERAL : 0); 47425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */ 48425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 49425bb815Sopenharmony_ci flags |= (has_class ? JERRY_SNAPSHOT_HAS_CLASS_LITERAL : 0); 50425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 51425bb815Sopenharmony_ci 52425bb815Sopenharmony_ci return flags; 53425bb815Sopenharmony_ci} /* snapshot_get_global_flags */ 54425bb815Sopenharmony_ci 55425bb815Sopenharmony_ci/** 56425bb815Sopenharmony_ci * Checks whether the global_flags argument matches to the current feature set. 57425bb815Sopenharmony_ci * 58425bb815Sopenharmony_ci * @return true if global_flags accepted, false otherwise 59425bb815Sopenharmony_ci */ 60425bb815Sopenharmony_cistatic inline bool JERRY_ATTR_ALWAYS_INLINE 61425bb815Sopenharmony_cisnapshot_check_global_flags (uint32_t global_flags) /**< global flags */ 62425bb815Sopenharmony_ci{ 63425bb815Sopenharmony_ci#if ENABLED (JERRY_BUILTIN_REGEXP) 64425bb815Sopenharmony_ci global_flags &= (uint32_t) ~JERRY_SNAPSHOT_HAS_REGEX_LITERAL; 65425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */ 66425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 67425bb815Sopenharmony_ci global_flags &= (uint32_t) ~JERRY_SNAPSHOT_HAS_CLASS_LITERAL; 68425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 69425bb815Sopenharmony_ci 70425bb815Sopenharmony_ci return global_flags == snapshot_get_global_flags (false, false); 71425bb815Sopenharmony_ci} /* snapshot_check_global_flags */ 72425bb815Sopenharmony_ci 73425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) || ENABLED (JERRY_SNAPSHOT_EXEC) */ 74425bb815Sopenharmony_ci 75425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_SAVE) 76425bb815Sopenharmony_ci 77425bb815Sopenharmony_ci/** 78425bb815Sopenharmony_ci * Variables required to take a snapshot. 79425bb815Sopenharmony_ci */ 80425bb815Sopenharmony_citypedef struct 81425bb815Sopenharmony_ci{ 82425bb815Sopenharmony_ci size_t snapshot_buffer_write_offset; 83425bb815Sopenharmony_ci ecma_value_t snapshot_error; 84425bb815Sopenharmony_ci bool regex_found; 85425bb815Sopenharmony_ci bool class_found; 86425bb815Sopenharmony_ci} snapshot_globals_t; 87425bb815Sopenharmony_ci 88425bb815Sopenharmony_ci/** \addtogroup jerrysnapshot Jerry snapshot operations 89425bb815Sopenharmony_ci * @{ 90425bb815Sopenharmony_ci */ 91425bb815Sopenharmony_ci 92425bb815Sopenharmony_ci/** 93425bb815Sopenharmony_ci * Write data into the specified buffer. 94425bb815Sopenharmony_ci * 95425bb815Sopenharmony_ci * Note: 96425bb815Sopenharmony_ci * Offset is in-out and is incremented if the write operation completes successfully. 97425bb815Sopenharmony_ci * 98425bb815Sopenharmony_ci * @return true - if write was successful, i.e. offset + data_size doesn't exceed buffer size, 99425bb815Sopenharmony_ci * false - otherwise 100425bb815Sopenharmony_ci */ 101425bb815Sopenharmony_cistatic inline bool JERRY_ATTR_ALWAYS_INLINE 102425bb815Sopenharmony_cisnapshot_write_to_buffer_by_offset (uint8_t *buffer_p, /**< buffer */ 103425bb815Sopenharmony_ci size_t buffer_size, /**< size of buffer */ 104425bb815Sopenharmony_ci size_t *in_out_buffer_offset_p, /**< [in,out] offset to write to 105425bb815Sopenharmony_ci * incremented with data_size */ 106425bb815Sopenharmony_ci const void *data_p, /**< data */ 107425bb815Sopenharmony_ci size_t data_size) /**< size of the writable data */ 108425bb815Sopenharmony_ci{ 109425bb815Sopenharmony_ci if (*in_out_buffer_offset_p + data_size > buffer_size) 110425bb815Sopenharmony_ci { 111425bb815Sopenharmony_ci return false; 112425bb815Sopenharmony_ci } 113425bb815Sopenharmony_ci 114425bb815Sopenharmony_ci memcpy (buffer_p + *in_out_buffer_offset_p, data_p, data_size); 115425bb815Sopenharmony_ci *in_out_buffer_offset_p += data_size; 116425bb815Sopenharmony_ci 117425bb815Sopenharmony_ci return true; 118425bb815Sopenharmony_ci} /* snapshot_write_to_buffer_by_offset */ 119425bb815Sopenharmony_ci 120425bb815Sopenharmony_ci/** 121425bb815Sopenharmony_ci * Maximum snapshot write buffer offset. 122425bb815Sopenharmony_ci */ 123425bb815Sopenharmony_ci#if !ENABLED (JERRY_NUMBER_TYPE_FLOAT64) 124425bb815Sopenharmony_ci#define JERRY_SNAPSHOT_MAXIMUM_WRITE_OFFSET (0x7fffff >> 1) 125425bb815Sopenharmony_ci#else /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ 126425bb815Sopenharmony_ci#define JERRY_SNAPSHOT_MAXIMUM_WRITE_OFFSET (UINT32_MAX >> 1) 127425bb815Sopenharmony_ci#endif /* !ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ 128425bb815Sopenharmony_ci 129425bb815Sopenharmony_ci/** 130425bb815Sopenharmony_ci * Save snapshot helper. 131425bb815Sopenharmony_ci * 132425bb815Sopenharmony_ci * @return start offset 133425bb815Sopenharmony_ci */ 134425bb815Sopenharmony_cistatic uint32_t 135425bb815Sopenharmony_cisnapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled code */ 136425bb815Sopenharmony_ci uint8_t *snapshot_buffer_p, /**< snapshot buffer */ 137425bb815Sopenharmony_ci size_t snapshot_buffer_size, /**< snapshot buffer size */ 138425bb815Sopenharmony_ci snapshot_globals_t *globals_p) /**< snapshot globals */ 139425bb815Sopenharmony_ci{ 140425bb815Sopenharmony_ci const jerry_char_t *error_buffer_too_small_p = (const jerry_char_t *) "Snapshot buffer too small."; 141425bb815Sopenharmony_ci 142425bb815Sopenharmony_ci if (!ecma_is_value_empty (globals_p->snapshot_error)) 143425bb815Sopenharmony_ci { 144425bb815Sopenharmony_ci return 0; 145425bb815Sopenharmony_ci } 146425bb815Sopenharmony_ci 147425bb815Sopenharmony_ci JERRY_ASSERT ((globals_p->snapshot_buffer_write_offset & (JMEM_ALIGNMENT - 1)) == 0); 148425bb815Sopenharmony_ci 149425bb815Sopenharmony_ci if (globals_p->snapshot_buffer_write_offset > JERRY_SNAPSHOT_MAXIMUM_WRITE_OFFSET) 150425bb815Sopenharmony_ci { 151425bb815Sopenharmony_ci const char * const error_message_p = "Maximum snapshot size reached."; 152425bb815Sopenharmony_ci globals_p->snapshot_error = jerry_create_error (JERRY_ERROR_RANGE, (const jerry_char_t *) error_message_p); 153425bb815Sopenharmony_ci return 0; 154425bb815Sopenharmony_ci } 155425bb815Sopenharmony_ci 156425bb815Sopenharmony_ci /* The snapshot generator always parses a single file, 157425bb815Sopenharmony_ci * so the base always starts right after the snapshot header. */ 158425bb815Sopenharmony_ci uint32_t start_offset = (uint32_t) (globals_p->snapshot_buffer_write_offset - sizeof (jerry_snapshot_header_t)); 159425bb815Sopenharmony_ci 160425bb815Sopenharmony_ci uint8_t *copied_code_start_p = snapshot_buffer_p + globals_p->snapshot_buffer_write_offset; 161425bb815Sopenharmony_ci ecma_compiled_code_t *copied_code_p = (ecma_compiled_code_t *) copied_code_start_p; 162425bb815Sopenharmony_ci 163425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 164425bb815Sopenharmony_ci if (compiled_code_p->status_flags & CBC_CODE_FLAG_HAS_TAGGED_LITERALS) 165425bb815Sopenharmony_ci { 166425bb815Sopenharmony_ci const char * const error_message_p = "Unsupported feature: tagged template literals."; 167425bb815Sopenharmony_ci globals_p->snapshot_error = jerry_create_error (JERRY_ERROR_RANGE, (const jerry_char_t *) error_message_p); 168425bb815Sopenharmony_ci return 0; 169425bb815Sopenharmony_ci } 170425bb815Sopenharmony_ci 171425bb815Sopenharmony_ci if (compiled_code_p->status_flags & CBC_CODE_FLAGS_CLASS_CONSTRUCTOR) 172425bb815Sopenharmony_ci { 173425bb815Sopenharmony_ci globals_p->class_found = true; 174425bb815Sopenharmony_ci } 175425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 176425bb815Sopenharmony_ci 177425bb815Sopenharmony_ci#if ENABLED (JERRY_BUILTIN_REGEXP) 178425bb815Sopenharmony_ci if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FUNCTION)) 179425bb815Sopenharmony_ci { 180425bb815Sopenharmony_ci /* Regular expression. */ 181425bb815Sopenharmony_ci if (globals_p->snapshot_buffer_write_offset + sizeof (ecma_compiled_code_t) > snapshot_buffer_size) 182425bb815Sopenharmony_ci { 183425bb815Sopenharmony_ci globals_p->snapshot_error = jerry_create_error (JERRY_ERROR_RANGE, error_buffer_too_small_p); 184425bb815Sopenharmony_ci return 0; 185425bb815Sopenharmony_ci } 186425bb815Sopenharmony_ci 187425bb815Sopenharmony_ci globals_p->snapshot_buffer_write_offset += sizeof (ecma_compiled_code_t); 188425bb815Sopenharmony_ci 189425bb815Sopenharmony_ci ecma_value_t pattern = ((re_compiled_code_t *) compiled_code_p)->source; 190425bb815Sopenharmony_ci ecma_string_t *pattern_string_p = ecma_get_string_from_value (pattern); 191425bb815Sopenharmony_ci 192425bb815Sopenharmony_ci ecma_length_t pattern_size = 0; 193425bb815Sopenharmony_ci 194425bb815Sopenharmony_ci ECMA_STRING_TO_UTF8_STRING (pattern_string_p, buffer_p, buffer_size); 195425bb815Sopenharmony_ci 196425bb815Sopenharmony_ci pattern_size = buffer_size; 197425bb815Sopenharmony_ci 198425bb815Sopenharmony_ci if (!snapshot_write_to_buffer_by_offset (snapshot_buffer_p, 199425bb815Sopenharmony_ci snapshot_buffer_size, 200425bb815Sopenharmony_ci &globals_p->snapshot_buffer_write_offset, 201425bb815Sopenharmony_ci buffer_p, 202425bb815Sopenharmony_ci buffer_size)) 203425bb815Sopenharmony_ci { 204425bb815Sopenharmony_ci globals_p->snapshot_error = jerry_create_error (JERRY_ERROR_RANGE, error_buffer_too_small_p); 205425bb815Sopenharmony_ci /* cannot return inside ECMA_FINALIZE_UTF8_STRING */ 206425bb815Sopenharmony_ci } 207425bb815Sopenharmony_ci 208425bb815Sopenharmony_ci ECMA_FINALIZE_UTF8_STRING (buffer_p, buffer_size); 209425bb815Sopenharmony_ci 210425bb815Sopenharmony_ci if (!ecma_is_value_empty (globals_p->snapshot_error)) 211425bb815Sopenharmony_ci { 212425bb815Sopenharmony_ci return 0; 213425bb815Sopenharmony_ci } 214425bb815Sopenharmony_ci 215425bb815Sopenharmony_ci globals_p->regex_found = true; 216425bb815Sopenharmony_ci globals_p->snapshot_buffer_write_offset = JERRY_ALIGNUP (globals_p->snapshot_buffer_write_offset, 217425bb815Sopenharmony_ci JMEM_ALIGNMENT); 218425bb815Sopenharmony_ci 219425bb815Sopenharmony_ci /* Regexp character size is stored in refs. */ 220425bb815Sopenharmony_ci copied_code_p->refs = (uint16_t) pattern_size; 221425bb815Sopenharmony_ci 222425bb815Sopenharmony_ci pattern_size += (ecma_length_t) sizeof (ecma_compiled_code_t); 223425bb815Sopenharmony_ci copied_code_p->size = (uint16_t) ((pattern_size + JMEM_ALIGNMENT - 1) >> JMEM_ALIGNMENT_LOG); 224425bb815Sopenharmony_ci 225425bb815Sopenharmony_ci copied_code_p->status_flags = compiled_code_p->status_flags; 226425bb815Sopenharmony_ci 227425bb815Sopenharmony_ci return start_offset; 228425bb815Sopenharmony_ci } 229425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */ 230425bb815Sopenharmony_ci 231425bb815Sopenharmony_ci JERRY_ASSERT (compiled_code_p->status_flags & CBC_CODE_FLAGS_FUNCTION); 232425bb815Sopenharmony_ci 233425bb815Sopenharmony_ci if (!snapshot_write_to_buffer_by_offset (snapshot_buffer_p, 234425bb815Sopenharmony_ci snapshot_buffer_size, 235425bb815Sopenharmony_ci &globals_p->snapshot_buffer_write_offset, 236425bb815Sopenharmony_ci compiled_code_p, 237425bb815Sopenharmony_ci ((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG)) 238425bb815Sopenharmony_ci { 239425bb815Sopenharmony_ci globals_p->snapshot_error = jerry_create_error (JERRY_ERROR_RANGE, error_buffer_too_small_p); 240425bb815Sopenharmony_ci return 0; 241425bb815Sopenharmony_ci } 242425bb815Sopenharmony_ci 243425bb815Sopenharmony_ci /* Sub-functions and regular expressions are stored recursively. */ 244425bb815Sopenharmony_ci uint8_t *buffer_p = (uint8_t *) copied_code_p; 245425bb815Sopenharmony_ci ecma_value_t *literal_start_p; 246425bb815Sopenharmony_ci uint32_t const_literal_end; 247425bb815Sopenharmony_ci uint32_t literal_end; 248425bb815Sopenharmony_ci 249425bb815Sopenharmony_ci if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) 250425bb815Sopenharmony_ci { 251425bb815Sopenharmony_ci literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint16_arguments_t)); 252425bb815Sopenharmony_ci 253425bb815Sopenharmony_ci cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) buffer_p; 254425bb815Sopenharmony_ci literal_end = (uint32_t) (args_p->literal_end - args_p->register_end); 255425bb815Sopenharmony_ci const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); 256425bb815Sopenharmony_ci } 257425bb815Sopenharmony_ci else 258425bb815Sopenharmony_ci { 259425bb815Sopenharmony_ci literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint8_arguments_t)); 260425bb815Sopenharmony_ci 261425bb815Sopenharmony_ci cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) buffer_p; 262425bb815Sopenharmony_ci literal_end = (uint32_t) (args_p->literal_end - args_p->register_end); 263425bb815Sopenharmony_ci const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); 264425bb815Sopenharmony_ci } 265425bb815Sopenharmony_ci 266425bb815Sopenharmony_ci for (uint32_t i = const_literal_end; i < literal_end; i++) 267425bb815Sopenharmony_ci { 268425bb815Sopenharmony_ci ecma_compiled_code_t *bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, 269425bb815Sopenharmony_ci literal_start_p[i]); 270425bb815Sopenharmony_ci 271425bb815Sopenharmony_ci if (bytecode_p == compiled_code_p) 272425bb815Sopenharmony_ci { 273425bb815Sopenharmony_ci literal_start_p[i] = 0; 274425bb815Sopenharmony_ci } 275425bb815Sopenharmony_ci else 276425bb815Sopenharmony_ci { 277425bb815Sopenharmony_ci uint32_t offset = snapshot_add_compiled_code (bytecode_p, 278425bb815Sopenharmony_ci snapshot_buffer_p, 279425bb815Sopenharmony_ci snapshot_buffer_size, 280425bb815Sopenharmony_ci globals_p); 281425bb815Sopenharmony_ci 282425bb815Sopenharmony_ci JERRY_ASSERT (!ecma_is_value_empty (globals_p->snapshot_error) || offset > start_offset); 283425bb815Sopenharmony_ci 284425bb815Sopenharmony_ci literal_start_p[i] = offset - start_offset; 285425bb815Sopenharmony_ci } 286425bb815Sopenharmony_ci } 287425bb815Sopenharmony_ci 288425bb815Sopenharmony_ci return start_offset; 289425bb815Sopenharmony_ci} /* snapshot_add_compiled_code */ 290425bb815Sopenharmony_ci 291425bb815Sopenharmony_ci/** 292425bb815Sopenharmony_ci * Create unsupported literal error. 293425bb815Sopenharmony_ci */ 294425bb815Sopenharmony_cistatic void 295425bb815Sopenharmony_cistatic_snapshot_error_unsupported_literal (snapshot_globals_t *globals_p, /**< snapshot globals */ 296425bb815Sopenharmony_ci ecma_value_t literal) /**< literal form the literal pool */ 297425bb815Sopenharmony_ci{ 298425bb815Sopenharmony_ci lit_utf8_byte_t *str_p = (lit_utf8_byte_t *) "Unsupported static snapshot literal: "; 299425bb815Sopenharmony_ci ecma_stringbuilder_t builder = ecma_stringbuilder_create_raw (str_p, 37); 300425bb815Sopenharmony_ci 301425bb815Sopenharmony_ci JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (literal)); 302425bb815Sopenharmony_ci 303425bb815Sopenharmony_ci ecma_string_t *literal_string_p = ecma_op_to_string (literal); 304425bb815Sopenharmony_ci JERRY_ASSERT (literal_string_p != NULL); 305425bb815Sopenharmony_ci 306425bb815Sopenharmony_ci ecma_stringbuilder_append (&builder, literal_string_p); 307425bb815Sopenharmony_ci 308425bb815Sopenharmony_ci ecma_deref_ecma_string (literal_string_p); 309425bb815Sopenharmony_ci 310425bb815Sopenharmony_ci ecma_object_t *error_object_p = ecma_new_standard_error_with_message (ECMA_ERROR_RANGE, 311425bb815Sopenharmony_ci ecma_stringbuilder_finalize (&builder)); 312425bb815Sopenharmony_ci 313425bb815Sopenharmony_ci globals_p->snapshot_error = ecma_create_error_object_reference (error_object_p); 314425bb815Sopenharmony_ci} /* static_snapshot_error_unsupported_literal */ 315425bb815Sopenharmony_ci 316425bb815Sopenharmony_ci/** 317425bb815Sopenharmony_ci * Save static snapshot helper. 318425bb815Sopenharmony_ci * 319425bb815Sopenharmony_ci * @return start offset 320425bb815Sopenharmony_ci */ 321425bb815Sopenharmony_cistatic uint32_t 322425bb815Sopenharmony_cistatic_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< compiled code */ 323425bb815Sopenharmony_ci uint8_t *snapshot_buffer_p, /**< snapshot buffer */ 324425bb815Sopenharmony_ci size_t snapshot_buffer_size, /**< snapshot buffer size */ 325425bb815Sopenharmony_ci snapshot_globals_t *globals_p) /**< snapshot globals */ 326425bb815Sopenharmony_ci{ 327425bb815Sopenharmony_ci if (!ecma_is_value_empty (globals_p->snapshot_error)) 328425bb815Sopenharmony_ci { 329425bb815Sopenharmony_ci return 0; 330425bb815Sopenharmony_ci } 331425bb815Sopenharmony_ci 332425bb815Sopenharmony_ci JERRY_ASSERT ((globals_p->snapshot_buffer_write_offset & (JMEM_ALIGNMENT - 1)) == 0); 333425bb815Sopenharmony_ci 334425bb815Sopenharmony_ci if (globals_p->snapshot_buffer_write_offset >= JERRY_SNAPSHOT_MAXIMUM_WRITE_OFFSET) 335425bb815Sopenharmony_ci { 336425bb815Sopenharmony_ci const char * const error_message_p = "Maximum snapshot size reached."; 337425bb815Sopenharmony_ci globals_p->snapshot_error = jerry_create_error (JERRY_ERROR_RANGE, (const jerry_char_t *) error_message_p); 338425bb815Sopenharmony_ci return 0; 339425bb815Sopenharmony_ci } 340425bb815Sopenharmony_ci 341425bb815Sopenharmony_ci /* The snapshot generator always parses a single file, 342425bb815Sopenharmony_ci * so the base always starts right after the snapshot header. */ 343425bb815Sopenharmony_ci uint32_t start_offset = (uint32_t) (globals_p->snapshot_buffer_write_offset - sizeof (jerry_snapshot_header_t)); 344425bb815Sopenharmony_ci 345425bb815Sopenharmony_ci uint8_t *copied_code_start_p = snapshot_buffer_p + globals_p->snapshot_buffer_write_offset; 346425bb815Sopenharmony_ci ecma_compiled_code_t *copied_code_p = (ecma_compiled_code_t *) copied_code_start_p; 347425bb815Sopenharmony_ci 348425bb815Sopenharmony_ci if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FUNCTION)) 349425bb815Sopenharmony_ci { 350425bb815Sopenharmony_ci /* Regular expression literals are not supported. */ 351425bb815Sopenharmony_ci const char * const error_message_p = "Regular expression literals are not supported."; 352425bb815Sopenharmony_ci globals_p->snapshot_error = jerry_create_error (JERRY_ERROR_RANGE, (const jerry_char_t *) error_message_p); 353425bb815Sopenharmony_ci return 0; 354425bb815Sopenharmony_ci } 355425bb815Sopenharmony_ci 356425bb815Sopenharmony_ci if (!snapshot_write_to_buffer_by_offset (snapshot_buffer_p, 357425bb815Sopenharmony_ci snapshot_buffer_size, 358425bb815Sopenharmony_ci &globals_p->snapshot_buffer_write_offset, 359425bb815Sopenharmony_ci compiled_code_p, 360425bb815Sopenharmony_ci ((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG)) 361425bb815Sopenharmony_ci { 362425bb815Sopenharmony_ci const char * const error_message_p = "Snapshot buffer too small."; 363425bb815Sopenharmony_ci globals_p->snapshot_error = jerry_create_error (JERRY_ERROR_RANGE, (const jerry_char_t *) error_message_p); 364425bb815Sopenharmony_ci return 0; 365425bb815Sopenharmony_ci } 366425bb815Sopenharmony_ci 367425bb815Sopenharmony_ci /* Sub-functions and regular expressions are stored recursively. */ 368425bb815Sopenharmony_ci uint8_t *buffer_p = (uint8_t *) copied_code_p; 369425bb815Sopenharmony_ci ecma_value_t *literal_start_p; 370425bb815Sopenharmony_ci uint32_t argument_end; 371425bb815Sopenharmony_ci uint32_t const_literal_end; 372425bb815Sopenharmony_ci uint32_t literal_end; 373425bb815Sopenharmony_ci 374425bb815Sopenharmony_ci ((ecma_compiled_code_t *) copied_code_p)->status_flags |= CBC_CODE_FLAGS_STATIC_FUNCTION; 375425bb815Sopenharmony_ci 376425bb815Sopenharmony_ci if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) 377425bb815Sopenharmony_ci { 378425bb815Sopenharmony_ci literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint16_arguments_t)); 379425bb815Sopenharmony_ci 380425bb815Sopenharmony_ci cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) buffer_p; 381425bb815Sopenharmony_ci argument_end = args_p->argument_end; 382425bb815Sopenharmony_ci literal_end = (uint32_t) (args_p->literal_end - args_p->register_end); 383425bb815Sopenharmony_ci const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); 384425bb815Sopenharmony_ci } 385425bb815Sopenharmony_ci else 386425bb815Sopenharmony_ci { 387425bb815Sopenharmony_ci literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint8_arguments_t)); 388425bb815Sopenharmony_ci 389425bb815Sopenharmony_ci cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) buffer_p; 390425bb815Sopenharmony_ci argument_end = args_p->argument_end; 391425bb815Sopenharmony_ci literal_end = (uint32_t) (args_p->literal_end - args_p->register_end); 392425bb815Sopenharmony_ci const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); 393425bb815Sopenharmony_ci } 394425bb815Sopenharmony_ci 395425bb815Sopenharmony_ci for (uint32_t i = 0; i < const_literal_end; i++) 396425bb815Sopenharmony_ci { 397425bb815Sopenharmony_ci if (!ecma_is_value_direct (literal_start_p[i]) 398425bb815Sopenharmony_ci && !ecma_is_value_direct_string (literal_start_p[i])) 399425bb815Sopenharmony_ci { 400425bb815Sopenharmony_ci static_snapshot_error_unsupported_literal (globals_p, literal_start_p[i]); 401425bb815Sopenharmony_ci return 0; 402425bb815Sopenharmony_ci } 403425bb815Sopenharmony_ci } 404425bb815Sopenharmony_ci 405425bb815Sopenharmony_ci for (uint32_t i = const_literal_end; i < literal_end; i++) 406425bb815Sopenharmony_ci { 407425bb815Sopenharmony_ci ecma_compiled_code_t *bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, 408425bb815Sopenharmony_ci literal_start_p[i]); 409425bb815Sopenharmony_ci 410425bb815Sopenharmony_ci if (bytecode_p == compiled_code_p) 411425bb815Sopenharmony_ci { 412425bb815Sopenharmony_ci literal_start_p[i] = 0; 413425bb815Sopenharmony_ci } 414425bb815Sopenharmony_ci else 415425bb815Sopenharmony_ci { 416425bb815Sopenharmony_ci uint32_t offset = static_snapshot_add_compiled_code (bytecode_p, 417425bb815Sopenharmony_ci snapshot_buffer_p, 418425bb815Sopenharmony_ci snapshot_buffer_size, 419425bb815Sopenharmony_ci globals_p); 420425bb815Sopenharmony_ci 421425bb815Sopenharmony_ci JERRY_ASSERT (!ecma_is_value_empty (globals_p->snapshot_error) || offset > start_offset); 422425bb815Sopenharmony_ci 423425bb815Sopenharmony_ci literal_start_p[i] = offset - start_offset; 424425bb815Sopenharmony_ci } 425425bb815Sopenharmony_ci } 426425bb815Sopenharmony_ci 427425bb815Sopenharmony_ci if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) 428425bb815Sopenharmony_ci { 429425bb815Sopenharmony_ci buffer_p += ((size_t) compiled_code_p->size) << JMEM_ALIGNMENT_LOG; 430425bb815Sopenharmony_ci literal_start_p = ((ecma_value_t *) buffer_p) - argument_end; 431425bb815Sopenharmony_ci 432425bb815Sopenharmony_ci for (uint32_t i = 0; i < argument_end; i++) 433425bb815Sopenharmony_ci { 434425bb815Sopenharmony_ci if (!ecma_is_value_direct_string (literal_start_p[i])) 435425bb815Sopenharmony_ci { 436425bb815Sopenharmony_ci static_snapshot_error_unsupported_literal (globals_p, literal_start_p[i]); 437425bb815Sopenharmony_ci return 0; 438425bb815Sopenharmony_ci } 439425bb815Sopenharmony_ci } 440425bb815Sopenharmony_ci } 441425bb815Sopenharmony_ci 442425bb815Sopenharmony_ci return start_offset; 443425bb815Sopenharmony_ci} /* static_snapshot_add_compiled_code */ 444425bb815Sopenharmony_ci 445425bb815Sopenharmony_ci/** 446425bb815Sopenharmony_ci * Set the uint16_t offsets in the code area. 447425bb815Sopenharmony_ci */ 448425bb815Sopenharmony_cistatic void 449425bb815Sopenharmony_cijerry_snapshot_set_offsets (uint32_t *buffer_p, /**< buffer */ 450425bb815Sopenharmony_ci uint32_t size, /**< buffer size */ 451425bb815Sopenharmony_ci lit_mem_to_snapshot_id_map_entry_t *lit_map_p) /**< literal map */ 452425bb815Sopenharmony_ci{ 453425bb815Sopenharmony_ci JERRY_ASSERT (size > 0); 454425bb815Sopenharmony_ci 455425bb815Sopenharmony_ci do 456425bb815Sopenharmony_ci { 457425bb815Sopenharmony_ci ecma_compiled_code_t *bytecode_p = (ecma_compiled_code_t *) buffer_p; 458425bb815Sopenharmony_ci uint32_t code_size = ((uint32_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG; 459425bb815Sopenharmony_ci 460425bb815Sopenharmony_ci if (bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION) 461425bb815Sopenharmony_ci { 462425bb815Sopenharmony_ci ecma_value_t *literal_start_p; 463425bb815Sopenharmony_ci uint32_t argument_end; 464425bb815Sopenharmony_ci uint32_t const_literal_end; 465425bb815Sopenharmony_ci 466425bb815Sopenharmony_ci if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) 467425bb815Sopenharmony_ci { 468425bb815Sopenharmony_ci literal_start_p = (ecma_value_t *) (((uint8_t *) buffer_p) + sizeof (cbc_uint16_arguments_t)); 469425bb815Sopenharmony_ci 470425bb815Sopenharmony_ci cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) buffer_p; 471425bb815Sopenharmony_ci argument_end = args_p->argument_end; 472425bb815Sopenharmony_ci const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); 473425bb815Sopenharmony_ci } 474425bb815Sopenharmony_ci else 475425bb815Sopenharmony_ci { 476425bb815Sopenharmony_ci literal_start_p = (ecma_value_t *) (((uint8_t *) buffer_p) + sizeof (cbc_uint8_arguments_t)); 477425bb815Sopenharmony_ci 478425bb815Sopenharmony_ci cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) buffer_p; 479425bb815Sopenharmony_ci argument_end = args_p->argument_end; 480425bb815Sopenharmony_ci const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); 481425bb815Sopenharmony_ci } 482425bb815Sopenharmony_ci 483425bb815Sopenharmony_ci for (uint32_t i = 0; i < const_literal_end; i++) 484425bb815Sopenharmony_ci { 485425bb815Sopenharmony_ci if (ecma_is_value_string (literal_start_p[i]) 486425bb815Sopenharmony_ci || ecma_is_value_float_number (literal_start_p[i])) 487425bb815Sopenharmony_ci { 488425bb815Sopenharmony_ci lit_mem_to_snapshot_id_map_entry_t *current_p = lit_map_p; 489425bb815Sopenharmony_ci 490425bb815Sopenharmony_ci while (current_p->literal_id != literal_start_p[i]) 491425bb815Sopenharmony_ci { 492425bb815Sopenharmony_ci current_p++; 493425bb815Sopenharmony_ci } 494425bb815Sopenharmony_ci 495425bb815Sopenharmony_ci literal_start_p[i] = current_p->literal_offset; 496425bb815Sopenharmony_ci } 497425bb815Sopenharmony_ci } 498425bb815Sopenharmony_ci 499425bb815Sopenharmony_ci if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) 500425bb815Sopenharmony_ci { 501425bb815Sopenharmony_ci uint8_t *byte_p = (uint8_t *) bytecode_p; 502425bb815Sopenharmony_ci byte_p += ((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG; 503425bb815Sopenharmony_ci literal_start_p = ((ecma_value_t *) byte_p) - argument_end; 504425bb815Sopenharmony_ci 505425bb815Sopenharmony_ci for (uint32_t i = 0; i < argument_end; i++) 506425bb815Sopenharmony_ci { 507425bb815Sopenharmony_ci if (literal_start_p[i] != ECMA_VALUE_EMPTY) 508425bb815Sopenharmony_ci { 509425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_string (literal_start_p[i])); 510425bb815Sopenharmony_ci 511425bb815Sopenharmony_ci lit_mem_to_snapshot_id_map_entry_t *current_p = lit_map_p; 512425bb815Sopenharmony_ci 513425bb815Sopenharmony_ci while (current_p->literal_id != literal_start_p[i]) 514425bb815Sopenharmony_ci { 515425bb815Sopenharmony_ci current_p++; 516425bb815Sopenharmony_ci } 517425bb815Sopenharmony_ci 518425bb815Sopenharmony_ci literal_start_p[i] = current_p->literal_offset; 519425bb815Sopenharmony_ci } 520425bb815Sopenharmony_ci } 521425bb815Sopenharmony_ci } 522425bb815Sopenharmony_ci 523425bb815Sopenharmony_ci /* Set reference counter to 1. */ 524425bb815Sopenharmony_ci bytecode_p->refs = 1; 525425bb815Sopenharmony_ci } 526425bb815Sopenharmony_ci 527425bb815Sopenharmony_ci JERRY_ASSERT ((code_size % sizeof (uint32_t)) == 0); 528425bb815Sopenharmony_ci buffer_p += code_size / sizeof (uint32_t); 529425bb815Sopenharmony_ci size -= code_size; 530425bb815Sopenharmony_ci } 531425bb815Sopenharmony_ci while (size > 0); 532425bb815Sopenharmony_ci} /* jerry_snapshot_set_offsets */ 533425bb815Sopenharmony_ci 534425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */ 535425bb815Sopenharmony_ci 536425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_EXEC) 537425bb815Sopenharmony_ci 538425bb815Sopenharmony_ci/** 539425bb815Sopenharmony_ci * Byte code blocks shorter than this threshold are always copied into the memory. 540425bb815Sopenharmony_ci * The memory / performance trade-of of byte code redirection does not worth 541425bb815Sopenharmony_ci * in such cases. 542425bb815Sopenharmony_ci */ 543425bb815Sopenharmony_ci#define BYTECODE_NO_COPY_THRESHOLD 8 544425bb815Sopenharmony_ci 545425bb815Sopenharmony_ci/** 546425bb815Sopenharmony_ci * Load byte code from snapshot. 547425bb815Sopenharmony_ci * 548425bb815Sopenharmony_ci * @return byte code 549425bb815Sopenharmony_ci */ 550425bb815Sopenharmony_cistatic ecma_compiled_code_t * 551425bb815Sopenharmony_cisnapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of the 552425bb815Sopenharmony_ci * current primary function */ 553425bb815Sopenharmony_ci const uint8_t *literal_base_p, /**< literal start */ 554425bb815Sopenharmony_ci bool copy_bytecode) /**< byte code should be copied to memory */ 555425bb815Sopenharmony_ci{ 556425bb815Sopenharmony_ci ecma_compiled_code_t *bytecode_p = (ecma_compiled_code_t *) base_addr_p; 557425bb815Sopenharmony_ci uint32_t code_size = ((uint32_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG; 558425bb815Sopenharmony_ci 559425bb815Sopenharmony_ci#if ENABLED (JERRY_BUILTIN_REGEXP) 560425bb815Sopenharmony_ci if (!(bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION)) 561425bb815Sopenharmony_ci { 562425bb815Sopenharmony_ci 563425bb815Sopenharmony_ci const uint8_t *regex_start_p = ((const uint8_t *) bytecode_p) + sizeof (ecma_compiled_code_t); 564425bb815Sopenharmony_ci 565425bb815Sopenharmony_ci /* Real size is stored in refs. */ 566425bb815Sopenharmony_ci ecma_string_t *pattern_str_p = ecma_new_ecma_string_from_utf8 (regex_start_p, 567425bb815Sopenharmony_ci bytecode_p->refs); 568425bb815Sopenharmony_ci 569425bb815Sopenharmony_ci const re_compiled_code_t *re_bytecode_p = re_compile_bytecode (pattern_str_p, 570425bb815Sopenharmony_ci bytecode_p->status_flags); 571425bb815Sopenharmony_ci ecma_deref_ecma_string (pattern_str_p); 572425bb815Sopenharmony_ci 573425bb815Sopenharmony_ci return (ecma_compiled_code_t *) re_bytecode_p; 574425bb815Sopenharmony_ci } 575425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */ 576425bb815Sopenharmony_ci 577425bb815Sopenharmony_ci JERRY_ASSERT (bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION); 578425bb815Sopenharmony_ci 579425bb815Sopenharmony_ci size_t header_size; 580425bb815Sopenharmony_ci uint32_t argument_end = 0; 581425bb815Sopenharmony_ci uint32_t const_literal_end; 582425bb815Sopenharmony_ci uint32_t literal_end; 583425bb815Sopenharmony_ci 584425bb815Sopenharmony_ci if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) 585425bb815Sopenharmony_ci { 586425bb815Sopenharmony_ci uint8_t *byte_p = (uint8_t *) bytecode_p; 587425bb815Sopenharmony_ci cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) byte_p; 588425bb815Sopenharmony_ci 589425bb815Sopenharmony_ci if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) 590425bb815Sopenharmony_ci { 591425bb815Sopenharmony_ci argument_end = args_p->argument_end; 592425bb815Sopenharmony_ci } 593425bb815Sopenharmony_ci 594425bb815Sopenharmony_ci const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); 595425bb815Sopenharmony_ci literal_end = (uint32_t) (args_p->literal_end - args_p->register_end); 596425bb815Sopenharmony_ci header_size = sizeof (cbc_uint16_arguments_t); 597425bb815Sopenharmony_ci } 598425bb815Sopenharmony_ci else 599425bb815Sopenharmony_ci { 600425bb815Sopenharmony_ci uint8_t *byte_p = (uint8_t *) bytecode_p; 601425bb815Sopenharmony_ci cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) byte_p; 602425bb815Sopenharmony_ci 603425bb815Sopenharmony_ci if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) 604425bb815Sopenharmony_ci { 605425bb815Sopenharmony_ci argument_end = args_p->argument_end; 606425bb815Sopenharmony_ci } 607425bb815Sopenharmony_ci 608425bb815Sopenharmony_ci const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); 609425bb815Sopenharmony_ci literal_end = (uint32_t) (args_p->literal_end - args_p->register_end); 610425bb815Sopenharmony_ci header_size = sizeof (cbc_uint8_arguments_t); 611425bb815Sopenharmony_ci } 612425bb815Sopenharmony_ci 613425bb815Sopenharmony_ci if (copy_bytecode 614425bb815Sopenharmony_ci || (header_size + (literal_end * sizeof (uint16_t)) + BYTECODE_NO_COPY_THRESHOLD > code_size)) 615425bb815Sopenharmony_ci { 616425bb815Sopenharmony_ci bytecode_p = (ecma_compiled_code_t *) jmem_heap_alloc_block (code_size); 617425bb815Sopenharmony_ci 618425bb815Sopenharmony_ci#if ENABLED (JERRY_MEM_STATS) 619425bb815Sopenharmony_ci jmem_stats_allocate_byte_code_bytes (code_size); 620425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_MEM_STATS) */ 621425bb815Sopenharmony_ci 622425bb815Sopenharmony_ci memcpy (bytecode_p, base_addr_p, code_size); 623425bb815Sopenharmony_ci } 624425bb815Sopenharmony_ci else 625425bb815Sopenharmony_ci { 626425bb815Sopenharmony_ci uint32_t start_offset = (uint32_t) (header_size + literal_end * sizeof (ecma_value_t)); 627425bb815Sopenharmony_ci 628425bb815Sopenharmony_ci uint8_t *real_bytecode_p = ((uint8_t *) bytecode_p) + start_offset; 629425bb815Sopenharmony_ci uint32_t new_code_size = (uint32_t) (start_offset + 1 + sizeof (uint8_t *)); 630425bb815Sopenharmony_ci 631425bb815Sopenharmony_ci if (argument_end != 0) 632425bb815Sopenharmony_ci { 633425bb815Sopenharmony_ci new_code_size += (uint32_t) (argument_end * sizeof (ecma_value_t)); 634425bb815Sopenharmony_ci } 635425bb815Sopenharmony_ci 636425bb815Sopenharmony_ci new_code_size = JERRY_ALIGNUP (new_code_size, JMEM_ALIGNMENT); 637425bb815Sopenharmony_ci 638425bb815Sopenharmony_ci bytecode_p = (ecma_compiled_code_t *) jmem_heap_alloc_block (new_code_size); 639425bb815Sopenharmony_ci 640425bb815Sopenharmony_ci#if ENABLED (JERRY_MEM_STATS) 641425bb815Sopenharmony_ci jmem_stats_allocate_byte_code_bytes (new_code_size); 642425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_MEM_STATS) */ 643425bb815Sopenharmony_ci 644425bb815Sopenharmony_ci memcpy (bytecode_p, base_addr_p, start_offset); 645425bb815Sopenharmony_ci 646425bb815Sopenharmony_ci bytecode_p->size = (uint16_t) (new_code_size >> JMEM_ALIGNMENT_LOG); 647425bb815Sopenharmony_ci 648425bb815Sopenharmony_ci uint8_t *byte_p = (uint8_t *) bytecode_p; 649425bb815Sopenharmony_ci 650425bb815Sopenharmony_ci if (argument_end != 0) 651425bb815Sopenharmony_ci { 652425bb815Sopenharmony_ci uint32_t argument_size = (uint32_t) (argument_end * sizeof (ecma_value_t)); 653425bb815Sopenharmony_ci memcpy (byte_p + new_code_size - argument_size, 654425bb815Sopenharmony_ci base_addr_p + code_size - argument_size, 655425bb815Sopenharmony_ci argument_size); 656425bb815Sopenharmony_ci } 657425bb815Sopenharmony_ci 658425bb815Sopenharmony_ci byte_p[start_offset] = CBC_SET_BYTECODE_PTR; 659425bb815Sopenharmony_ci memcpy (byte_p + start_offset + 1, &real_bytecode_p, sizeof (uint8_t *)); 660425bb815Sopenharmony_ci 661425bb815Sopenharmony_ci code_size = new_code_size; 662425bb815Sopenharmony_ci } 663425bb815Sopenharmony_ci 664425bb815Sopenharmony_ci JERRY_ASSERT (bytecode_p->refs == 1); 665425bb815Sopenharmony_ci 666425bb815Sopenharmony_ci#if ENABLED (JERRY_DEBUGGER) 667425bb815Sopenharmony_ci bytecode_p->status_flags = (uint16_t) (bytecode_p->status_flags | CBC_CODE_FLAGS_DEBUGGER_IGNORE); 668425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_DEBUGGER) */ 669425bb815Sopenharmony_ci 670425bb815Sopenharmony_ci ecma_value_t *literal_start_p = (ecma_value_t *) (((uint8_t *) bytecode_p) + header_size); 671425bb815Sopenharmony_ci 672425bb815Sopenharmony_ci for (uint32_t i = 0; i < const_literal_end; i++) 673425bb815Sopenharmony_ci { 674425bb815Sopenharmony_ci if ((literal_start_p[i] & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET) 675425bb815Sopenharmony_ci { 676425bb815Sopenharmony_ci literal_start_p[i] = ecma_snapshot_get_literal (literal_base_p, literal_start_p[i]); 677425bb815Sopenharmony_ci } 678425bb815Sopenharmony_ci } 679425bb815Sopenharmony_ci 680425bb815Sopenharmony_ci for (uint32_t i = const_literal_end; i < literal_end; i++) 681425bb815Sopenharmony_ci { 682425bb815Sopenharmony_ci size_t literal_offset = (size_t) literal_start_p[i]; 683425bb815Sopenharmony_ci 684425bb815Sopenharmony_ci if (literal_offset == 0) 685425bb815Sopenharmony_ci { 686425bb815Sopenharmony_ci /* Self reference */ 687425bb815Sopenharmony_ci ECMA_SET_INTERNAL_VALUE_POINTER (literal_start_p[i], 688425bb815Sopenharmony_ci bytecode_p); 689425bb815Sopenharmony_ci } 690425bb815Sopenharmony_ci else 691425bb815Sopenharmony_ci { 692425bb815Sopenharmony_ci ecma_compiled_code_t *literal_bytecode_p; 693425bb815Sopenharmony_ci literal_bytecode_p = snapshot_load_compiled_code (base_addr_p + literal_offset, 694425bb815Sopenharmony_ci literal_base_p, 695425bb815Sopenharmony_ci copy_bytecode); 696425bb815Sopenharmony_ci 697425bb815Sopenharmony_ci ECMA_SET_INTERNAL_VALUE_POINTER (literal_start_p[i], 698425bb815Sopenharmony_ci literal_bytecode_p); 699425bb815Sopenharmony_ci } 700425bb815Sopenharmony_ci } 701425bb815Sopenharmony_ci 702425bb815Sopenharmony_ci if (argument_end != 0) 703425bb815Sopenharmony_ci { 704425bb815Sopenharmony_ci literal_start_p = (ecma_value_t *) (((uint8_t *) bytecode_p) + code_size); 705425bb815Sopenharmony_ci literal_start_p -= argument_end; 706425bb815Sopenharmony_ci 707425bb815Sopenharmony_ci for (uint32_t i = 0; i < argument_end; i++) 708425bb815Sopenharmony_ci { 709425bb815Sopenharmony_ci if ((literal_start_p[i] & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET) 710425bb815Sopenharmony_ci { 711425bb815Sopenharmony_ci literal_start_p[i] = ecma_snapshot_get_literal (literal_base_p, literal_start_p[i]); 712425bb815Sopenharmony_ci } 713425bb815Sopenharmony_ci } 714425bb815Sopenharmony_ci } 715425bb815Sopenharmony_ci 716425bb815Sopenharmony_ci return bytecode_p; 717425bb815Sopenharmony_ci} /* snapshot_load_compiled_code */ 718425bb815Sopenharmony_ci 719425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */ 720425bb815Sopenharmony_ci 721425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_SAVE) 722425bb815Sopenharmony_ci 723425bb815Sopenharmony_ci/** 724425bb815Sopenharmony_ci * Generate snapshot from specified source and arguments 725425bb815Sopenharmony_ci * 726425bb815Sopenharmony_ci * @return size of snapshot (a number value), if it was generated succesfully 727425bb815Sopenharmony_ci * (i.e. there are no syntax errors in source code, buffer size is sufficient, 728425bb815Sopenharmony_ci * and snapshot support is enabled in current configuration through JERRY_SNAPSHOT_SAVE), 729425bb815Sopenharmony_ci * error object otherwise 730425bb815Sopenharmony_ci */ 731425bb815Sopenharmony_cistatic jerry_value_t 732425bb815Sopenharmony_cijerry_generate_snapshot_with_args (const jerry_char_t *resource_name_p, /**< script resource name */ 733425bb815Sopenharmony_ci size_t resource_name_length, /**< script resource name length */ 734425bb815Sopenharmony_ci const jerry_char_t *source_p, /**< script source */ 735425bb815Sopenharmony_ci size_t source_size, /**< script source size */ 736425bb815Sopenharmony_ci const jerry_char_t *args_p, /**< arguments string */ 737425bb815Sopenharmony_ci size_t args_size, /**< arguments string size */ 738425bb815Sopenharmony_ci uint32_t generate_snapshot_opts, /**< jerry_generate_snapshot_opts_t option bits */ 739425bb815Sopenharmony_ci uint32_t *buffer_p, /**< buffer to save snapshot to */ 740425bb815Sopenharmony_ci size_t buffer_size) /**< the buffer's size */ 741425bb815Sopenharmony_ci{ 742425bb815Sopenharmony_ci /* Currently unused arguments. */ 743425bb815Sopenharmony_ci JERRY_UNUSED (resource_name_p); 744425bb815Sopenharmony_ci JERRY_UNUSED (resource_name_length); 745425bb815Sopenharmony_ci 746425bb815Sopenharmony_ci#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) 747425bb815Sopenharmony_ci JERRY_CONTEXT (resource_name) = ECMA_VALUE_UNDEFINED; 748425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ 749425bb815Sopenharmony_ci 750425bb815Sopenharmony_ci snapshot_globals_t globals; 751425bb815Sopenharmony_ci ecma_value_t parse_status; 752425bb815Sopenharmony_ci ecma_compiled_code_t *bytecode_data_p; 753425bb815Sopenharmony_ci const uint32_t aligned_header_size = JERRY_ALIGNUP (sizeof (jerry_snapshot_header_t), 754425bb815Sopenharmony_ci JMEM_ALIGNMENT); 755425bb815Sopenharmony_ci 756425bb815Sopenharmony_ci globals.snapshot_buffer_write_offset = aligned_header_size; 757425bb815Sopenharmony_ci globals.snapshot_error = ECMA_VALUE_EMPTY; 758425bb815Sopenharmony_ci globals.regex_found = false; 759425bb815Sopenharmony_ci globals.class_found = false; 760425bb815Sopenharmony_ci 761425bb815Sopenharmony_ci parse_status = parser_parse_script (args_p, 762425bb815Sopenharmony_ci args_size, 763425bb815Sopenharmony_ci source_p, 764425bb815Sopenharmony_ci source_size, 765425bb815Sopenharmony_ci (generate_snapshot_opts & JERRY_SNAPSHOT_SAVE_STRICT) != 0, 766425bb815Sopenharmony_ci &bytecode_data_p); 767425bb815Sopenharmony_ci 768425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (parse_status)) 769425bb815Sopenharmony_ci { 770425bb815Sopenharmony_ci return ecma_create_error_reference_from_context (); 771425bb815Sopenharmony_ci } 772425bb815Sopenharmony_ci 773425bb815Sopenharmony_ci JERRY_ASSERT (bytecode_data_p != NULL); 774425bb815Sopenharmony_ci 775425bb815Sopenharmony_ci if (generate_snapshot_opts & JERRY_SNAPSHOT_SAVE_STATIC) 776425bb815Sopenharmony_ci { 777425bb815Sopenharmony_ci static_snapshot_add_compiled_code (bytecode_data_p, (uint8_t *) buffer_p, buffer_size, &globals); 778425bb815Sopenharmony_ci } 779425bb815Sopenharmony_ci else 780425bb815Sopenharmony_ci { 781425bb815Sopenharmony_ci snapshot_add_compiled_code (bytecode_data_p, (uint8_t *) buffer_p, buffer_size, &globals); 782425bb815Sopenharmony_ci } 783425bb815Sopenharmony_ci 784425bb815Sopenharmony_ci if (!ecma_is_value_empty (globals.snapshot_error)) 785425bb815Sopenharmony_ci { 786425bb815Sopenharmony_ci ecma_bytecode_deref (bytecode_data_p); 787425bb815Sopenharmony_ci return globals.snapshot_error; 788425bb815Sopenharmony_ci } 789425bb815Sopenharmony_ci 790425bb815Sopenharmony_ci jerry_snapshot_header_t header; 791425bb815Sopenharmony_ci header.magic = JERRY_SNAPSHOT_MAGIC; 792425bb815Sopenharmony_ci header.version = JERRY_SNAPSHOT_VERSION; 793425bb815Sopenharmony_ci header.global_flags = snapshot_get_global_flags (globals.regex_found, globals.class_found); 794425bb815Sopenharmony_ci header.lit_table_offset = (uint32_t) globals.snapshot_buffer_write_offset; 795425bb815Sopenharmony_ci header.number_of_funcs = 1; 796425bb815Sopenharmony_ci header.func_offsets[0] = aligned_header_size; 797425bb815Sopenharmony_ci 798425bb815Sopenharmony_ci lit_mem_to_snapshot_id_map_entry_t *lit_map_p = NULL; 799425bb815Sopenharmony_ci uint32_t literals_num = 0; 800425bb815Sopenharmony_ci 801425bb815Sopenharmony_ci if (!(generate_snapshot_opts & JERRY_SNAPSHOT_SAVE_STATIC)) 802425bb815Sopenharmony_ci { 803425bb815Sopenharmony_ci ecma_collection_t *lit_pool_p = ecma_new_collection (); 804425bb815Sopenharmony_ci 805425bb815Sopenharmony_ci ecma_save_literals_add_compiled_code (bytecode_data_p, lit_pool_p); 806425bb815Sopenharmony_ci 807425bb815Sopenharmony_ci if (!ecma_save_literals_for_snapshot (lit_pool_p, 808425bb815Sopenharmony_ci buffer_p, 809425bb815Sopenharmony_ci buffer_size, 810425bb815Sopenharmony_ci &globals.snapshot_buffer_write_offset, 811425bb815Sopenharmony_ci &lit_map_p, 812425bb815Sopenharmony_ci &literals_num)) 813425bb815Sopenharmony_ci { 814425bb815Sopenharmony_ci JERRY_ASSERT (lit_map_p == NULL); 815425bb815Sopenharmony_ci const char * const error_message_p = "Cannot allocate memory for literals."; 816425bb815Sopenharmony_ci ecma_bytecode_deref (bytecode_data_p); 817425bb815Sopenharmony_ci return jerry_create_error (JERRY_ERROR_COMMON, (const jerry_char_t *) error_message_p); 818425bb815Sopenharmony_ci } 819425bb815Sopenharmony_ci 820425bb815Sopenharmony_ci jerry_snapshot_set_offsets (buffer_p + (aligned_header_size / sizeof (uint32_t)), 821425bb815Sopenharmony_ci (uint32_t) (header.lit_table_offset - aligned_header_size), 822425bb815Sopenharmony_ci lit_map_p); 823425bb815Sopenharmony_ci } 824425bb815Sopenharmony_ci 825425bb815Sopenharmony_ci size_t header_offset = 0; 826425bb815Sopenharmony_ci 827425bb815Sopenharmony_ci snapshot_write_to_buffer_by_offset ((uint8_t *) buffer_p, 828425bb815Sopenharmony_ci buffer_size, 829425bb815Sopenharmony_ci &header_offset, 830425bb815Sopenharmony_ci &header, 831425bb815Sopenharmony_ci sizeof (header)); 832425bb815Sopenharmony_ci 833425bb815Sopenharmony_ci if (lit_map_p != NULL) 834425bb815Sopenharmony_ci { 835425bb815Sopenharmony_ci jmem_heap_free_block (lit_map_p, literals_num * sizeof (lit_mem_to_snapshot_id_map_entry_t)); 836425bb815Sopenharmony_ci } 837425bb815Sopenharmony_ci 838425bb815Sopenharmony_ci ecma_bytecode_deref (bytecode_data_p); 839425bb815Sopenharmony_ci 840425bb815Sopenharmony_ci return ecma_make_number_value ((ecma_number_t) globals.snapshot_buffer_write_offset); 841425bb815Sopenharmony_ci} /* jerry_generate_snapshot_with_args */ 842425bb815Sopenharmony_ci 843425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */ 844425bb815Sopenharmony_ci 845425bb815Sopenharmony_ci/** 846425bb815Sopenharmony_ci * Generate snapshot from specified source and arguments 847425bb815Sopenharmony_ci * 848425bb815Sopenharmony_ci * @return size of snapshot (a number value), if it was generated succesfully 849425bb815Sopenharmony_ci * (i.e. there are no syntax errors in source code, buffer size is sufficient, 850425bb815Sopenharmony_ci * and snapshot support is enabled in current configuration through JERRY_SNAPSHOT_SAVE), 851425bb815Sopenharmony_ci * error object otherwise 852425bb815Sopenharmony_ci */ 853425bb815Sopenharmony_cijerry_value_t 854425bb815Sopenharmony_cijerry_generate_snapshot (const jerry_char_t *resource_name_p, /**< script resource name */ 855425bb815Sopenharmony_ci size_t resource_name_length, /**< script resource name length */ 856425bb815Sopenharmony_ci const jerry_char_t *source_p, /**< script source */ 857425bb815Sopenharmony_ci size_t source_size, /**< script source size */ 858425bb815Sopenharmony_ci uint32_t generate_snapshot_opts, /**< jerry_generate_snapshot_opts_t option bits */ 859425bb815Sopenharmony_ci uint32_t *buffer_p, /**< buffer to save snapshot to */ 860425bb815Sopenharmony_ci size_t buffer_size) /**< the buffer's size */ 861425bb815Sopenharmony_ci{ 862425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_SAVE) 863425bb815Sopenharmony_ci uint32_t allowed_opts = (JERRY_SNAPSHOT_SAVE_STATIC | JERRY_SNAPSHOT_SAVE_STRICT); 864425bb815Sopenharmony_ci 865425bb815Sopenharmony_ci if ((generate_snapshot_opts & ~(allowed_opts)) != 0) 866425bb815Sopenharmony_ci { 867425bb815Sopenharmony_ci const char * const error_message_p = "Unsupported generate snapshot flags specified."; 868425bb815Sopenharmony_ci return jerry_create_error (JERRY_ERROR_RANGE, (const jerry_char_t *) error_message_p); 869425bb815Sopenharmony_ci } 870425bb815Sopenharmony_ci 871425bb815Sopenharmony_ci return jerry_generate_snapshot_with_args (resource_name_p, 872425bb815Sopenharmony_ci resource_name_length, 873425bb815Sopenharmony_ci source_p, 874425bb815Sopenharmony_ci source_size, 875425bb815Sopenharmony_ci NULL, 876425bb815Sopenharmony_ci 0, 877425bb815Sopenharmony_ci generate_snapshot_opts, 878425bb815Sopenharmony_ci buffer_p, 879425bb815Sopenharmony_ci buffer_size); 880425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_SNAPSHOT_SAVE) */ 881425bb815Sopenharmony_ci JERRY_UNUSED (resource_name_p); 882425bb815Sopenharmony_ci JERRY_UNUSED (resource_name_length); 883425bb815Sopenharmony_ci JERRY_UNUSED (source_p); 884425bb815Sopenharmony_ci JERRY_UNUSED (source_size); 885425bb815Sopenharmony_ci JERRY_UNUSED (generate_snapshot_opts); 886425bb815Sopenharmony_ci JERRY_UNUSED (buffer_p); 887425bb815Sopenharmony_ci JERRY_UNUSED (buffer_size); 888425bb815Sopenharmony_ci 889425bb815Sopenharmony_ci return jerry_create_error (JERRY_ERROR_COMMON, (const jerry_char_t *) "Snapshot save is not supported."); 890425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */ 891425bb815Sopenharmony_ci} /* jerry_generate_snapshot */ 892425bb815Sopenharmony_ci 893425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_EXEC) 894425bb815Sopenharmony_ci/** 895425bb815Sopenharmony_ci * Execute/load snapshot from specified buffer 896425bb815Sopenharmony_ci * 897425bb815Sopenharmony_ci * Note: 898425bb815Sopenharmony_ci * returned value must be freed with jerry_release_value, when it is no longer needed. 899425bb815Sopenharmony_ci * 900425bb815Sopenharmony_ci * @return result of bytecode - if run was successful 901425bb815Sopenharmony_ci * thrown error - otherwise 902425bb815Sopenharmony_ci */ 903425bb815Sopenharmony_cistatic jerry_value_t 904425bb815Sopenharmony_cijerry_snapshot_result (const uint32_t *snapshot_p, /**< snapshot */ 905425bb815Sopenharmony_ci size_t snapshot_size, /**< size of snapshot */ 906425bb815Sopenharmony_ci size_t func_index, /**< index of primary function */ 907425bb815Sopenharmony_ci uint32_t exec_snapshot_opts, /**< jerry_exec_snapshot_opts_t option bits */ 908425bb815Sopenharmony_ci bool as_function) /** < specify if the loaded snapshot should be returned as a function */ 909425bb815Sopenharmony_ci{ 910425bb815Sopenharmony_ci JERRY_ASSERT (snapshot_p != NULL); 911425bb815Sopenharmony_ci 912425bb815Sopenharmony_ci uint32_t allowed_opts = (JERRY_SNAPSHOT_EXEC_COPY_DATA | JERRY_SNAPSHOT_EXEC_ALLOW_STATIC); 913425bb815Sopenharmony_ci 914425bb815Sopenharmony_ci if ((exec_snapshot_opts & ~(allowed_opts)) != 0) 915425bb815Sopenharmony_ci { 916425bb815Sopenharmony_ci ecma_raise_range_error (ECMA_ERR_MSG ("Unsupported exec snapshot flags specified.")); 917425bb815Sopenharmony_ci return ecma_create_error_reference_from_context (); 918425bb815Sopenharmony_ci } 919425bb815Sopenharmony_ci 920425bb815Sopenharmony_ci const char * const invalid_version_error_p = "Invalid snapshot version or unsupported features present"; 921425bb815Sopenharmony_ci const char * const invalid_format_error_p = "Invalid snapshot format"; 922425bb815Sopenharmony_ci const uint8_t *snapshot_data_p = (uint8_t *) snapshot_p; 923425bb815Sopenharmony_ci 924425bb815Sopenharmony_ci if (snapshot_size <= sizeof (jerry_snapshot_header_t)) 925425bb815Sopenharmony_ci { 926425bb815Sopenharmony_ci ecma_raise_type_error (invalid_format_error_p); 927425bb815Sopenharmony_ci return ecma_create_error_reference_from_context (); 928425bb815Sopenharmony_ci } 929425bb815Sopenharmony_ci 930425bb815Sopenharmony_ci const jerry_snapshot_header_t *header_p = (const jerry_snapshot_header_t *) snapshot_data_p; 931425bb815Sopenharmony_ci 932425bb815Sopenharmony_ci if (header_p->magic != JERRY_SNAPSHOT_MAGIC 933425bb815Sopenharmony_ci || header_p->version != JERRY_SNAPSHOT_VERSION 934425bb815Sopenharmony_ci || !snapshot_check_global_flags (header_p->global_flags)) 935425bb815Sopenharmony_ci { 936425bb815Sopenharmony_ci ecma_raise_type_error (invalid_version_error_p); 937425bb815Sopenharmony_ci return ecma_create_error_reference_from_context (); 938425bb815Sopenharmony_ci } 939425bb815Sopenharmony_ci 940425bb815Sopenharmony_ci if (header_p->lit_table_offset > snapshot_size) 941425bb815Sopenharmony_ci { 942425bb815Sopenharmony_ci ecma_raise_type_error (invalid_version_error_p); 943425bb815Sopenharmony_ci return ecma_create_error_reference_from_context (); 944425bb815Sopenharmony_ci } 945425bb815Sopenharmony_ci 946425bb815Sopenharmony_ci if (func_index >= header_p->number_of_funcs) 947425bb815Sopenharmony_ci { 948425bb815Sopenharmony_ci ecma_raise_range_error (ECMA_ERR_MSG ("Function index is higher than maximum")); 949425bb815Sopenharmony_ci return ecma_create_error_reference_from_context (); 950425bb815Sopenharmony_ci } 951425bb815Sopenharmony_ci 952425bb815Sopenharmony_ci JERRY_ASSERT ((header_p->lit_table_offset % sizeof (uint32_t)) == 0); 953425bb815Sopenharmony_ci 954425bb815Sopenharmony_ci uint32_t func_offset = header_p->func_offsets[func_index]; 955425bb815Sopenharmony_ci ecma_compiled_code_t *bytecode_p = (ecma_compiled_code_t *) (snapshot_data_p + func_offset); 956425bb815Sopenharmony_ci 957425bb815Sopenharmony_ci if (bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION) 958425bb815Sopenharmony_ci { 959425bb815Sopenharmony_ci if (!(exec_snapshot_opts & JERRY_SNAPSHOT_EXEC_ALLOW_STATIC)) 960425bb815Sopenharmony_ci { 961425bb815Sopenharmony_ci ecma_raise_common_error (ECMA_ERR_MSG ("Static snapshots not allowed")); 962425bb815Sopenharmony_ci return ecma_create_error_reference_from_context (); 963425bb815Sopenharmony_ci } 964425bb815Sopenharmony_ci 965425bb815Sopenharmony_ci if (exec_snapshot_opts & JERRY_SNAPSHOT_EXEC_COPY_DATA) 966425bb815Sopenharmony_ci { 967425bb815Sopenharmony_ci ecma_raise_common_error (ECMA_ERR_MSG ("Static snapshots cannot be copied into memory")); 968425bb815Sopenharmony_ci return ecma_create_error_reference_from_context (); 969425bb815Sopenharmony_ci } 970425bb815Sopenharmony_ci } 971425bb815Sopenharmony_ci else 972425bb815Sopenharmony_ci { 973425bb815Sopenharmony_ci const uint8_t *literal_base_p = snapshot_data_p + header_p->lit_table_offset; 974425bb815Sopenharmony_ci 975425bb815Sopenharmony_ci bytecode_p = snapshot_load_compiled_code ((const uint8_t *) bytecode_p, 976425bb815Sopenharmony_ci literal_base_p, 977425bb815Sopenharmony_ci (exec_snapshot_opts & JERRY_SNAPSHOT_EXEC_COPY_DATA) != 0); 978425bb815Sopenharmony_ci 979425bb815Sopenharmony_ci if (bytecode_p == NULL) 980425bb815Sopenharmony_ci { 981425bb815Sopenharmony_ci return ecma_raise_type_error (invalid_format_error_p); 982425bb815Sopenharmony_ci } 983425bb815Sopenharmony_ci } 984425bb815Sopenharmony_ci 985425bb815Sopenharmony_ci ecma_value_t ret_val; 986425bb815Sopenharmony_ci 987425bb815Sopenharmony_ci if (as_function) 988425bb815Sopenharmony_ci { 989425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 990425bb815Sopenharmony_ci if (bytecode_p->status_flags & CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED) 991425bb815Sopenharmony_ci { 992425bb815Sopenharmony_ci ecma_create_global_lexical_block (); 993425bb815Sopenharmony_ci } 994425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 995425bb815Sopenharmony_ci 996425bb815Sopenharmony_ci ecma_object_t *lex_env_p = ecma_get_global_scope (); 997425bb815Sopenharmony_ci ecma_object_t *func_obj_p = ecma_op_create_simple_function_object (lex_env_p, bytecode_p); 998425bb815Sopenharmony_ci 999425bb815Sopenharmony_ci if (!(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) 1000425bb815Sopenharmony_ci { 1001425bb815Sopenharmony_ci ecma_bytecode_deref (bytecode_p); 1002425bb815Sopenharmony_ci } 1003425bb815Sopenharmony_ci ret_val = ecma_make_object_value (func_obj_p); 1004425bb815Sopenharmony_ci } 1005425bb815Sopenharmony_ci else 1006425bb815Sopenharmony_ci { 1007425bb815Sopenharmony_ci ret_val = vm_run_global (bytecode_p); 1008425bb815Sopenharmony_ci if (!(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) 1009425bb815Sopenharmony_ci { 1010425bb815Sopenharmony_ci ecma_bytecode_deref (bytecode_p); 1011425bb815Sopenharmony_ci } 1012425bb815Sopenharmony_ci } 1013425bb815Sopenharmony_ci 1014425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (ret_val)) 1015425bb815Sopenharmony_ci { 1016425bb815Sopenharmony_ci return ecma_create_error_reference_from_context (); 1017425bb815Sopenharmony_ci } 1018425bb815Sopenharmony_ci 1019425bb815Sopenharmony_ci return ret_val; 1020425bb815Sopenharmony_ci} /* jerry_snapshot_result */ 1021425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */ 1022425bb815Sopenharmony_ci 1023425bb815Sopenharmony_ci/** 1024425bb815Sopenharmony_ci * Execute snapshot from specified buffer 1025425bb815Sopenharmony_ci * 1026425bb815Sopenharmony_ci * Note: 1027425bb815Sopenharmony_ci * returned value must be freed with jerry_release_value, when it is no longer needed. 1028425bb815Sopenharmony_ci * 1029425bb815Sopenharmony_ci * @return result of bytecode - if run was successful 1030425bb815Sopenharmony_ci * thrown error - otherwise 1031425bb815Sopenharmony_ci */ 1032425bb815Sopenharmony_cijerry_value_t 1033425bb815Sopenharmony_cijerry_exec_snapshot (const uint32_t *snapshot_p, /**< snapshot */ 1034425bb815Sopenharmony_ci size_t snapshot_size, /**< size of snapshot */ 1035425bb815Sopenharmony_ci size_t func_index, /**< index of primary function */ 1036425bb815Sopenharmony_ci uint32_t exec_snapshot_opts) /**< jerry_exec_snapshot_opts_t option bits */ 1037425bb815Sopenharmony_ci{ 1038425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_EXEC) 1039425bb815Sopenharmony_ci return jerry_snapshot_result (snapshot_p, snapshot_size, func_index, exec_snapshot_opts, false); 1040425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_SNAPSHOT_EXEC) */ 1041425bb815Sopenharmony_ci JERRY_UNUSED (snapshot_p); 1042425bb815Sopenharmony_ci JERRY_UNUSED (snapshot_size); 1043425bb815Sopenharmony_ci JERRY_UNUSED (func_index); 1044425bb815Sopenharmony_ci JERRY_UNUSED (exec_snapshot_opts); 1045425bb815Sopenharmony_ci 1046425bb815Sopenharmony_ci return jerry_create_error (JERRY_ERROR_COMMON, (const jerry_char_t *) "Snapshot execution is not supported."); 1047425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */ 1048425bb815Sopenharmony_ci} /* jerry_exec_snapshot */ 1049425bb815Sopenharmony_ci 1050425bb815Sopenharmony_ci/** 1051425bb815Sopenharmony_ci * @} 1052425bb815Sopenharmony_ci */ 1053425bb815Sopenharmony_ci 1054425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_SAVE) 1055425bb815Sopenharmony_ci 1056425bb815Sopenharmony_ci/** 1057425bb815Sopenharmony_ci * Collect all literals from a snapshot file. 1058425bb815Sopenharmony_ci */ 1059425bb815Sopenharmony_cistatic void 1060425bb815Sopenharmony_ciscan_snapshot_functions (const uint8_t *buffer_p, /**< snapshot buffer start */ 1061425bb815Sopenharmony_ci const uint8_t *buffer_end_p, /**< snapshot buffer end */ 1062425bb815Sopenharmony_ci ecma_collection_t *lit_pool_p, /**< list of known values */ 1063425bb815Sopenharmony_ci const uint8_t *literal_base_p) /**< start of literal data */ 1064425bb815Sopenharmony_ci{ 1065425bb815Sopenharmony_ci JERRY_ASSERT (buffer_end_p > buffer_p); 1066425bb815Sopenharmony_ci 1067425bb815Sopenharmony_ci do 1068425bb815Sopenharmony_ci { 1069425bb815Sopenharmony_ci const ecma_compiled_code_t *bytecode_p = (ecma_compiled_code_t *) buffer_p; 1070425bb815Sopenharmony_ci uint32_t code_size = ((uint32_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG; 1071425bb815Sopenharmony_ci 1072425bb815Sopenharmony_ci if ((bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION) 1073425bb815Sopenharmony_ci && !(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) 1074425bb815Sopenharmony_ci { 1075425bb815Sopenharmony_ci const ecma_value_t *literal_start_p; 1076425bb815Sopenharmony_ci uint32_t argument_end; 1077425bb815Sopenharmony_ci uint32_t const_literal_end; 1078425bb815Sopenharmony_ci 1079425bb815Sopenharmony_ci if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) 1080425bb815Sopenharmony_ci { 1081425bb815Sopenharmony_ci literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint16_arguments_t)); 1082425bb815Sopenharmony_ci 1083425bb815Sopenharmony_ci cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) buffer_p; 1084425bb815Sopenharmony_ci argument_end = args_p->argument_end; 1085425bb815Sopenharmony_ci const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); 1086425bb815Sopenharmony_ci } 1087425bb815Sopenharmony_ci else 1088425bb815Sopenharmony_ci { 1089425bb815Sopenharmony_ci literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint8_arguments_t)); 1090425bb815Sopenharmony_ci 1091425bb815Sopenharmony_ci cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) buffer_p; 1092425bb815Sopenharmony_ci argument_end = args_p->argument_end; 1093425bb815Sopenharmony_ci const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); 1094425bb815Sopenharmony_ci } 1095425bb815Sopenharmony_ci 1096425bb815Sopenharmony_ci for (uint32_t i = 0; i < const_literal_end; i++) 1097425bb815Sopenharmony_ci { 1098425bb815Sopenharmony_ci if ((literal_start_p[i] & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET) 1099425bb815Sopenharmony_ci { 1100425bb815Sopenharmony_ci ecma_value_t lit_value = ecma_snapshot_get_literal (literal_base_p, literal_start_p[i]); 1101425bb815Sopenharmony_ci ecma_save_literals_append_value (lit_value, lit_pool_p); 1102425bb815Sopenharmony_ci } 1103425bb815Sopenharmony_ci } 1104425bb815Sopenharmony_ci 1105425bb815Sopenharmony_ci if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) 1106425bb815Sopenharmony_ci { 1107425bb815Sopenharmony_ci uint8_t *byte_p = (uint8_t *) bytecode_p; 1108425bb815Sopenharmony_ci byte_p += ((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG; 1109425bb815Sopenharmony_ci literal_start_p = ((ecma_value_t *) byte_p) - argument_end; 1110425bb815Sopenharmony_ci 1111425bb815Sopenharmony_ci for (uint32_t i = 0; i < argument_end; i++) 1112425bb815Sopenharmony_ci { 1113425bb815Sopenharmony_ci if ((literal_start_p[i] & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET) 1114425bb815Sopenharmony_ci { 1115425bb815Sopenharmony_ci ecma_value_t lit_value = ecma_snapshot_get_literal (literal_base_p, literal_start_p[i]); 1116425bb815Sopenharmony_ci ecma_save_literals_append_value (lit_value, lit_pool_p); 1117425bb815Sopenharmony_ci } 1118425bb815Sopenharmony_ci } 1119425bb815Sopenharmony_ci } 1120425bb815Sopenharmony_ci } 1121425bb815Sopenharmony_ci 1122425bb815Sopenharmony_ci buffer_p += code_size; 1123425bb815Sopenharmony_ci } 1124425bb815Sopenharmony_ci while (buffer_p < buffer_end_p); 1125425bb815Sopenharmony_ci} /* scan_snapshot_functions */ 1126425bb815Sopenharmony_ci 1127425bb815Sopenharmony_ci/** 1128425bb815Sopenharmony_ci * Update all literal offsets in a snapshot data. 1129425bb815Sopenharmony_ci */ 1130425bb815Sopenharmony_cistatic void 1131425bb815Sopenharmony_ciupdate_literal_offsets (uint8_t *buffer_p, /**< [in,out] snapshot buffer start */ 1132425bb815Sopenharmony_ci const uint8_t *buffer_end_p, /**< snapshot buffer end */ 1133425bb815Sopenharmony_ci const lit_mem_to_snapshot_id_map_entry_t *lit_map_p, /**< literal map */ 1134425bb815Sopenharmony_ci const uint8_t *literal_base_p) /**< start of literal data */ 1135425bb815Sopenharmony_ci{ 1136425bb815Sopenharmony_ci JERRY_ASSERT (buffer_end_p > buffer_p); 1137425bb815Sopenharmony_ci 1138425bb815Sopenharmony_ci do 1139425bb815Sopenharmony_ci { 1140425bb815Sopenharmony_ci const ecma_compiled_code_t *bytecode_p = (ecma_compiled_code_t *) buffer_p; 1141425bb815Sopenharmony_ci uint32_t code_size = ((uint32_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG; 1142425bb815Sopenharmony_ci 1143425bb815Sopenharmony_ci if ((bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION) 1144425bb815Sopenharmony_ci && !(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) 1145425bb815Sopenharmony_ci { 1146425bb815Sopenharmony_ci ecma_value_t *literal_start_p; 1147425bb815Sopenharmony_ci uint32_t argument_end; 1148425bb815Sopenharmony_ci uint32_t const_literal_end; 1149425bb815Sopenharmony_ci 1150425bb815Sopenharmony_ci if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) 1151425bb815Sopenharmony_ci { 1152425bb815Sopenharmony_ci literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint16_arguments_t)); 1153425bb815Sopenharmony_ci 1154425bb815Sopenharmony_ci cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) buffer_p; 1155425bb815Sopenharmony_ci argument_end = args_p->argument_end; 1156425bb815Sopenharmony_ci const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); 1157425bb815Sopenharmony_ci } 1158425bb815Sopenharmony_ci else 1159425bb815Sopenharmony_ci { 1160425bb815Sopenharmony_ci literal_start_p = (ecma_value_t *) (buffer_p + sizeof (cbc_uint8_arguments_t)); 1161425bb815Sopenharmony_ci 1162425bb815Sopenharmony_ci cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) buffer_p; 1163425bb815Sopenharmony_ci argument_end = args_p->argument_end; 1164425bb815Sopenharmony_ci const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end); 1165425bb815Sopenharmony_ci } 1166425bb815Sopenharmony_ci 1167425bb815Sopenharmony_ci for (uint32_t i = 0; i < const_literal_end; i++) 1168425bb815Sopenharmony_ci { 1169425bb815Sopenharmony_ci if ((literal_start_p[i] & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET) 1170425bb815Sopenharmony_ci { 1171425bb815Sopenharmony_ci ecma_value_t lit_value = ecma_snapshot_get_literal (literal_base_p, literal_start_p[i]); 1172425bb815Sopenharmony_ci const lit_mem_to_snapshot_id_map_entry_t *current_p = lit_map_p; 1173425bb815Sopenharmony_ci 1174425bb815Sopenharmony_ci while (current_p->literal_id != lit_value) 1175425bb815Sopenharmony_ci { 1176425bb815Sopenharmony_ci current_p++; 1177425bb815Sopenharmony_ci } 1178425bb815Sopenharmony_ci 1179425bb815Sopenharmony_ci literal_start_p[i] = current_p->literal_offset; 1180425bb815Sopenharmony_ci } 1181425bb815Sopenharmony_ci } 1182425bb815Sopenharmony_ci 1183425bb815Sopenharmony_ci if (bytecode_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) 1184425bb815Sopenharmony_ci { 1185425bb815Sopenharmony_ci uint8_t *byte_p = (uint8_t *) bytecode_p; 1186425bb815Sopenharmony_ci byte_p += ((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG; 1187425bb815Sopenharmony_ci literal_start_p = ((ecma_value_t *) byte_p) - argument_end; 1188425bb815Sopenharmony_ci 1189425bb815Sopenharmony_ci for (uint32_t i = 0; i < argument_end; i++) 1190425bb815Sopenharmony_ci { 1191425bb815Sopenharmony_ci if ((literal_start_p[i] & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_SNAPSHOT_OFFSET) 1192425bb815Sopenharmony_ci { 1193425bb815Sopenharmony_ci ecma_value_t lit_value = ecma_snapshot_get_literal (literal_base_p, literal_start_p[i]); 1194425bb815Sopenharmony_ci const lit_mem_to_snapshot_id_map_entry_t *current_p = lit_map_p; 1195425bb815Sopenharmony_ci 1196425bb815Sopenharmony_ci while (current_p->literal_id != lit_value) 1197425bb815Sopenharmony_ci { 1198425bb815Sopenharmony_ci current_p++; 1199425bb815Sopenharmony_ci } 1200425bb815Sopenharmony_ci 1201425bb815Sopenharmony_ci literal_start_p[i] = current_p->literal_offset; 1202425bb815Sopenharmony_ci } 1203425bb815Sopenharmony_ci } 1204425bb815Sopenharmony_ci } 1205425bb815Sopenharmony_ci } 1206425bb815Sopenharmony_ci 1207425bb815Sopenharmony_ci buffer_p += code_size; 1208425bb815Sopenharmony_ci } 1209425bb815Sopenharmony_ci while (buffer_p < buffer_end_p); 1210425bb815Sopenharmony_ci} /* update_literal_offsets */ 1211425bb815Sopenharmony_ci 1212425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */ 1213425bb815Sopenharmony_ci 1214425bb815Sopenharmony_ci/** 1215425bb815Sopenharmony_ci * Merge multiple snapshots into a single buffer 1216425bb815Sopenharmony_ci * 1217425bb815Sopenharmony_ci * @return length of merged snapshot file 1218425bb815Sopenharmony_ci * 0 on error 1219425bb815Sopenharmony_ci */ 1220425bb815Sopenharmony_cisize_t 1221425bb815Sopenharmony_cijerry_merge_snapshots (const uint32_t **inp_buffers_p, /**< array of (pointers to start of) input buffers */ 1222425bb815Sopenharmony_ci size_t *inp_buffer_sizes_p, /**< array of input buffer sizes */ 1223425bb815Sopenharmony_ci size_t number_of_snapshots, /**< number of snapshots */ 1224425bb815Sopenharmony_ci uint32_t *out_buffer_p, /**< output buffer */ 1225425bb815Sopenharmony_ci size_t out_buffer_size, /**< output buffer size */ 1226425bb815Sopenharmony_ci const char **error_p) /**< error description */ 1227425bb815Sopenharmony_ci{ 1228425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_SAVE) 1229425bb815Sopenharmony_ci uint32_t number_of_funcs = 0; 1230425bb815Sopenharmony_ci uint32_t merged_global_flags = 0; 1231425bb815Sopenharmony_ci size_t functions_size = sizeof (jerry_snapshot_header_t); 1232425bb815Sopenharmony_ci 1233425bb815Sopenharmony_ci if (number_of_snapshots < 2) 1234425bb815Sopenharmony_ci { 1235425bb815Sopenharmony_ci *error_p = "at least two snapshots must be passed"; 1236425bb815Sopenharmony_ci return 0; 1237425bb815Sopenharmony_ci } 1238425bb815Sopenharmony_ci 1239425bb815Sopenharmony_ci ecma_collection_t *lit_pool_p = ecma_new_collection (); 1240425bb815Sopenharmony_ci 1241425bb815Sopenharmony_ci for (uint32_t i = 0; i < number_of_snapshots; i++) 1242425bb815Sopenharmony_ci { 1243425bb815Sopenharmony_ci if (inp_buffer_sizes_p[i] < sizeof (jerry_snapshot_header_t)) 1244425bb815Sopenharmony_ci { 1245425bb815Sopenharmony_ci *error_p = "invalid snapshot file"; 1246425bb815Sopenharmony_ci ecma_collection_destroy (lit_pool_p); 1247425bb815Sopenharmony_ci return 0; 1248425bb815Sopenharmony_ci } 1249425bb815Sopenharmony_ci 1250425bb815Sopenharmony_ci const jerry_snapshot_header_t *header_p = (const jerry_snapshot_header_t *) inp_buffers_p[i]; 1251425bb815Sopenharmony_ci 1252425bb815Sopenharmony_ci if (header_p->magic != JERRY_SNAPSHOT_MAGIC 1253425bb815Sopenharmony_ci || header_p->version != JERRY_SNAPSHOT_VERSION 1254425bb815Sopenharmony_ci || !snapshot_check_global_flags (header_p->global_flags)) 1255425bb815Sopenharmony_ci { 1256425bb815Sopenharmony_ci *error_p = "invalid snapshot version or unsupported features present"; 1257425bb815Sopenharmony_ci ecma_collection_destroy (lit_pool_p); 1258425bb815Sopenharmony_ci return 0; 1259425bb815Sopenharmony_ci } 1260425bb815Sopenharmony_ci 1261425bb815Sopenharmony_ci merged_global_flags |= header_p->global_flags; 1262425bb815Sopenharmony_ci 1263425bb815Sopenharmony_ci uint32_t start_offset = header_p->func_offsets[0]; 1264425bb815Sopenharmony_ci const uint8_t *data_p = (const uint8_t *) inp_buffers_p[i]; 1265425bb815Sopenharmony_ci const uint8_t *literal_base_p = data_p + header_p->lit_table_offset; 1266425bb815Sopenharmony_ci 1267425bb815Sopenharmony_ci JERRY_ASSERT (header_p->number_of_funcs > 0); 1268425bb815Sopenharmony_ci 1269425bb815Sopenharmony_ci number_of_funcs += header_p->number_of_funcs; 1270425bb815Sopenharmony_ci functions_size += header_p->lit_table_offset - start_offset; 1271425bb815Sopenharmony_ci 1272425bb815Sopenharmony_ci scan_snapshot_functions (data_p + start_offset, 1273425bb815Sopenharmony_ci literal_base_p, 1274425bb815Sopenharmony_ci lit_pool_p, 1275425bb815Sopenharmony_ci literal_base_p); 1276425bb815Sopenharmony_ci } 1277425bb815Sopenharmony_ci 1278425bb815Sopenharmony_ci JERRY_ASSERT (number_of_funcs > 0); 1279425bb815Sopenharmony_ci 1280425bb815Sopenharmony_ci functions_size += JERRY_ALIGNUP ((number_of_funcs - 1) * sizeof (uint32_t), JMEM_ALIGNMENT); 1281425bb815Sopenharmony_ci 1282425bb815Sopenharmony_ci if (functions_size >= out_buffer_size) 1283425bb815Sopenharmony_ci { 1284425bb815Sopenharmony_ci *error_p = "output buffer is too small"; 1285425bb815Sopenharmony_ci ecma_collection_destroy (lit_pool_p); 1286425bb815Sopenharmony_ci return 0; 1287425bb815Sopenharmony_ci } 1288425bb815Sopenharmony_ci 1289425bb815Sopenharmony_ci jerry_snapshot_header_t *header_p = (jerry_snapshot_header_t *) out_buffer_p; 1290425bb815Sopenharmony_ci 1291425bb815Sopenharmony_ci header_p->magic = JERRY_SNAPSHOT_MAGIC; 1292425bb815Sopenharmony_ci header_p->version = JERRY_SNAPSHOT_VERSION; 1293425bb815Sopenharmony_ci header_p->global_flags = merged_global_flags; 1294425bb815Sopenharmony_ci header_p->lit_table_offset = (uint32_t) functions_size; 1295425bb815Sopenharmony_ci header_p->number_of_funcs = number_of_funcs; 1296425bb815Sopenharmony_ci 1297425bb815Sopenharmony_ci lit_mem_to_snapshot_id_map_entry_t *lit_map_p; 1298425bb815Sopenharmony_ci uint32_t literals_num; 1299425bb815Sopenharmony_ci 1300425bb815Sopenharmony_ci if (!ecma_save_literals_for_snapshot (lit_pool_p, 1301425bb815Sopenharmony_ci out_buffer_p, 1302425bb815Sopenharmony_ci out_buffer_size, 1303425bb815Sopenharmony_ci &functions_size, 1304425bb815Sopenharmony_ci &lit_map_p, 1305425bb815Sopenharmony_ci &literals_num)) 1306425bb815Sopenharmony_ci { 1307425bb815Sopenharmony_ci *error_p = "buffer is too small"; 1308425bb815Sopenharmony_ci return 0; 1309425bb815Sopenharmony_ci } 1310425bb815Sopenharmony_ci 1311425bb815Sopenharmony_ci uint32_t *func_offset_p = header_p->func_offsets; 1312425bb815Sopenharmony_ci uint8_t *dst_p = ((uint8_t *) out_buffer_p) + sizeof (jerry_snapshot_header_t); 1313425bb815Sopenharmony_ci dst_p += JERRY_ALIGNUP ((number_of_funcs - 1) * sizeof (uint32_t), JMEM_ALIGNMENT); 1314425bb815Sopenharmony_ci 1315425bb815Sopenharmony_ci for (uint32_t i = 0; i < number_of_snapshots; i++) 1316425bb815Sopenharmony_ci { 1317425bb815Sopenharmony_ci const jerry_snapshot_header_t *current_header_p = (const jerry_snapshot_header_t *) inp_buffers_p[i]; 1318425bb815Sopenharmony_ci 1319425bb815Sopenharmony_ci uint32_t start_offset = current_header_p->func_offsets[0]; 1320425bb815Sopenharmony_ci 1321425bb815Sopenharmony_ci memcpy (dst_p, 1322425bb815Sopenharmony_ci ((const uint8_t *) inp_buffers_p[i]) + start_offset, 1323425bb815Sopenharmony_ci current_header_p->lit_table_offset - start_offset); 1324425bb815Sopenharmony_ci 1325425bb815Sopenharmony_ci const uint8_t *literal_base_p = ((const uint8_t *) inp_buffers_p[i]) + current_header_p->lit_table_offset; 1326425bb815Sopenharmony_ci update_literal_offsets (dst_p, 1327425bb815Sopenharmony_ci dst_p + current_header_p->lit_table_offset - start_offset, 1328425bb815Sopenharmony_ci lit_map_p, 1329425bb815Sopenharmony_ci literal_base_p); 1330425bb815Sopenharmony_ci 1331425bb815Sopenharmony_ci uint32_t current_offset = (uint32_t) (dst_p - (uint8_t *) out_buffer_p) - start_offset; 1332425bb815Sopenharmony_ci 1333425bb815Sopenharmony_ci for (uint32_t j = 0; j < current_header_p->number_of_funcs; j++) 1334425bb815Sopenharmony_ci { 1335425bb815Sopenharmony_ci /* Updating offset without changing any flags. */ 1336425bb815Sopenharmony_ci *func_offset_p++ = current_header_p->func_offsets[j] + current_offset; 1337425bb815Sopenharmony_ci } 1338425bb815Sopenharmony_ci 1339425bb815Sopenharmony_ci dst_p += current_header_p->lit_table_offset - start_offset; 1340425bb815Sopenharmony_ci } 1341425bb815Sopenharmony_ci 1342425bb815Sopenharmony_ci JERRY_ASSERT ((uint32_t) (dst_p - (uint8_t *) out_buffer_p) == header_p->lit_table_offset); 1343425bb815Sopenharmony_ci 1344425bb815Sopenharmony_ci if (lit_map_p != NULL) 1345425bb815Sopenharmony_ci { 1346425bb815Sopenharmony_ci jmem_heap_free_block (lit_map_p, literals_num * sizeof (lit_mem_to_snapshot_id_map_entry_t)); 1347425bb815Sopenharmony_ci } 1348425bb815Sopenharmony_ci 1349425bb815Sopenharmony_ci *error_p = NULL; 1350425bb815Sopenharmony_ci return functions_size; 1351425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_SNAPSHOT_SAVE) */ 1352425bb815Sopenharmony_ci JERRY_UNUSED (inp_buffers_p); 1353425bb815Sopenharmony_ci JERRY_UNUSED (inp_buffer_sizes_p); 1354425bb815Sopenharmony_ci JERRY_UNUSED (number_of_snapshots); 1355425bb815Sopenharmony_ci JERRY_UNUSED (out_buffer_p); 1356425bb815Sopenharmony_ci JERRY_UNUSED (out_buffer_size); 1357425bb815Sopenharmony_ci JERRY_UNUSED (error_p); 1358425bb815Sopenharmony_ci 1359425bb815Sopenharmony_ci *error_p = "snapshot merge not supported"; 1360425bb815Sopenharmony_ci return 0; 1361425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */ 1362425bb815Sopenharmony_ci} /* jerry_merge_snapshots */ 1363425bb815Sopenharmony_ci 1364425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_SAVE) 1365425bb815Sopenharmony_ci 1366425bb815Sopenharmony_ci/** 1367425bb815Sopenharmony_ci * ====================== Functions for literal saving ========================== 1368425bb815Sopenharmony_ci */ 1369425bb815Sopenharmony_ci 1370425bb815Sopenharmony_ci/** 1371425bb815Sopenharmony_ci * Compare two ecma_strings by size, then lexicographically. 1372425bb815Sopenharmony_ci * 1373425bb815Sopenharmony_ci * @return true - if the first string is less than the second one, 1374425bb815Sopenharmony_ci * false - otherwise 1375425bb815Sopenharmony_ci */ 1376425bb815Sopenharmony_cistatic bool 1377425bb815Sopenharmony_cijerry_save_literals_compare (ecma_string_t *literal1, /**< first literal */ 1378425bb815Sopenharmony_ci ecma_string_t *literal2) /**< second literal */ 1379425bb815Sopenharmony_ci{ 1380425bb815Sopenharmony_ci const lit_utf8_size_t lit1_size = ecma_string_get_size (literal1); 1381425bb815Sopenharmony_ci const lit_utf8_size_t lit2_size = ecma_string_get_size (literal2); 1382425bb815Sopenharmony_ci 1383425bb815Sopenharmony_ci if (lit1_size == lit2_size) 1384425bb815Sopenharmony_ci { 1385425bb815Sopenharmony_ci return ecma_compare_ecma_strings_relational (literal1, literal2); 1386425bb815Sopenharmony_ci } 1387425bb815Sopenharmony_ci 1388425bb815Sopenharmony_ci return (lit1_size < lit2_size); 1389425bb815Sopenharmony_ci} /* jerry_save_literals_compare */ 1390425bb815Sopenharmony_ci 1391425bb815Sopenharmony_ci/** 1392425bb815Sopenharmony_ci * Helper function for the heapsort algorithm. 1393425bb815Sopenharmony_ci * 1394425bb815Sopenharmony_ci * @return index of the maximum value 1395425bb815Sopenharmony_ci */ 1396425bb815Sopenharmony_cistatic lit_utf8_size_t 1397425bb815Sopenharmony_cijerry_save_literals_heap_max (ecma_string_t *literals[], /**< array of literals */ 1398425bb815Sopenharmony_ci lit_utf8_size_t num_of_nodes, /**< number of nodes */ 1399425bb815Sopenharmony_ci lit_utf8_size_t node_idx, /**< index of parent node */ 1400425bb815Sopenharmony_ci lit_utf8_size_t child_idx1, /**< index of the first child */ 1401425bb815Sopenharmony_ci lit_utf8_size_t child_idx2) /**< index of the second child */ 1402425bb815Sopenharmony_ci{ 1403425bb815Sopenharmony_ci lit_utf8_size_t max_idx = node_idx; 1404425bb815Sopenharmony_ci 1405425bb815Sopenharmony_ci if (child_idx1 < num_of_nodes 1406425bb815Sopenharmony_ci && jerry_save_literals_compare (literals[max_idx], literals[child_idx1])) 1407425bb815Sopenharmony_ci { 1408425bb815Sopenharmony_ci max_idx = child_idx1; 1409425bb815Sopenharmony_ci } 1410425bb815Sopenharmony_ci 1411425bb815Sopenharmony_ci if (child_idx2 < num_of_nodes 1412425bb815Sopenharmony_ci && jerry_save_literals_compare (literals[max_idx], literals[child_idx2])) 1413425bb815Sopenharmony_ci { 1414425bb815Sopenharmony_ci max_idx = child_idx2; 1415425bb815Sopenharmony_ci } 1416425bb815Sopenharmony_ci 1417425bb815Sopenharmony_ci return max_idx; 1418425bb815Sopenharmony_ci} /* jerry_save_literals_heap_max */ 1419425bb815Sopenharmony_ci 1420425bb815Sopenharmony_ci/** 1421425bb815Sopenharmony_ci * Helper function for the heapsort algorithm. 1422425bb815Sopenharmony_ci */ 1423425bb815Sopenharmony_cistatic void 1424425bb815Sopenharmony_cijerry_save_literals_down_heap (ecma_string_t *literals[], /**< array of literals */ 1425425bb815Sopenharmony_ci lit_utf8_size_t num_of_nodes, /**< number of nodes */ 1426425bb815Sopenharmony_ci lit_utf8_size_t node_idx) /**< index of parent node */ 1427425bb815Sopenharmony_ci{ 1428425bb815Sopenharmony_ci while (true) 1429425bb815Sopenharmony_ci { 1430425bb815Sopenharmony_ci lit_utf8_size_t max_idx = jerry_save_literals_heap_max (literals, 1431425bb815Sopenharmony_ci num_of_nodes, 1432425bb815Sopenharmony_ci node_idx, 1433425bb815Sopenharmony_ci 2 * node_idx + 1, 1434425bb815Sopenharmony_ci 2 * node_idx + 2); 1435425bb815Sopenharmony_ci if (max_idx == node_idx) 1436425bb815Sopenharmony_ci { 1437425bb815Sopenharmony_ci break; 1438425bb815Sopenharmony_ci } 1439425bb815Sopenharmony_ci 1440425bb815Sopenharmony_ci ecma_string_t *tmp_str_p = literals[node_idx]; 1441425bb815Sopenharmony_ci literals[node_idx] = literals[max_idx]; 1442425bb815Sopenharmony_ci literals[max_idx] = tmp_str_p; 1443425bb815Sopenharmony_ci 1444425bb815Sopenharmony_ci node_idx = max_idx; 1445425bb815Sopenharmony_ci } 1446425bb815Sopenharmony_ci} /* jerry_save_literals_down_heap */ 1447425bb815Sopenharmony_ci 1448425bb815Sopenharmony_ci/** 1449425bb815Sopenharmony_ci * Helper function for a heapsort algorithm. 1450425bb815Sopenharmony_ci */ 1451425bb815Sopenharmony_cistatic void 1452425bb815Sopenharmony_cijerry_save_literals_sort (ecma_string_t *literals[], /**< array of literals */ 1453425bb815Sopenharmony_ci lit_utf8_size_t num_of_literals) /**< number of literals */ 1454425bb815Sopenharmony_ci{ 1455425bb815Sopenharmony_ci if (num_of_literals < 2) 1456425bb815Sopenharmony_ci { 1457425bb815Sopenharmony_ci return; 1458425bb815Sopenharmony_ci } 1459425bb815Sopenharmony_ci 1460425bb815Sopenharmony_ci lit_utf8_size_t lit_idx = (num_of_literals - 2) / 2; 1461425bb815Sopenharmony_ci 1462425bb815Sopenharmony_ci while (lit_idx <= (num_of_literals - 2) / 2) 1463425bb815Sopenharmony_ci { 1464425bb815Sopenharmony_ci jerry_save_literals_down_heap (literals, num_of_literals, lit_idx--); 1465425bb815Sopenharmony_ci } 1466425bb815Sopenharmony_ci 1467425bb815Sopenharmony_ci for (lit_idx = 0; lit_idx < num_of_literals; lit_idx++) 1468425bb815Sopenharmony_ci { 1469425bb815Sopenharmony_ci const lit_utf8_size_t last_idx = num_of_literals - lit_idx - 1; 1470425bb815Sopenharmony_ci 1471425bb815Sopenharmony_ci ecma_string_t *tmp_str_p = literals[last_idx]; 1472425bb815Sopenharmony_ci literals[last_idx] = literals[0]; 1473425bb815Sopenharmony_ci literals[0] = tmp_str_p; 1474425bb815Sopenharmony_ci 1475425bb815Sopenharmony_ci jerry_save_literals_down_heap (literals, last_idx, 0); 1476425bb815Sopenharmony_ci } 1477425bb815Sopenharmony_ci} /* jerry_save_literals_sort */ 1478425bb815Sopenharmony_ci 1479425bb815Sopenharmony_ci/** 1480425bb815Sopenharmony_ci * Append characters to the specified buffer. 1481425bb815Sopenharmony_ci * 1482425bb815Sopenharmony_ci * @return the position of the buffer pointer after copy. 1483425bb815Sopenharmony_ci */ 1484425bb815Sopenharmony_cistatic uint8_t * 1485425bb815Sopenharmony_cijerry_append_chars_to_buffer (uint8_t *buffer_p, /**< buffer */ 1486425bb815Sopenharmony_ci uint8_t *buffer_end_p, /**< the end of the buffer */ 1487425bb815Sopenharmony_ci const char *chars, /**< string */ 1488425bb815Sopenharmony_ci lit_utf8_size_t string_size) /**< string size */ 1489425bb815Sopenharmony_ci{ 1490425bb815Sopenharmony_ci if (buffer_p > buffer_end_p) 1491425bb815Sopenharmony_ci { 1492425bb815Sopenharmony_ci return buffer_p; 1493425bb815Sopenharmony_ci } 1494425bb815Sopenharmony_ci 1495425bb815Sopenharmony_ci if (string_size == 0) 1496425bb815Sopenharmony_ci { 1497425bb815Sopenharmony_ci string_size = (lit_utf8_size_t) strlen (chars); 1498425bb815Sopenharmony_ci } 1499425bb815Sopenharmony_ci 1500425bb815Sopenharmony_ci if (buffer_p + string_size <= buffer_end_p) 1501425bb815Sopenharmony_ci { 1502425bb815Sopenharmony_ci memcpy ((char *) buffer_p, chars, string_size); 1503425bb815Sopenharmony_ci 1504425bb815Sopenharmony_ci return buffer_p + string_size; 1505425bb815Sopenharmony_ci } 1506425bb815Sopenharmony_ci 1507425bb815Sopenharmony_ci /* Move the pointer behind the buffer to prevent further writes. */ 1508425bb815Sopenharmony_ci return buffer_end_p + 1; 1509425bb815Sopenharmony_ci} /* jerry_append_chars_to_buffer */ 1510425bb815Sopenharmony_ci 1511425bb815Sopenharmony_ci/** 1512425bb815Sopenharmony_ci * Append an ecma-string to the specified buffer. 1513425bb815Sopenharmony_ci * 1514425bb815Sopenharmony_ci * @return the position of the buffer pointer after copy. 1515425bb815Sopenharmony_ci */ 1516425bb815Sopenharmony_cistatic uint8_t * 1517425bb815Sopenharmony_cijerry_append_ecma_string_to_buffer (uint8_t *buffer_p, /**< buffer */ 1518425bb815Sopenharmony_ci uint8_t *buffer_end_p, /**< the end of the buffer */ 1519425bb815Sopenharmony_ci ecma_string_t *string_p) /**< ecma-string */ 1520425bb815Sopenharmony_ci{ 1521425bb815Sopenharmony_ci ECMA_STRING_TO_UTF8_STRING (string_p, str_buffer_p, str_buffer_size); 1522425bb815Sopenharmony_ci 1523425bb815Sopenharmony_ci /* Append the string to the buffer. */ 1524425bb815Sopenharmony_ci uint8_t *new_buffer_p = jerry_append_chars_to_buffer (buffer_p, 1525425bb815Sopenharmony_ci buffer_end_p, 1526425bb815Sopenharmony_ci (const char *) str_buffer_p, 1527425bb815Sopenharmony_ci str_buffer_size); 1528425bb815Sopenharmony_ci 1529425bb815Sopenharmony_ci ECMA_FINALIZE_UTF8_STRING (str_buffer_p, str_buffer_size); 1530425bb815Sopenharmony_ci 1531425bb815Sopenharmony_ci return new_buffer_p; 1532425bb815Sopenharmony_ci} /* jerry_append_ecma_string_to_buffer */ 1533425bb815Sopenharmony_ci 1534425bb815Sopenharmony_ci/** 1535425bb815Sopenharmony_ci * Append an unsigned number to the specified buffer. 1536425bb815Sopenharmony_ci * 1537425bb815Sopenharmony_ci * @return the position of the buffer pointer after copy. 1538425bb815Sopenharmony_ci */ 1539425bb815Sopenharmony_cistatic uint8_t * 1540425bb815Sopenharmony_cijerry_append_number_to_buffer (uint8_t *buffer_p, /**< buffer */ 1541425bb815Sopenharmony_ci uint8_t *buffer_end_p, /**< the end of the buffer */ 1542425bb815Sopenharmony_ci lit_utf8_size_t number) /**< number */ 1543425bb815Sopenharmony_ci{ 1544425bb815Sopenharmony_ci lit_utf8_byte_t uint32_to_str_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; 1545425bb815Sopenharmony_ci lit_utf8_size_t utf8_str_size = ecma_uint32_to_utf8_string (number, 1546425bb815Sopenharmony_ci uint32_to_str_buffer, 1547425bb815Sopenharmony_ci ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); 1548425bb815Sopenharmony_ci 1549425bb815Sopenharmony_ci JERRY_ASSERT (utf8_str_size <= ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); 1550425bb815Sopenharmony_ci 1551425bb815Sopenharmony_ci return jerry_append_chars_to_buffer (buffer_p, 1552425bb815Sopenharmony_ci buffer_end_p, 1553425bb815Sopenharmony_ci (const char *) uint32_to_str_buffer, 1554425bb815Sopenharmony_ci utf8_str_size); 1555425bb815Sopenharmony_ci} /* jerry_append_number_to_buffer */ 1556425bb815Sopenharmony_ci 1557425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */ 1558425bb815Sopenharmony_ci 1559425bb815Sopenharmony_ci/** 1560425bb815Sopenharmony_ci * Get the literals from a snapshot. Copies certain string literals into the given 1561425bb815Sopenharmony_ci * buffer in a specified format. 1562425bb815Sopenharmony_ci * 1563425bb815Sopenharmony_ci * Note: 1564425bb815Sopenharmony_ci * Only valid identifiers are saved in C format. 1565425bb815Sopenharmony_ci * 1566425bb815Sopenharmony_ci * @return size of the literal-list in bytes, at most equal to the buffer size, 1567425bb815Sopenharmony_ci * if the list of the literals isn't empty, 1568425bb815Sopenharmony_ci * 0 - otherwise. 1569425bb815Sopenharmony_ci */ 1570425bb815Sopenharmony_cisize_t 1571425bb815Sopenharmony_cijerry_get_literals_from_snapshot (const uint32_t *snapshot_p, /**< input snapshot buffer */ 1572425bb815Sopenharmony_ci size_t snapshot_size, /**< size of the input snapshot buffer */ 1573425bb815Sopenharmony_ci jerry_char_t *lit_buf_p, /**< [out] buffer to save literals to */ 1574425bb815Sopenharmony_ci size_t lit_buf_size, /**< the buffer's size */ 1575425bb815Sopenharmony_ci bool is_c_format) /**< format-flag */ 1576425bb815Sopenharmony_ci{ 1577425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_SAVE) 1578425bb815Sopenharmony_ci const uint8_t *snapshot_data_p = (uint8_t *) snapshot_p; 1579425bb815Sopenharmony_ci const jerry_snapshot_header_t *header_p = (const jerry_snapshot_header_t *) snapshot_data_p; 1580425bb815Sopenharmony_ci 1581425bb815Sopenharmony_ci if (snapshot_size <= sizeof (jerry_snapshot_header_t) 1582425bb815Sopenharmony_ci || header_p->magic != JERRY_SNAPSHOT_MAGIC 1583425bb815Sopenharmony_ci || header_p->version != JERRY_SNAPSHOT_VERSION 1584425bb815Sopenharmony_ci || !snapshot_check_global_flags (header_p->global_flags)) 1585425bb815Sopenharmony_ci { 1586425bb815Sopenharmony_ci /* Invalid snapshot format */ 1587425bb815Sopenharmony_ci return 0; 1588425bb815Sopenharmony_ci } 1589425bb815Sopenharmony_ci 1590425bb815Sopenharmony_ci JERRY_ASSERT ((header_p->lit_table_offset % sizeof (uint32_t)) == 0); 1591425bb815Sopenharmony_ci const uint8_t *literal_base_p = snapshot_data_p + header_p->lit_table_offset; 1592425bb815Sopenharmony_ci 1593425bb815Sopenharmony_ci ecma_collection_t *lit_pool_p = ecma_new_collection (); 1594425bb815Sopenharmony_ci scan_snapshot_functions (snapshot_data_p + header_p->func_offsets[0], 1595425bb815Sopenharmony_ci literal_base_p, 1596425bb815Sopenharmony_ci lit_pool_p, 1597425bb815Sopenharmony_ci literal_base_p); 1598425bb815Sopenharmony_ci 1599425bb815Sopenharmony_ci lit_utf8_size_t literal_count = 0; 1600425bb815Sopenharmony_ci ecma_value_t *buffer_p = lit_pool_p->buffer_p; 1601425bb815Sopenharmony_ci 1602425bb815Sopenharmony_ci /* Count the valid and non-magic identifiers in the list. */ 1603425bb815Sopenharmony_ci for (uint32_t i = 0; i < lit_pool_p->item_count; i++) 1604425bb815Sopenharmony_ci { 1605425bb815Sopenharmony_ci if (ecma_is_value_string (buffer_p[i])) 1606425bb815Sopenharmony_ci { 1607425bb815Sopenharmony_ci ecma_string_t *literal_p = ecma_get_string_from_value (buffer_p[i]); 1608425bb815Sopenharmony_ci 1609425bb815Sopenharmony_ci if (ecma_get_string_magic (literal_p) == LIT_MAGIC_STRING__COUNT) 1610425bb815Sopenharmony_ci { 1611425bb815Sopenharmony_ci literal_count++; 1612425bb815Sopenharmony_ci } 1613425bb815Sopenharmony_ci } 1614425bb815Sopenharmony_ci } 1615425bb815Sopenharmony_ci 1616425bb815Sopenharmony_ci if (literal_count == 0) 1617425bb815Sopenharmony_ci { 1618425bb815Sopenharmony_ci ecma_collection_destroy (lit_pool_p); 1619425bb815Sopenharmony_ci return 0; 1620425bb815Sopenharmony_ci } 1621425bb815Sopenharmony_ci 1622425bb815Sopenharmony_ci jerry_char_t *const buffer_start_p = lit_buf_p; 1623425bb815Sopenharmony_ci jerry_char_t *const buffer_end_p = lit_buf_p + lit_buf_size; 1624425bb815Sopenharmony_ci 1625425bb815Sopenharmony_ci JMEM_DEFINE_LOCAL_ARRAY (literal_array, literal_count, ecma_string_t *); 1626425bb815Sopenharmony_ci lit_utf8_size_t literal_idx = 0; 1627425bb815Sopenharmony_ci 1628425bb815Sopenharmony_ci buffer_p = lit_pool_p->buffer_p; 1629425bb815Sopenharmony_ci 1630425bb815Sopenharmony_ci /* Count the valid and non-magic identifiers in the list. */ 1631425bb815Sopenharmony_ci for (uint32_t i = 0; i < lit_pool_p->item_count; i++) 1632425bb815Sopenharmony_ci { 1633425bb815Sopenharmony_ci if (ecma_is_value_string (buffer_p[i])) 1634425bb815Sopenharmony_ci { 1635425bb815Sopenharmony_ci ecma_string_t *literal_p = ecma_get_string_from_value (buffer_p[i]); 1636425bb815Sopenharmony_ci 1637425bb815Sopenharmony_ci if (ecma_get_string_magic (literal_p) == LIT_MAGIC_STRING__COUNT) 1638425bb815Sopenharmony_ci { 1639425bb815Sopenharmony_ci literal_array[literal_idx++] = literal_p; 1640425bb815Sopenharmony_ci } 1641425bb815Sopenharmony_ci } 1642425bb815Sopenharmony_ci } 1643425bb815Sopenharmony_ci 1644425bb815Sopenharmony_ci ecma_collection_destroy (lit_pool_p); 1645425bb815Sopenharmony_ci 1646425bb815Sopenharmony_ci /* Sort the strings by size at first, then lexicographically. */ 1647425bb815Sopenharmony_ci jerry_save_literals_sort (literal_array, literal_count); 1648425bb815Sopenharmony_ci 1649425bb815Sopenharmony_ci if (is_c_format) 1650425bb815Sopenharmony_ci { 1651425bb815Sopenharmony_ci /* Save literal count. */ 1652425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, 1653425bb815Sopenharmony_ci buffer_end_p, 1654425bb815Sopenharmony_ci "jerry_length_t literal_count = ", 1655425bb815Sopenharmony_ci 0); 1656425bb815Sopenharmony_ci 1657425bb815Sopenharmony_ci lit_buf_p = jerry_append_number_to_buffer (lit_buf_p, buffer_end_p, literal_count); 1658425bb815Sopenharmony_ci 1659425bb815Sopenharmony_ci /* Save the array of literals. */ 1660425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, 1661425bb815Sopenharmony_ci buffer_end_p, 1662425bb815Sopenharmony_ci ";\n\njerry_char_t *literals[", 1663425bb815Sopenharmony_ci 0); 1664425bb815Sopenharmony_ci 1665425bb815Sopenharmony_ci lit_buf_p = jerry_append_number_to_buffer (lit_buf_p, buffer_end_p, literal_count); 1666425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, "] =\n{\n", 0); 1667425bb815Sopenharmony_ci 1668425bb815Sopenharmony_ci for (lit_utf8_size_t i = 0; i < literal_count; i++) 1669425bb815Sopenharmony_ci { 1670425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, " \"", 0); 1671425bb815Sopenharmony_ci ECMA_STRING_TO_UTF8_STRING (literal_array[i], str_buffer_p, str_buffer_size); 1672425bb815Sopenharmony_ci for (lit_utf8_size_t j = 0; j < str_buffer_size; j++) 1673425bb815Sopenharmony_ci { 1674425bb815Sopenharmony_ci uint8_t byte = str_buffer_p[j]; 1675425bb815Sopenharmony_ci if (byte < 32 || byte > 127) 1676425bb815Sopenharmony_ci { 1677425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, "\\x", 0); 1678425bb815Sopenharmony_ci ecma_char_t hex_digit = (ecma_char_t) (byte >> 4); 1679425bb815Sopenharmony_ci *lit_buf_p++ = (lit_utf8_byte_t) ((hex_digit > 9) ? (hex_digit + ('A' - 10)) : (hex_digit + '0')); 1680425bb815Sopenharmony_ci hex_digit = (lit_utf8_byte_t) (byte & 0xf); 1681425bb815Sopenharmony_ci *lit_buf_p++ = (lit_utf8_byte_t) ((hex_digit > 9) ? (hex_digit + ('A' - 10)) : (hex_digit + '0')); 1682425bb815Sopenharmony_ci } 1683425bb815Sopenharmony_ci else 1684425bb815Sopenharmony_ci { 1685425bb815Sopenharmony_ci if (byte == '\\' || byte == '"') 1686425bb815Sopenharmony_ci { 1687425bb815Sopenharmony_ci *lit_buf_p++ = '\\'; 1688425bb815Sopenharmony_ci } 1689425bb815Sopenharmony_ci *lit_buf_p++ = byte; 1690425bb815Sopenharmony_ci } 1691425bb815Sopenharmony_ci } 1692425bb815Sopenharmony_ci 1693425bb815Sopenharmony_ci ECMA_FINALIZE_UTF8_STRING (str_buffer_p, str_buffer_size); 1694425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, "\"", 0); 1695425bb815Sopenharmony_ci 1696425bb815Sopenharmony_ci if (i < literal_count - 1) 1697425bb815Sopenharmony_ci { 1698425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, ",", 0); 1699425bb815Sopenharmony_ci } 1700425bb815Sopenharmony_ci 1701425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, "\n", 0); 1702425bb815Sopenharmony_ci } 1703425bb815Sopenharmony_ci 1704425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, 1705425bb815Sopenharmony_ci buffer_end_p, 1706425bb815Sopenharmony_ci "};\n\njerry_length_t literal_sizes[", 1707425bb815Sopenharmony_ci 0); 1708425bb815Sopenharmony_ci 1709425bb815Sopenharmony_ci lit_buf_p = jerry_append_number_to_buffer (lit_buf_p, buffer_end_p, literal_count); 1710425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, "] =\n{\n", 0); 1711425bb815Sopenharmony_ci } 1712425bb815Sopenharmony_ci 1713425bb815Sopenharmony_ci /* Save the literal sizes respectively. */ 1714425bb815Sopenharmony_ci for (lit_utf8_size_t i = 0; i < literal_count; i++) 1715425bb815Sopenharmony_ci { 1716425bb815Sopenharmony_ci lit_utf8_size_t str_size = ecma_string_get_size (literal_array[i]); 1717425bb815Sopenharmony_ci 1718425bb815Sopenharmony_ci if (is_c_format) 1719425bb815Sopenharmony_ci { 1720425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, " ", 0); 1721425bb815Sopenharmony_ci } 1722425bb815Sopenharmony_ci 1723425bb815Sopenharmony_ci lit_buf_p = jerry_append_number_to_buffer (lit_buf_p, buffer_end_p, str_size); 1724425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, " ", 0); 1725425bb815Sopenharmony_ci 1726425bb815Sopenharmony_ci if (is_c_format) 1727425bb815Sopenharmony_ci { 1728425bb815Sopenharmony_ci /* Show the given string as a comment. */ 1729425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, "/* ", 0); 1730425bb815Sopenharmony_ci lit_buf_p = jerry_append_ecma_string_to_buffer (lit_buf_p, buffer_end_p, literal_array[i]); 1731425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, " */", 0); 1732425bb815Sopenharmony_ci 1733425bb815Sopenharmony_ci if (i < literal_count - 1) 1734425bb815Sopenharmony_ci { 1735425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, ",", 0); 1736425bb815Sopenharmony_ci } 1737425bb815Sopenharmony_ci } 1738425bb815Sopenharmony_ci else 1739425bb815Sopenharmony_ci { 1740425bb815Sopenharmony_ci lit_buf_p = jerry_append_ecma_string_to_buffer (lit_buf_p, buffer_end_p, literal_array[i]); 1741425bb815Sopenharmony_ci } 1742425bb815Sopenharmony_ci 1743425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, "\n", 0); 1744425bb815Sopenharmony_ci } 1745425bb815Sopenharmony_ci 1746425bb815Sopenharmony_ci if (is_c_format) 1747425bb815Sopenharmony_ci { 1748425bb815Sopenharmony_ci lit_buf_p = jerry_append_chars_to_buffer (lit_buf_p, buffer_end_p, "};\n", 0); 1749425bb815Sopenharmony_ci } 1750425bb815Sopenharmony_ci 1751425bb815Sopenharmony_ci JMEM_FINALIZE_LOCAL_ARRAY (literal_array); 1752425bb815Sopenharmony_ci 1753425bb815Sopenharmony_ci return lit_buf_p <= buffer_end_p ? (size_t) (lit_buf_p - buffer_start_p) : 0; 1754425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_SNAPSHOT_SAVE) */ 1755425bb815Sopenharmony_ci JERRY_UNUSED (snapshot_p); 1756425bb815Sopenharmony_ci JERRY_UNUSED (snapshot_size); 1757425bb815Sopenharmony_ci JERRY_UNUSED (lit_buf_p); 1758425bb815Sopenharmony_ci JERRY_UNUSED (lit_buf_size); 1759425bb815Sopenharmony_ci JERRY_UNUSED (is_c_format); 1760425bb815Sopenharmony_ci 1761425bb815Sopenharmony_ci return 0; 1762425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */ 1763425bb815Sopenharmony_ci} /* jerry_get_literals_from_snapshot */ 1764425bb815Sopenharmony_ci 1765425bb815Sopenharmony_ci/** 1766425bb815Sopenharmony_ci * Generate snapshot function from specified source and arguments 1767425bb815Sopenharmony_ci * 1768425bb815Sopenharmony_ci * @return size of snapshot (a number value), if it was generated succesfully 1769425bb815Sopenharmony_ci * (i.e. there are no syntax errors in source code, buffer size is sufficient, 1770425bb815Sopenharmony_ci * and snapshot support is enabled in current configuration through JERRY_SNAPSHOT_SAVE), 1771425bb815Sopenharmony_ci * error object otherwise 1772425bb815Sopenharmony_ci */ 1773425bb815Sopenharmony_cijerry_value_t 1774425bb815Sopenharmony_cijerry_generate_function_snapshot (const jerry_char_t *resource_name_p, /**< script resource name */ 1775425bb815Sopenharmony_ci size_t resource_name_length, /**< script resource name length */ 1776425bb815Sopenharmony_ci const jerry_char_t *source_p, /**< script source */ 1777425bb815Sopenharmony_ci size_t source_size, /**< script source size */ 1778425bb815Sopenharmony_ci const jerry_char_t *args_p, /**< arguments string */ 1779425bb815Sopenharmony_ci size_t args_size, /**< arguments string size */ 1780425bb815Sopenharmony_ci uint32_t generate_snapshot_opts, /**< jerry_generate_snapshot_opts_t option bits */ 1781425bb815Sopenharmony_ci uint32_t *buffer_p, /**< buffer to save snapshot to */ 1782425bb815Sopenharmony_ci size_t buffer_size) /**< the buffer's size */ 1783425bb815Sopenharmony_ci{ 1784425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_SAVE) 1785425bb815Sopenharmony_ci uint32_t allowed_opts = (JERRY_SNAPSHOT_SAVE_STATIC | JERRY_SNAPSHOT_SAVE_STRICT); 1786425bb815Sopenharmony_ci 1787425bb815Sopenharmony_ci if ((generate_snapshot_opts & ~(allowed_opts)) != 0) 1788425bb815Sopenharmony_ci { 1789425bb815Sopenharmony_ci const char * const error_message_p = "Unsupported generate snapshot flags specified."; 1790425bb815Sopenharmony_ci return jerry_create_error (JERRY_ERROR_RANGE, (const jerry_char_t *) error_message_p); 1791425bb815Sopenharmony_ci } 1792425bb815Sopenharmony_ci 1793425bb815Sopenharmony_ci return jerry_generate_snapshot_with_args (resource_name_p, 1794425bb815Sopenharmony_ci resource_name_length, 1795425bb815Sopenharmony_ci source_p, 1796425bb815Sopenharmony_ci source_size, 1797425bb815Sopenharmony_ci args_p, 1798425bb815Sopenharmony_ci args_size, 1799425bb815Sopenharmony_ci generate_snapshot_opts, 1800425bb815Sopenharmony_ci buffer_p, 1801425bb815Sopenharmony_ci buffer_size); 1802425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_SNAPSHOT_SAVE) */ 1803425bb815Sopenharmony_ci JERRY_UNUSED (resource_name_p); 1804425bb815Sopenharmony_ci JERRY_UNUSED (resource_name_length); 1805425bb815Sopenharmony_ci JERRY_UNUSED (source_p); 1806425bb815Sopenharmony_ci JERRY_UNUSED (source_size); 1807425bb815Sopenharmony_ci JERRY_UNUSED (args_p); 1808425bb815Sopenharmony_ci JERRY_UNUSED (args_size); 1809425bb815Sopenharmony_ci JERRY_UNUSED (generate_snapshot_opts); 1810425bb815Sopenharmony_ci JERRY_UNUSED (buffer_p); 1811425bb815Sopenharmony_ci JERRY_UNUSED (buffer_size); 1812425bb815Sopenharmony_ci 1813425bb815Sopenharmony_ci return jerry_create_error (JERRY_ERROR_COMMON, (const jerry_char_t *) "Snapshot save is not supported."); 1814425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */ 1815425bb815Sopenharmony_ci} /* jerry_generate_function_snapshot */ 1816425bb815Sopenharmony_ci 1817425bb815Sopenharmony_ci/** 1818425bb815Sopenharmony_ci * Load function from specified snapshot buffer 1819425bb815Sopenharmony_ci * 1820425bb815Sopenharmony_ci * Note: 1821425bb815Sopenharmony_ci * returned value must be freed with jerry_release_value, when it is no longer needed. 1822425bb815Sopenharmony_ci * 1823425bb815Sopenharmony_ci * @return result of bytecode - if run was successful 1824425bb815Sopenharmony_ci * thrown error - otherwise 1825425bb815Sopenharmony_ci */ 1826425bb815Sopenharmony_cijerry_value_t 1827425bb815Sopenharmony_cijerry_load_function_snapshot (const uint32_t *function_snapshot_p, /**< snapshot of the function(s) */ 1828425bb815Sopenharmony_ci const size_t function_snapshot_size, /**< size of the snapshot */ 1829425bb815Sopenharmony_ci size_t func_index, /**< index of the function to load */ 1830425bb815Sopenharmony_ci uint32_t exec_snapshot_opts) /**< jerry_exec_snapshot_opts_t option bits */ 1831425bb815Sopenharmony_ci{ 1832425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_EXEC) 1833425bb815Sopenharmony_ci return jerry_snapshot_result (function_snapshot_p, function_snapshot_size, func_index, exec_snapshot_opts, true); 1834425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_SNAPSHOT_EXEC) */ 1835425bb815Sopenharmony_ci JERRY_UNUSED (function_snapshot_p); 1836425bb815Sopenharmony_ci JERRY_UNUSED (function_snapshot_size); 1837425bb815Sopenharmony_ci JERRY_UNUSED (func_index); 1838425bb815Sopenharmony_ci JERRY_UNUSED (exec_snapshot_opts); 1839425bb815Sopenharmony_ci 1840425bb815Sopenharmony_ci return jerry_create_error (JERRY_ERROR_COMMON, (const jerry_char_t *) "Snapshot execution is not supported."); 1841425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */ 1842425bb815Sopenharmony_ci} /* jerry_load_function_snapshot */ 1843