/** * Register bytecode and idx map from snapshot * * NOTE: * If is_copy flag is set, bytecode is copied from snapshot, else bytecode is referenced directly * from snapshot * * @return pointer to byte-code header, upon success, * NULL - upon failure (i.e., in case snapshot format is not valid) */ const bytecode_data_header_t * serializer_load_bytecode_with_idx_map (const uint8_t *bytecode_and_idx_map_p, /**< buffer with instructions array * and idx to literals map from * snapshot */ uint32_t bytecode_size, /**< size of instructions array */ uint32_t idx_to_lit_map_size, /**< size of the idx to literals map */ const lit_mem_to_snapshot_id_map_entry_t *lit_map_p, /**< map of in-snapshot * literal offsets * to literal identifiers, * created in literal * storage */ uint32_t literals_num, /**< number of literals */ bool is_copy) /** flag, indicating whether the passed in-snapshot data * should be copied to engine's memory (true), * or it can be referenced until engine is stopped * (i.e. until call to jerry_cleanup) */ { const uint8_t *idx_to_lit_map_p = bytecode_and_idx_map_p + bytecode_size; size_t instructions_number = bytecode_size / sizeof (vm_instr_t); size_t blocks_count = JERRY_ALIGNUP (instructions_number, BLOCK_SIZE) / BLOCK_SIZE; uint32_t idx_num_total; size_t idx_to_lit_map_offset = 0; if (!jrt_read_from_buffer_by_offset (idx_to_lit_map_p, idx_to_lit_map_size, &idx_to_lit_map_offset, &idx_num_total)) { return NULL; } const size_t bytecode_alloc_size = JERRY_ALIGNUP (bytecode_size, MEM_ALIGNMENT); const size_t hash_table_size = lit_id_hash_table_get_size_for_table (idx_num_total, blocks_count); const size_t header_and_hash_table_size = JERRY_ALIGNUP (sizeof (bytecode_data_header_t) + hash_table_size, MEM_ALIGNMENT); const size_t alloc_size = header_and_hash_table_size + (is_copy ? bytecode_alloc_size : 0); uint8_t *buffer_p = (uint8_t*) mem_heap_alloc_block (alloc_size, MEM_HEAP_ALLOC_LONG_TERM); bytecode_data_header_t *header_p = (bytecode_data_header_t *) buffer_p; vm_instr_t *instrs_p; vm_instr_t *snapshot_instrs_p = (vm_instr_t *) bytecode_and_idx_map_p; if (is_copy) { instrs_p = (vm_instr_t *) (buffer_p + header_and_hash_table_size); memcpy (instrs_p, snapshot_instrs_p, bytecode_size); } else { instrs_p = snapshot_instrs_p; } uint8_t *lit_id_hash_table_buffer_p = buffer_p + sizeof (bytecode_data_header_t); if (lit_id_hash_table_load_from_snapshot (blocks_count, idx_num_total, idx_to_lit_map_p + idx_to_lit_map_offset, idx_to_lit_map_size - idx_to_lit_map_offset, lit_map_p, literals_num, lit_id_hash_table_buffer_p, hash_table_size) && (vm_instr_counter_t) instructions_number == instructions_number) { MEM_CP_SET_NON_NULL_POINTER (header_p->lit_id_hash_cp, lit_id_hash_table_buffer_p); header_p->instrs_p = instrs_p; header_p->instrs_count = (vm_instr_counter_t) instructions_number; MEM_CP_SET_POINTER (header_p->next_header_cp, first_bytecode_header_p); first_bytecode_header_p = header_p; return header_p; } else { mem_heap_free_block (buffer_p); return NULL; } } /* serializer_load_bytecode_with_idx_map */
/** * Register bytecode and supplementary data of a single scope from snapshot * * NOTE: * If is_copy flag is set, bytecode is copied from snapshot, else bytecode is referenced directly * from snapshot * * @return pointer to byte-code header, upon success, * NULL - upon failure (i.e., in case snapshot format is not valid) */ static bytecode_data_header_t * bc_load_bytecode_with_idx_map (const uint8_t *snapshot_data_p, /**< buffer with instructions array * and idx to literals map from * snapshot */ size_t snapshot_size, /**< remaining size of snapshot */ const lit_mem_to_snapshot_id_map_entry_t *lit_map_p, /**< map of in-snapshot * literal offsets * to literal identifiers, * created in literal * storage */ uint32_t literals_num, /**< number of literals */ bool is_copy, /** flag, indicating whether the passed in-snapshot data * should be copied to engine's memory (true), * or it can be referenced until engine is stopped * (i.e. until call to jerry_cleanup) */ uint32_t *out_bytecode_data_size) /**< out: size occupied by bytecode data * in snapshot */ { size_t buffer_offset = 0; jerry_snapshot_bytecode_header_t bytecode_header; if (!jrt_read_from_buffer_by_offset (snapshot_data_p, snapshot_size, &buffer_offset, &bytecode_header, sizeof (bytecode_header))) { return NULL; } *out_bytecode_data_size = bytecode_header.size; buffer_offset += (JERRY_ALIGNUP (sizeof (jerry_snapshot_bytecode_header_t), MEM_ALIGNMENT) - sizeof (jerry_snapshot_bytecode_header_t)); JERRY_ASSERT (bytecode_header.size <= snapshot_size); /* Read uid->lit_cp hash table size */ const uint8_t *idx_to_lit_map_p = (snapshot_data_p + buffer_offset + + bytecode_header.instrs_size + bytecode_header.var_decls_count * sizeof (uint32_t)); size_t instructions_number = bytecode_header.instrs_size / sizeof (vm_instr_t); size_t blocks_count = JERRY_ALIGNUP (instructions_number, BLOCK_SIZE) / BLOCK_SIZE; uint32_t idx_num_total; size_t idx_to_lit_map_offset = 0; if (!jrt_read_from_buffer_by_offset (idx_to_lit_map_p, bytecode_header.idx_to_lit_map_size, &idx_to_lit_map_offset, &idx_num_total, sizeof (idx_num_total))) { return NULL; } /* Alloc bytecode_header for runtime */ const size_t bytecode_alloc_size = JERRY_ALIGNUP (bytecode_header.instrs_size, MEM_ALIGNMENT); const size_t hash_table_size = lit_id_hash_table_get_size_for_table (idx_num_total, blocks_count); const size_t declarations_area_size = JERRY_ALIGNUP (bytecode_header.func_scopes_count * sizeof (mem_cpointer_t) + bytecode_header.var_decls_count * sizeof (lit_cpointer_t), MEM_ALIGNMENT); const size_t header_and_tables_size = JERRY_ALIGNUP ((sizeof (bytecode_data_header_t) + hash_table_size + declarations_area_size), MEM_ALIGNMENT); const size_t alloc_size = header_and_tables_size + (is_copy ? bytecode_alloc_size : 0); uint8_t *buffer_p = (uint8_t*) mem_heap_alloc_block (alloc_size, MEM_HEAP_ALLOC_LONG_TERM); bytecode_data_header_t *header_p = (bytecode_data_header_t *) buffer_p; vm_instr_t *instrs_p; vm_instr_t *snapshot_instrs_p = (vm_instr_t *) (snapshot_data_p + buffer_offset); if (is_copy) { instrs_p = (vm_instr_t *) (buffer_p + header_and_tables_size); memcpy (instrs_p, snapshot_instrs_p, bytecode_header.instrs_size); } else { instrs_p = snapshot_instrs_p; } buffer_offset += bytecode_header.instrs_size; /* buffer_offset is now offset of variable declarations */ /* Read uid->lit_cp hash table */ uint8_t *lit_id_hash_table_buffer_p = buffer_p + sizeof (bytecode_data_header_t); if (!(lit_id_hash_table_load_from_snapshot (blocks_count, idx_num_total, idx_to_lit_map_p + idx_to_lit_map_offset, bytecode_header.idx_to_lit_map_size - idx_to_lit_map_offset, lit_map_p, literals_num, lit_id_hash_table_buffer_p, hash_table_size) && (vm_instr_counter_t) instructions_number == instructions_number)) { mem_heap_free_block (buffer_p); return NULL; } /* Fill with NULLs child scopes declarations for this scope */ mem_cpointer_t *declarations_p = (mem_cpointer_t *) (buffer_p + sizeof (bytecode_data_header_t) + hash_table_size); memset (declarations_p, 0, bytecode_header.func_scopes_count * sizeof (mem_cpointer_t)); /* Read variable declarations for this scope */ lit_cpointer_t *var_decls_p = (lit_cpointer_t *) (declarations_p + bytecode_header.func_scopes_count); for (uint32_t i = 0; i < bytecode_header.var_decls_count; i++) { uint32_t lit_offset_from_snapshot; if (!jrt_read_from_buffer_by_offset (snapshot_data_p, buffer_offset + bytecode_header.var_decls_count * sizeof (uint32_t), &buffer_offset, &lit_offset_from_snapshot, sizeof (lit_offset_from_snapshot))) { mem_heap_free_block (buffer_p); return NULL; } /** * TODO: implement binary search here */ lit_cpointer_t lit_cp = NOT_A_LITERAL; uint32_t j; for (j = 0; j < literals_num; j++) { if (lit_map_p[j].literal_offset == lit_offset_from_snapshot) { lit_cp.packed_value = lit_map_p[j].literal_id.packed_value; break; } } if (j == literals_num) { mem_heap_free_block (buffer_p); return NULL; } var_decls_p[i] = lit_cp; } /* Fill bytecode_data_header */ bc_fill_bytecode_data_header (header_p, (lit_id_hash_table *) lit_id_hash_table_buffer_p, instrs_p, declarations_p, (uint16_t) bytecode_header.func_scopes_count, (uint16_t) bytecode_header.var_decls_count, bytecode_header.is_strict, bytecode_header.is_ref_arguments_identifier, bytecode_header.is_ref_eval_identifier, bytecode_header.is_args_moved_to_regs, bytecode_header.is_args_moved_to_regs, bytecode_header.is_no_lex_env); return header_p; } /* bc_load_bytecode_with_idx_map */