/* Copyright 2015 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef LIT_LITERAL_STORAGE_H #define LIT_LITERAL_STORAGE_H #include "ecma-globals.h" #include "rcs-recordset.h" class lit_literal_storage_t; extern lit_literal_storage_t lit_storage; /** * Charset record * * layout: * ------- header ----------------------- * type (4 bits) * alignment (2 bits) * unused (2 bits) * hash (8 bits) * length (16 bits) * pointer to prev (16 bits) * ------- characters ------------------- * ... * chars * .... * ------- alignment bytes -------------- * unused bytes (their count is specified * by 'alignment' field in header) * -------------------------------------- */ class lit_charset_record_t : public rcs_record_t { friend class rcs_recordset_t; friend class lit_literal_storage_t; public: /** * Calculate the size that record will occupy inside the storage * * @return size of the record in bytes */ static size_t size (size_t size) /**< size of the charset buffer */ { return JERRY_ALIGNUP (size + header_size (), RCS_DYN_STORAGE_LENGTH_UNIT); } /* size */ /** * Get the size of the header part of the record * * @return size of the header in bytes */ static size_t header_size () { return _header_size; } /* header_size */ /** * Get the count of the alignment bytes at the end of record. * These bytes are needed to align the record to RCS_DYN_STORAGE_ALIGNMENT. * * @return alignment bytes count (the value of the 'alignment' field in the header) */ size_t get_alignment_bytes_count () const { return get_field (_alignment_field_pos, _alignment_field_width); } /* get_alignment_bytes_count */ /** * Set the count of the alignment bytes at the end of record (the value of the 'alignment' field in the header) */ void set_alignment_bytes_count (size_t count) /**< count of the alignment bytes */ { JERRY_ASSERT (count <= RCS_DYN_STORAGE_ALIGNMENT); set_field (_alignment_field_pos, _alignment_field_width, count); } /* set_alignment_bytes_count */ /** * Get hash value of the record's charset. * * @return hash value of the string (the value of the 'hash' field in the header) */ lit_string_hash_t get_hash () const { return (lit_string_hash_t) get_field (_hash_field_pos, _hash_field_width); } /* get_hash */ /** * Get the length of the string, which is contained inside the record * * @return length of the string (count of the ecma_char_t characters inside the charset) */ ecma_length_t get_length () const { return (ecma_length_t) ((get_size () - header_size () - get_alignment_bytes_count ()) / sizeof (ecma_char_t)); } /* get_length */ /** * Get the size of the record * * @return size of the record in bytes */ size_t get_size () const { return get_field (_length_field_pos, _length_field_width) * RCS_DYN_STORAGE_LENGTH_UNIT; } /* get_size */ rcs_record_t *get_prev () const; ecma_length_t get_charset (ecma_char_t *buff, size_t size); int compare_zt (const ecma_char_t *, size_t); bool equal (lit_charset_record_t *); bool equal_zt (const ecma_char_t *); bool equal_non_zt (const ecma_char_t *, ecma_length_t); private: /** * Set record's size (the value of the 'length' field in the header) */ void set_size (size_t size) /**< size in bytes */ { JERRY_ASSERT (JERRY_ALIGNUP (size, RCS_DYN_STORAGE_ALIGNMENT) == size); set_field (_length_field_pos, _length_field_width, size >> RCS_DYN_STORAGE_ALIGNMENT_LOG); } /* set_size */ /** * Set record's hash (the value of the 'hash' field in the header) */ void set_hash (lit_string_hash_t hash) /**< hash value */ { set_field (_hash_field_pos, _hash_field_width, hash); } /* set_hash */ void set_prev (rcs_record_t *); void set_charset (const ecma_char_t *, size_t); /** * Offset and length of 'alignment' field, in bits */ static const uint32_t _alignment_field_pos = _fields_offset_begin; static const uint32_t _alignment_field_width = 2u; /** * Offset and length of 'hash' field, in bits */ static const uint32_t _hash_field_pos = _alignment_field_pos + _alignment_field_width + 2u; static const uint32_t _hash_field_width = 8u; /** * Offset and length of 'alignment' field, in bits */ static const uint32_t _length_field_pos = _hash_field_pos + _hash_field_width; static const uint32_t _length_field_width = 16u; /** * Offset and length of 'prev' field, in bits */ static const uint32_t _prev_field_pos = _length_field_pos + _length_field_width; static const uint32_t _prev_field_width = rcs_cpointer_t::bit_field_width; static const size_t _header_size = RCS_DYN_STORAGE_LENGTH_UNIT + RCS_DYN_STORAGE_LENGTH_UNIT / 2; }; /* lit_charset_record_t */ /** * Magic string record * Doesn't hold any characters. Corresponding string is identified by its id. * * Layout: * ------- header ----------------------- * type (4 bits) * magic string id (12 bits) * pointer to prev (16 bits) * -------------------------------------- */ class lit_magic_record_t : public rcs_record_t { friend class rcs_recordset_t; friend class lit_literal_storage_t; public: /** * Calculate the size that record will occupy inside the storage * * @return size of the record in bytes */ static size_t size () { return _size; } /* size */ /** * Get the size of the header part of the record * * @return size of the header in bytes */ static size_t header_size () { return _size; } /* header_size */ /** * Get the size of the record * * @return size of the record in bytes */ size_t get_size () const { return _size; } /* get_size */ /** * Get magic string id which is held by the record * * @return magic string id */ template magic_string_id_t get_magic_str_id () const { uint32_t id = get_field (magic_field_pos, magic_field_width); // JERRY_ASSERT (id < LIT_MAGIC_STRING__COUNT); return (magic_string_id_t) id; } /* get_magic_str_id */ private: /** * Set record's size (the value of the 'length' field in the header) */ void set_size (size_t size) /**< size in bytes */ { JERRY_ASSERT (size == get_size ()); } /* set_size */ template void set_magic_str_id (magic_string_id_t id) { set_field (magic_field_pos, magic_field_width, id); } /* set_magic_str_id */ /** * Get previous record in the literal storage * * @return pointer to the previous record relative to this record, or NULL if this is the first record in the * storage */ rcs_record_t *get_prev () const { return get_pointer (prev_field_pos, prev_field_width); } /* get_prev */ /** * Set the pointer to the previous record inside the literal storage (sets 'prev' field in the header) */ void set_prev (rcs_record_t *prev_rec_p) { set_pointer (prev_field_pos, prev_field_width, prev_rec_p); } /* set_prev */ /** * Offset and length of 'magic string id' field, in bits */ static const uint32_t magic_field_pos = _fields_offset_begin; static const uint32_t magic_field_width = 12u; /** * Offset and length of 'prev' field, in bits */ static const uint32_t prev_field_pos = magic_field_pos + magic_field_width; static const uint32_t prev_field_width = rcs_cpointer_t::bit_field_width; static const size_t _size = RCS_DYN_STORAGE_LENGTH_UNIT; }; /* lit_magic_record_t */ /** * Number record * Doesn't hold any characters, holds a number. Numbers from source code are represented as number literals. * * Layout: * ------- header ----------------------- * type (4 bits) * magic string id (12 bits) * pointer to prev (16 bits) * -------------------------------------- */ class lit_number_record_t : public rcs_record_t { friend class rcs_recordset_t; friend class lit_literal_storage_t; public: static size_t size () { return _size; } /* size */ /** * Get the size of the header part of the record * * @return size of the header in bytes */ static size_t header_size () { return _header_size; } /* header_size */ /** * Get the size of the record * * @return size of the record in bytes */ size_t get_size () const { return _size; } /* get_size */ /** * Get previous record in the literal storage * * @return pointer to the previous record relative to this record, or NULL if this is the first record in the * storage */ rcs_record_t * get_prev () const { return get_pointer (prev_field_pos, prev_field_width); } /* get_prev */ /** * Set the pointer to the previous record inside the literal storage (sets 'prev' field in the header) */ void set_prev (rcs_record_t *prev_rec_p) { set_pointer (prev_field_pos, prev_field_width, prev_rec_p); } /* set_prev */ /** * Get the number which is held by the record * * @return number */ ecma_number_t get_number () const { rcs_record_iterator_t it ((rcs_recordset_t *)&lit_storage, (rcs_record_t *)this); it.skip (header_size ()); return it.read (); } /* get_number */ private: /** * Set record's size (the value of the 'length' field in the header) */ void set_size (size_t size) /**< size in bytes */ { JERRY_ASSERT (size == get_size ()); } /* set_size */ /** * Offset and length of 'prev' field, in bits */ static const uint32_t prev_field_pos = _fields_offset_begin + 12u; static const uint32_t prev_field_width = rcs_cpointer_t::bit_field_width; static const size_t _header_size = RCS_DYN_STORAGE_LENGTH_UNIT; static const size_t _size = _header_size + sizeof (ecma_number_t); }; /* lit_number_record_t */ /** * Literal storage * * Represents flexible storage for the literals. The following records could be created inside the storage: * - charset literal (lit_charset_record_t) * - magic string literal (lit_magic_record_t) * - number literal (lit_number_record_t) */ class lit_literal_storage_t : public rcs_recordset_t { public: enum { LIT_STR = _first_type_id, LIT_MAGIC_STR, LIT_MAGIC_STR_EX, LIT_NUMBER }; lit_charset_record_t *create_charset_record (const ecma_char_t *, size_t); lit_magic_record_t *create_magic_record (lit_magic_string_id_t); lit_magic_record_t *create_magic_record_ex (lit_magic_string_ex_id_t); lit_number_record_t *create_number_record (ecma_number_t); void dump (); private: virtual rcs_record_t *get_prev (rcs_record_t *); virtual void set_prev (rcs_record_t *, rcs_record_t *); virtual size_t get_record_size (rcs_record_t *); }; /* lit_literal_storage_t */ #define LIT_STR_T (lit_literal_storage_t::LIT_STR) #define LIT_MAGIC_STR_T (lit_literal_storage_t::LIT_MAGIC_STR) #define LIT_MAGIC_STR_EX_T (lit_literal_storage_t::LIT_MAGIC_STR_EX) #define LIT_NUMBER_T (lit_literal_storage_t::LIT_NUMBER) #endif /* LIT_LITERAL_STORAGE_H */