/** * Find an existing number literal which contains the passed number * * @return pointer to existing or null */ lit_literal_t lit_find_literal_by_num (const ecma_number_t num) /**< a number to search for */ { lit_literal_t lit; for (lit = lit_storage; lit != NULL; lit = lit_cpointer_decompress (lit->next)) { const lit_record_type_t type = (lit_record_type_t) lit->type; if (type != LIT_RECORD_TYPE_NUMBER) { continue; } const ecma_number_t lit_num = lit_number_literal_get_number (lit); if (lit_num == num) { return lit; } } return NULL; } /* lit_find_literal_by_num */
/** * Free stored literal * * @return pointer to the next literal in the list */ lit_record_t * lit_free_literal (lit_record_t *lit_p) /**< literal record */ { lit_record_t *const ret_p = lit_cpointer_decompress (lit_p->next); mem_heap_free_block (lit_p, lit_get_literal_size (lit_p)); return ret_p; } /* lit_free_literal */
/** * Convert compressed pointer to literal * * @return literal */ lit_literal_t lit_get_literal_by_cp (lit_cpointer_t lit_cp) /**< compressed pointer to literal */ { lit_literal_t lit = lit_cpointer_decompress (lit_cp); JERRY_ASSERT (lit_literal_exists (lit)); return lit; } /* lit_get_literal_by_cp */
/** * Check if literal really exists in the storage * * @return true if literal exists in the storage * false otherwise */ static bool lit_literal_exists (lit_literal_t lit) /**< literal to check for existence */ { lit_literal_t current_lit; for (current_lit = lit_storage; current_lit != NULL; current_lit = lit_cpointer_decompress (current_lit->next)) { if (current_lit == lit) { return true; } } return false; } /* lit_literal_exists */
/** * Count literal records in the storage * * @return number of literals */ uint32_t lit_count_literals () { uint32_t num = 0; lit_record_t *rec_p; for (rec_p = lit_storage; rec_p != NULL; rec_p = lit_cpointer_decompress (rec_p->next)) { if (rec_p->type > LIT_RECORD_TYPE_FREE) { num++; } } return num; } /* lit_count_literals */
/** * Find a literal in literal storage. * Only charset and magic string records are checked during search. * * @return pointer to a literal or NULL if no corresponding literal exists */ lit_literal_t lit_find_literal_by_utf8_string (const lit_utf8_byte_t *str_p, /**< a string to search for */ lit_utf8_size_t str_size) /**< length of the string */ { JERRY_ASSERT (str_p || !str_size); lit_string_hash_t str_hash = lit_utf8_string_calc_hash (str_p, str_size); lit_literal_t lit; for (lit = lit_storage; lit != NULL; lit = lit_cpointer_decompress (lit->next)) { const lit_record_type_t type = (lit_record_type_t) lit->type; switch (type) { case LIT_RECORD_TYPE_CHARSET: { const lit_charset_record_t *const rec_p = (const lit_charset_record_t *) lit; if (rec_p->hash != str_hash) { continue; } if (rec_p->size != str_size) { continue; } if (!strncmp ((const char *) (rec_p + 1), (const char *) str_p, str_size)) { return lit; } break; } case LIT_RECORD_TYPE_MAGIC_STR: { lit_magic_string_id_t magic_id = (lit_magic_string_id_t) ((lit_magic_record_t *) lit)->magic_id; const lit_utf8_byte_t *magic_str_p = lit_get_magic_string_utf8 (magic_id); if (lit_get_magic_string_size (magic_id) != str_size) { continue; } if (!strncmp ((const char *) magic_str_p, (const char *) str_p, str_size)) { return lit; } break; } case LIT_RECORD_TYPE_MAGIC_STR_EX: { lit_magic_string_ex_id_t magic_id = ((lit_magic_record_t *) lit)->magic_id; const lit_utf8_byte_t *magic_str_p = lit_get_magic_string_ex_utf8 (magic_id); if (lit_get_magic_string_ex_size (magic_id) != str_size) { continue; } if (!strncmp ((const char *) magic_str_p, (const char *) str_p, str_size)) { return lit; } break; } default: { JERRY_ASSERT (type == LIT_RECORD_TYPE_NUMBER); break; } } } return NULL; } /* lit_find_literal_by_utf8_string */
/** * Dump the contents of the literal storage. */ void lit_dump_literals () { lit_record_t *rec_p; size_t i; JERRY_DLOG ("LITERALS:\n"); for (rec_p = lit_storage; rec_p != NULL; rec_p = lit_cpointer_decompress (rec_p->next)) { JERRY_DLOG ("%p ", rec_p); JERRY_DLOG ("[%3zu] ", lit_get_literal_size (rec_p)); switch (rec_p->type) { case LIT_RECORD_TYPE_CHARSET: { const lit_charset_record_t *const record_p = (const lit_charset_record_t *) rec_p; char *str = (char *) (record_p + 1); for (i = 0; i < record_p->size; ++i, ++str) { /* TODO: Support proper printing of characters which occupy more than one byte. */ JERRY_DLOG ("%c", *str); } JERRY_DLOG (" : STRING"); break; } case LIT_RECORD_TYPE_MAGIC_STR: { lit_magic_string_id_t id = (lit_magic_string_id_t) ((lit_magic_record_t *) rec_p)->magic_id; JERRY_DLOG ("%s : MAGIC STRING", lit_get_magic_string_utf8 (id)); JERRY_DLOG (" [id=%d] ", id); break; } case LIT_RECORD_TYPE_MAGIC_STR_EX: { lit_magic_string_ex_id_t id = ((lit_magic_record_t *) rec_p)->magic_id; JERRY_DLOG ("%s : EXT MAGIC STRING", lit_get_magic_string_ex_utf8 (id)); JERRY_DLOG (" [id=%d] ", id); break; } case LIT_RECORD_TYPE_NUMBER: { const lit_number_record_t *const record_p = (const lit_number_record_t *) rec_p; ecma_number_t value; memcpy (&value, &record_p->number, sizeof (ecma_number_t)); if (ecma_number_is_nan (value)) { JERRY_DLOG ("%s : NUMBER", "NaN"); } else { lit_utf8_byte_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER + 1u]; memset (buff, 0, sizeof (buff)); lit_utf8_size_t sz = ecma_number_to_utf8_string (value, buff, sizeof (buff)); JERRY_ASSERT (sz <= ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER); JERRY_DLOG ("%s : NUMBER", buff); } break; } default: { JERRY_UNREACHABLE (); } } JERRY_DLOG ("\n"); } } /* lit_dump_literals */