1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2013, 2014 Damien P. George
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  */
26 
27 #include <assert.h>
28 #include <string.h>
29 #include <stdio.h>
30 
31 #include "py/mpstate.h"
32 #include "py/qstr.h"
33 #include "py/gc.h"
34 #include "py/runtime.h"
35 
36 // NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings)
37 // ultimately we will replace this with a static hash table of some kind
38 // also probably need to include the length in the string data, to allow null bytes in the string
39 
40 #if MICROPY_DEBUG_VERBOSE // print debugging info
41 #define DEBUG_printf DEBUG_printf
42 #else // don't print debugging info
43 #define DEBUG_printf(...) (void)0
44 #endif
45 
46 // A qstr is an index into the qstr pool.
47 // The data for a qstr contains (hash, length, data):
48 //  - hash (configurable number of bytes)
49 //  - length (configurable number of bytes)
50 //  - data ("length" number of bytes)
51 //  - \0 terminated (so they can be printed using printf)
52 
53 #if MICROPY_QSTR_BYTES_IN_HASH == 1
54     #define Q_HASH_MASK (0xff)
55     #define Q_GET_HASH(q) ((mp_uint_t)(q)[0])
56     #define Q_SET_HASH(q, hash) do { (q)[0] = (hash); } while (0)
57 #elif MICROPY_QSTR_BYTES_IN_HASH == 2
58     #define Q_HASH_MASK (0xffff)
59     #define Q_GET_HASH(q) ((mp_uint_t)(q)[0] | ((mp_uint_t)(q)[1] << 8))
60     #define Q_SET_HASH(q, hash) do { (q)[0] = (hash); (q)[1] = (hash) >> 8; } while (0)
61 #else
62     #error unimplemented qstr hash decoding
63 #endif
64 #define Q_GET_ALLOC(q)  (MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + Q_GET_LENGTH(q) + 1)
65 #define Q_GET_DATA(q)   ((q) + MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN)
66 #if MICROPY_QSTR_BYTES_IN_LEN == 1
67     #define Q_GET_LENGTH(q) ((q)[MICROPY_QSTR_BYTES_IN_HASH])
68     #define Q_SET_LENGTH(q, len) do { (q)[MICROPY_QSTR_BYTES_IN_HASH] = (len); } while (0)
69 #elif MICROPY_QSTR_BYTES_IN_LEN == 2
70     #define Q_GET_LENGTH(q) ((q)[MICROPY_QSTR_BYTES_IN_HASH] | ((q)[MICROPY_QSTR_BYTES_IN_HASH + 1] << 8))
71     #define Q_SET_LENGTH(q, len) do { (q)[MICROPY_QSTR_BYTES_IN_HASH] = (len); (q)[MICROPY_QSTR_BYTES_IN_HASH + 1] = (len) >> 8; } while (0)
72 #else
73     #error unimplemented qstr length decoding
74 #endif
75 
76 #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL
77 #define QSTR_ENTER() mp_thread_mutex_lock(&MP_STATE_VM(qstr_mutex), 1)
78 #define QSTR_EXIT() mp_thread_mutex_unlock(&MP_STATE_VM(qstr_mutex))
79 #else
80 #define QSTR_ENTER()
81 #define QSTR_EXIT()
82 #endif
83 
84 // Initial number of entries for qstr pool, set so that the first dynamically
85 // allocated pool is twice this size.  The value here must be <= MP_QSTRnumber_of.
86 #define MICROPY_ALLOC_QSTR_ENTRIES_INIT (10)
87 
88 // this must match the equivalent function in makeqstrdata.py
qstr_compute_hash(const byte * data,size_t len)89 mp_uint_t qstr_compute_hash(const byte *data, size_t len) {
90     // djb2 algorithm; see http://www.cse.yorku.ca/~oz/hash.html
91     mp_uint_t hash = 5381;
92     for (const byte *top = data + len; data < top; data++) {
93         hash = ((hash << 5) + hash) ^ (*data); // hash * 33 ^ data
94     }
95     hash &= Q_HASH_MASK;
96     // Make sure that valid hash is never zero, zero means "hash not computed"
97     if (hash == 0) {
98         hash++;
99     }
100     return hash;
101 }
102 
103 const qstr_pool_t mp_qstr_const_pool = {
104     NULL,               // no previous pool
105     0,                  // no previous pool
106     MICROPY_ALLOC_QSTR_ENTRIES_INIT,
107     MP_QSTRnumber_of,   // corresponds to number of strings in array just below
108     {
109         #ifndef NO_QSTR
110 #define QDEF(id, str) str,
111         #include "genhdr/qstrdefs.generated.h"
112 #undef QDEF
113         #endif
114     },
115 };
116 
117 #ifdef MICROPY_QSTR_EXTRA_POOL
118 extern const qstr_pool_t MICROPY_QSTR_EXTRA_POOL;
119 #define CONST_POOL MICROPY_QSTR_EXTRA_POOL
120 #else
121 #define CONST_POOL mp_qstr_const_pool
122 #endif
123 
qstr_init(void)124 void qstr_init(void) {
125     MP_STATE_VM(last_pool) = (qstr_pool_t *)&CONST_POOL; // we won't modify the const_pool since it has no allocated room left
126     MP_STATE_VM(qstr_last_chunk) = NULL;
127 
128     #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL
129     mp_thread_mutex_init(&MP_STATE_VM(qstr_mutex));
130     #endif
131 }
132 
find_qstr(qstr q)133 STATIC const byte *find_qstr(qstr q) {
134     // search pool for this qstr
135     // total_prev_len==0 in the final pool, so the loop will always terminate
136     qstr_pool_t *pool = MP_STATE_VM(last_pool);
137     while (q < pool->total_prev_len) {
138         pool = pool->prev;
139     }
140     return pool->qstrs[q - pool->total_prev_len];
141 }
142 
143 // qstr_mutex must be taken while in this function
qstr_add(const byte * q_ptr)144 STATIC qstr qstr_add(const byte *q_ptr) {
145     DEBUG_printf("QSTR: add hash=%d len=%d data=%.*s\n", Q_GET_HASH(q_ptr), Q_GET_LENGTH(q_ptr), Q_GET_LENGTH(q_ptr), Q_GET_DATA(q_ptr));
146 
147     // make sure we have room in the pool for a new qstr
148     if (MP_STATE_VM(last_pool)->len >= MP_STATE_VM(last_pool)->alloc) {
149         size_t new_alloc = MP_STATE_VM(last_pool)->alloc * 2;
150         #ifdef MICROPY_QSTR_EXTRA_POOL
151         // Put a lower bound on the allocation size in case the extra qstr pool has few entries
152         new_alloc = MAX(MICROPY_ALLOC_QSTR_ENTRIES_INIT, new_alloc);
153         #endif
154         qstr_pool_t *pool = m_new_obj_var_maybe(qstr_pool_t, const char *, new_alloc);
155         if (pool == NULL) {
156             QSTR_EXIT();
157             m_malloc_fail(new_alloc);
158         }
159         pool->prev = MP_STATE_VM(last_pool);
160         pool->total_prev_len = MP_STATE_VM(last_pool)->total_prev_len + MP_STATE_VM(last_pool)->len;
161         pool->alloc = new_alloc;
162         pool->len = 0;
163         MP_STATE_VM(last_pool) = pool;
164         DEBUG_printf("QSTR: allocate new pool of size %d\n", MP_STATE_VM(last_pool)->alloc);
165     }
166 
167     // add the new qstr
168     MP_STATE_VM(last_pool)->qstrs[MP_STATE_VM(last_pool)->len++] = q_ptr;
169 
170     // return id for the newly-added qstr
171     return MP_STATE_VM(last_pool)->total_prev_len + MP_STATE_VM(last_pool)->len - 1;
172 }
173 
qstr_find_strn(const char * str,size_t str_len)174 qstr qstr_find_strn(const char *str, size_t str_len) {
175     // work out hash of str
176     mp_uint_t str_hash = qstr_compute_hash((const byte *)str, str_len);
177 
178     // search pools for the data
179     for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL; pool = pool->prev) {
180         for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) {
181             if (Q_GET_HASH(*q) == str_hash && Q_GET_LENGTH(*q) == str_len && memcmp(Q_GET_DATA(*q), str, str_len) == 0) {
182                 return pool->total_prev_len + (q - pool->qstrs);
183             }
184         }
185     }
186 
187     // not found; return null qstr
188     return 0;
189 }
190 
qstr_from_str(const char * str)191 qstr qstr_from_str(const char *str) {
192     return qstr_from_strn(str, strlen(str));
193 }
194 
qstr_from_strn(const char * str,size_t len)195 qstr qstr_from_strn(const char *str, size_t len) {
196     QSTR_ENTER();
197     qstr q = qstr_find_strn(str, len);
198     if (q == 0) {
199         // qstr does not exist in interned pool so need to add it
200 
201         // check that len is not too big
202         if (len >= (1 << (8 * MICROPY_QSTR_BYTES_IN_LEN))) {
203             QSTR_EXIT();
204             mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("name too long"));
205         }
206 
207         // compute number of bytes needed to intern this string
208         size_t n_bytes = MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len + 1;
209 
210         if (MP_STATE_VM(qstr_last_chunk) != NULL && MP_STATE_VM(qstr_last_used) + n_bytes > MP_STATE_VM(qstr_last_alloc)) {
211             // not enough room at end of previously interned string so try to grow
212             byte *new_p = m_renew_maybe(byte, MP_STATE_VM(qstr_last_chunk), MP_STATE_VM(qstr_last_alloc), MP_STATE_VM(qstr_last_alloc) + n_bytes, false);
213             if (new_p == NULL) {
214                 // could not grow existing memory; shrink it to fit previous
215                 (void)m_renew_maybe(byte, MP_STATE_VM(qstr_last_chunk), MP_STATE_VM(qstr_last_alloc), MP_STATE_VM(qstr_last_used), false);
216                 MP_STATE_VM(qstr_last_chunk) = NULL;
217             } else {
218                 // could grow existing memory
219                 MP_STATE_VM(qstr_last_alloc) += n_bytes;
220             }
221         }
222 
223         if (MP_STATE_VM(qstr_last_chunk) == NULL) {
224             // no existing memory for the interned string so allocate a new chunk
225             size_t al = n_bytes;
226             if (al < MICROPY_ALLOC_QSTR_CHUNK_INIT) {
227                 al = MICROPY_ALLOC_QSTR_CHUNK_INIT;
228             }
229             MP_STATE_VM(qstr_last_chunk) = m_new_maybe(byte, al);
230             if (MP_STATE_VM(qstr_last_chunk) == NULL) {
231                 // failed to allocate a large chunk so try with exact size
232                 MP_STATE_VM(qstr_last_chunk) = m_new_maybe(byte, n_bytes);
233                 if (MP_STATE_VM(qstr_last_chunk) == NULL) {
234                     QSTR_EXIT();
235                     m_malloc_fail(n_bytes);
236                 }
237                 al = n_bytes;
238             }
239             MP_STATE_VM(qstr_last_alloc) = al;
240             MP_STATE_VM(qstr_last_used) = 0;
241         }
242 
243         // allocate memory from the chunk for this new interned string's data
244         byte *q_ptr = MP_STATE_VM(qstr_last_chunk) + MP_STATE_VM(qstr_last_used);
245         MP_STATE_VM(qstr_last_used) += n_bytes;
246 
247         // store the interned strings' data
248         mp_uint_t hash = qstr_compute_hash((const byte *)str, len);
249         Q_SET_HASH(q_ptr, hash);
250         Q_SET_LENGTH(q_ptr, len);
251         memcpy(q_ptr + MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN, str, len);
252         q_ptr[MICROPY_QSTR_BYTES_IN_HASH + MICROPY_QSTR_BYTES_IN_LEN + len] = '\0';
253         q = qstr_add(q_ptr);
254     }
255     QSTR_EXIT();
256     return q;
257 }
258 
qstr_hash(qstr q)259 mp_uint_t qstr_hash(qstr q) {
260     const byte *qd = find_qstr(q);
261     return Q_GET_HASH(qd);
262 }
263 
qstr_len(qstr q)264 size_t qstr_len(qstr q) {
265     const byte *qd = find_qstr(q);
266     return Q_GET_LENGTH(qd);
267 }
268 
qstr_str(qstr q)269 const char *qstr_str(qstr q) {
270     const byte *qd = find_qstr(q);
271     return (const char *)Q_GET_DATA(qd);
272 }
273 
qstr_data(qstr q,size_t * len)274 const byte *qstr_data(qstr q, size_t *len) {
275     const byte *qd = find_qstr(q);
276     *len = Q_GET_LENGTH(qd);
277     return Q_GET_DATA(qd);
278 }
279 
qstr_pool_info(size_t * n_pool,size_t * n_qstr,size_t * n_str_data_bytes,size_t * n_total_bytes)280 void qstr_pool_info(size_t *n_pool, size_t *n_qstr, size_t *n_str_data_bytes, size_t *n_total_bytes) {
281     QSTR_ENTER();
282     *n_pool = 0;
283     *n_qstr = 0;
284     *n_str_data_bytes = 0;
285     *n_total_bytes = 0;
286     for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL && pool != &CONST_POOL; pool = pool->prev) {
287         *n_pool += 1;
288         *n_qstr += pool->len;
289         for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) {
290             *n_str_data_bytes += Q_GET_ALLOC(*q);
291         }
292         #if MICROPY_ENABLE_GC
293         *n_total_bytes += gc_nbytes(pool); // this counts actual bytes used in heap
294         #else
295         *n_total_bytes += sizeof(qstr_pool_t) + sizeof(qstr) * pool->alloc;
296         #endif
297     }
298     *n_total_bytes += *n_str_data_bytes;
299     QSTR_EXIT();
300 }
301 
302 #if MICROPY_PY_MICROPYTHON_MEM_INFO
qstr_dump_data(void)303 void qstr_dump_data(void) {
304     QSTR_ENTER();
305     for (qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL && pool != &CONST_POOL; pool = pool->prev) {
306         for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) {
307             mp_printf(&mp_plat_print, "Q(%s)\n", Q_GET_DATA(*q));
308         }
309     }
310     QSTR_EXIT();
311 }
312 #endif
313 
314 #if MICROPY_ROM_TEXT_COMPRESSION
315 
316 #ifdef NO_QSTR
317 
318 // If NO_QSTR is set, it means we're doing QSTR extraction.
319 // So we won't yet have "genhdr/compressed.data.h"
320 
321 #else
322 
323 // Emit the compressed_string_data string.
324 #define MP_COMPRESSED_DATA(x) STATIC const char *compressed_string_data = x;
325 #define MP_MATCH_COMPRESSED(a, b)
326 #include "genhdr/compressed.data.h"
327 #undef MP_COMPRESSED_DATA
328 #undef MP_MATCH_COMPRESSED
329 
330 #endif // NO_QSTR
331 
332 // This implements the "common word" compression scheme (see makecompresseddata.py) where the most
333 // common 128 words in error messages are replaced by their index into the list of common words.
334 
335 // The compressed string data is delimited by setting high bit in the final char of each word.
336 // e.g. aaaa<0x80|a>bbbbbb<0x80|b>....
337 // This method finds the n'th string.
find_uncompressed_string(uint8_t n)338 STATIC const byte *find_uncompressed_string(uint8_t n) {
339     const byte *c = (byte *)compressed_string_data;
340     while (n > 0) {
341         while ((*c & 0x80) == 0) {
342             ++c;
343         }
344         ++c;
345         --n;
346     }
347     return c;
348 }
349 
350 // Given a compressed string in src, decompresses it into dst.
351 // dst must be large enough (use MP_MAX_UNCOMPRESSED_TEXT_LEN+1).
mp_decompress_rom_string(byte * dst,const mp_rom_error_text_t src_chr)352 void mp_decompress_rom_string(byte *dst, const mp_rom_error_text_t src_chr) {
353     // Skip past the 0xff marker.
354     const byte *src = (byte *)src_chr + 1;
355     // Need to add spaces around compressed words, except for the first (i.e. transition from 1<->2).
356     // 0 = start, 1 = compressed, 2 = regular.
357     int state = 0;
358     while (*src) {
359         if ((byte) * src >= 128) {
360             if (state != 0) {
361                 *dst++ = ' ';
362             }
363             state = 1;
364 
365             // High bit set, replace with common word.
366             const byte *word = find_uncompressed_string(*src & 0x7f);
367             // The word is terminated by the final char having its high bit set.
368             while ((*word & 0x80) == 0) {
369                 *dst++ = *word++;
370             }
371             *dst++ = (*word & 0x7f);
372         } else {
373             // Otherwise just copy one char.
374             if (state == 1) {
375                 *dst++ = ' ';
376             }
377             state = 2;
378 
379             *dst++ = *src;
380         }
381         ++src;
382     }
383     // Add null-terminator.
384     *dst = 0;
385 }
386 
387 #endif // MICROPY_ROM_TEXT_COMPRESSION
388